leongersen / noUiSlider

noUiSlider is a lightweight, ARIA-accessible JavaScript range slider with multi-touch and keyboard support. It is fully GPU animated: no reflows, so it is fast; even on older devices. It also fits wonderfully in responsive designs and has no dependencies.
https://refreshless.com/nouislider/
MIT License
5.67k stars 659 forks source link

Don't block scrolling when the direction is perpendicular to the slider #788

Open oodavid opened 7 years ago

oodavid commented 7 years ago

Issue

Touch scrolling is prevented when the initial touchpoint is on a noUiSlider:

Proposal

  1. Store the touchstart coordinates
  2. Wait till the touchmove is a set distance away from touchstart - maybe 3vh, or some configurable value
  3. If the direction is perpendicular to the component, stop blocking the scroll event until touchend

Alternatively, on step 3, you could start blocking the scroll event if parallel to the component

Tap and Slide

oodavid commented 7 years ago

267

leongersen commented 7 years ago

Excellent report: I'll look into it.

oodavid commented 7 years ago

Happy to contribute.

I started going through the sources and found that preventDefault is triggered as part of a general event utility method here:

https://github.com/leongersen/noUiSlider/blob/58525cb9272dd15d424ca78148722a470145e790/src/js/scope_helpers.js#L64

I didn't fancy messing with that before seeing how it would affect the rest of the library.

leongersen commented 7 years ago

785 means getting rid of most calls to preventDefault anyway. Would you be willing to help with testing?

oodavid commented 7 years ago

Absolutely 👍

leongersen commented 7 years ago

Great! The dev branch has the changes, in this commit. Fixing #785 solves this issue from Chrome (desktop + mobile), Firefox and Edge, but not for iOS Safari, as that doesn't support touch-action: none.

Other browsers have the heuristics do separate a touchstart from a scroll intent for elements with touch-action: none, but as noUiSlider needs to act (by means of preventDefault) on the touchstart event, I don't really see a way to fix this for iOS.

MathieuDR commented 6 years ago

I'm unsure but is this still under development?

leongersen commented 6 years ago

I've been out of the loop for a little while, so I'll have to do some reading up on the recent changes browsers have been making. I know the Chrome team recently made some changes in this area. I'll add some details here.

leongersen commented 6 years ago

noUiSlider currently uses touch-action: none to guarantee the page doesn't scroll when using a slider. You could change that to touch-action: pan-up pan-down (etc.) for horizontal sliders, with left/right for vertical. That's not a change I think is smart: any touches near the slider shouldn't be at risk of glitchy behaviour, such a page scroll. Safari doesn't support these properties anyway, so the benefit is small.

japhex commented 6 years ago

Completely appreciate the amount of effort that has gone into this, its the first thing I've come across when testing this on mobile with a scrollable page. Its SUCH a shame because everything about this slider is perfect and I desperately want to use it..!

Has anybody managed to even hack their way around this to make the sliders not react on vertical scrolling? The only thing I can think of doing is blocking the slider until a user interacts with it, but I don't really want to do.

japhex commented 6 years ago

Is one way of looking at this to detect the scroll direction on the start event and if its vertical (not horizontal) adding a disabled property and disabling the slider until scrolled (and the end event is fired) and then remove it again?

Noticed here:

https://refreshless.com/nouislider/more/

If I disable the slider, then I can scroll past it happily. Just wondered if you guys think this could work.

lukaskabrt commented 5 years ago

Solution that works for me: