I have created a custom Slider component that works perfectly except for one issue.
If it is present in a modal, then the mouseUp
event for it fires on it for all events below it (z-index-wise) before on the element itself.
This is because to have a nice slider you need to attach the mouseMove
and mouseUp
events to the document instead of the slider itself so that you can still move the thumb and capture mouse up events even when the mouse moves off the slider while sliding the thumb.
As a result, I am now having issues where the mouseUp
event causes the click events for elements below it to run before the slider element. This causes issues like buttons below it clicking and the modal closing (since these are both click events).
A potential solution is to just add checks to all the potential event handlers that might be intercepted (something like if (thisModalOpened) { return false; }
to all the various other elements), but that solution seems a bit messy.
Is there any better way? A way to invert the bubbling order seems like it could work, because then I could just call stopPropagation
in the mouseUp
for the Slider component. However, I'm not sure if that can be done, because currently the event listener is registered in the document so that it can be detected outside of the element itself.
Some code snippets:
componentDidMount() {
document.addEventListener("pointermove", this.onThumbMove, false);
document.addEventListener("pointerup", this.onThumbUp, false);
}
onThumbDown = e => {
this.setState({ dragging: true, startX: this.getX(e) });
}
onThumbMove = e => {
if (this.state.dragging) {
this.setState({ position: e.clientX });
}
}
onThumbUp = e => {
if (this.state.dragging) {
let value = this.getValue();
this.setState({ dragging: false }, () =>
this.props.onSubmit(value);
});
}
}
<div onPointerDown={this.onThumbDown} ref={this.sliderRef}>
<div>+</div>
</div>