New issue
Advanced search Search tips

Issue 797870 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner:
Closed: Jan 2018
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug



Sign in to add a comment

event.preventDefault() doesn't seem to work with (touch-generated) pointermove events

Reported by bobbitdi...@gmail.com, Dec 28 2017

Issue description

UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0

Steps to reproduce the problem:
1. add an event handler for onpointermove
2. Do a drag with your finger to trigger a touch-generated pointermove event  (not a long press - just start and then drag outside the "slop region")
3. in the handler, call event.defaultPrevent() and return false (Note that I don't do this in all situations - sometimes I want the native drag behavior)

What is the expected behavior?
This should prevent Chrome from canceling the drag and triggering a pointercancel event.

What went wrong?
A pointercancel event is sent, canceling the drag

Did this work before? N/A 

Does this work in other browsers? N/A

Chrome version: 63.0.3239.84 (Official Build) (64-bit)  Channel: stable
OS Version: 10
Flash Version: Shockwave Flash 28.0 r0

The bug is avoided if I instead listen for touch events rather than pointer events, and call event.preventDefault() on the touchmove event.  It seems that the pointermove event is perhaps "fake" and only the "real" touchmove event will respond to preventDefault()

So, presumably, since the preventDefault() on the pointermove is ignored, Chrome thinks the native drag behavior needs to run, and thus sends the pointercancel.  Note that if I don't call preventDefault on the touchmove when listening for touch events, I get a similar unwanted touchcancel.

Finally, I'm aware of the CSS property `touch-action:none' but I don't want to use it hare, as that blocks native touch scroll ALL the time.  In my code, I call preventDefault() only in some situations.

Repro code (written by someone else):
https://jsfiddle.net/DiV666/f542bxbt/
Note that you can add the listener with {passive: false}, as is required in some Chrome releases to get the equivalent touch events to work right, but it makes no difference - the problem still happens.
 
Note this bug was reported earlier as https://bugs.chromium.org/p/chromium/issues/detail?id=768124 but closed since I didn't provide a repro case (I assume).
Note that the "OS Version" above should say "Windows 10".  Edits aren't allowed apaprently.
Labels: Needs-Triage-M63
Owner: nzolghadr@chromium.org
Status: Assigned (was: Unconfirmed)
Over to Navid since he has context with respect to  issue 768124 
So if I understand your expectation correctly you want the preventDefault on pointermove to prevent drag operation to start. Is that correct? I don't recall we had such an expectation supported anywhere. Does any other browser do that?

For your usecase, Quoting from pointerevent spec, this should work: 

If the start of the drag operation is prevented through any means (e.g. through calling preventDefault on the dragstart event) there will be no pointercancel event.


So you can call preventDefault on dragstart if your condition is met and prevent browser from dragging. This solution works (should work) for any dragging regardless of pointerevent type.
Labels: Hotlist-Input-Dev
>So if I understand your expectation correctly you want the preventDefault on
>pointermove to prevent drag operation to start. Is that correct? I don't recall 
>we had such an expectation supported anywhere. Does any other browser do that?

Not just drag, but all touch-initiated operations, scroll, drag, etc.  We have existing code that was listening to touchstart, touchmove, touchend, and touchcancel, and worked as expected, with calling preventDefault() on the touchmove event (based on dynamic logic) preventing touchcancel.

As far as other browsers, IE11/Edge doesn't allow for dynamic preventDefault() of touchmove (or pointermove), which people have filed a bug against - your approach is better.  Firefox doesn't define PointerEvent or TouchEvent so we haven't tried to get touch handling working.  You're the sole working implementation of TouchEvent with dynamic preventDefault() (perhaps Safari too but didn't test that).

>For your usecase, Quoting from pointerevent spec, this should work: 
>
>If the start of the drag operation is prevented through any means (e.g.
>through calling preventDefault on the dragstart event) there will be no
>pointercancel event.
>
>So you can call preventDefault on dragstart if your condition is met and >prevent browser from dragging. This solution works (should work) for any >dragging regardless of pointerevent type.

What we're trying to do right now in our code is transition from separate handling for mouseup/mousedown/mousemove+touchstart/touchend/touchmove/touchcancel to just handling pointerup/pointerdown/pointermove/pointercancel, but this bug (I see it as such) is preventing us from doing so.

Currently, our workaround is to continue to listen for touchmove, only using it to call preventDefault() - that seems to prevent pointercancel. We'd rather not refactor our code to have to listen to other events.  If you're not going to fix pointermove to accept preventDefault(), I guess we'll just leave that workaround in place (listening to touchmove), but it makes the code uglier than I think it should have to be.

I did try to look at the specs I could find on pointermove, and didn't find anything saying preventDefault() would be ignored.  (I didn't find anything saying it wouldn't be ignored either, but given that no console error is shown, I think the assumption would be it would be functional.)

(I am the OP, but had access problems so created a new account.)
PointerEvents are passive events. You cannot prevent scrolling by calling preventDefault on those. This is by design and that is why the touch-action css property was added.

What you are doing in terms of refactoring your code to only handle pointerevents was our intention at first for designing pointerevents. If you do that you can handle mouse/touch/stylus and whatever that comes in the future in one place. So you are going in the right direction. Awesome.

I'd like to know more about your usecase on how you handle mouseevents and touchevents right now. Then maybe I can help you better on how to migrate to pointerevents and if there was any missing feature in pointerevents we can discuss that in the pointer events working group to add the feature. For example why weren't you able to use touch-action to declare the scrolling behavior?

>PointerEvents are passive events. You cannot prevent scrolling by calling preventDefault on those.

Well that's a shame because calling preventDefault() works on touch events.  So that means we can't replace touch events with pointer events in our code.

>This is by design and that is why the touch-action css property was added.

No, a CSS property is not sufficient.  That's what I mentioned in my original bug report.  We make dynamic decisions when the touchmove is received whether we want to handle the scroll or drag in our own JS Framework code, or let it be handled by native browser functionality.

If we used the CSS property, then that would either permanently disable the native behavior for said elements (touch: none), or leave it in a configuration (touch-action: auto, touch-action: scroll, etc.) where there's no way to prevent the default native behavior.  We want to dynamically determine at runtime what to do.

>What you are doing in terms of refactoring your code to only handle >pointerevents was our intention at first for designing pointerevents. If you do >that you can handle mouse/touch/stylus and whatever that comes in the future in >one place. So you are going in the right direction. Awesome.

Well, it looks like we can't do that, given the limitations you mention about pointer events.  The switch between pointer and touch events for us isn't that large, but having to listen to other events would be - and I'm not sure there is an event to listen to to prevent native scrolls (other than canceling touchmove).  The onscroll event is called after native scrolling has already started, if my understanding is correct.


>I'd like to know more about your usecase on how you handle mouseevents and >touchevents right now. Then maybe I can help you better on how to migrate to >pointerevents and if there was any missing feature in pointerevents we can >discuss that in the pointer events working group to add the feature. For >example why weren't you able to use touch-action to declare the scrolling >behavior?

We have our own JS Framework and widgets that we manage, and we intercept events  and, depending on the situation and configuration of those widgets, either handle them with our own JS logic, or let the native browser behavior run.  "touch-action", being a CSS styling attribute, is insufficient because it's static - or at least is not intended to be changed as events come in.  From my reading of the spec, changing touch-action after a touchstart will have no impact on the touchmove associated with it - even if we did decide to somehow hack things and attempt to dynamically update that CSS property.

If there were some way to get the "real" event associated with a pointermove, that would make things a bit easier, as then we wouldn't actually have to install a listener for touchmove - we'd just preventDefault() on the "real" event.








Sorry the quoting of your text in my inline response is badly formatted.  There's no "preview" or "edit" feature.
Passiveness of pointermoves and not blocking scrolling on the result of pointermove handlers makes the scrolling much faster. That is the whole intention of that change. So if you declare the intention beforehand using the css properties browser can scroll much faster.

What I'd like to know is your logic which you decide whether you want to prevent scrolling or not. As you can see touch-action has a whole bunch of values for handling different common use cases at the moment. Knowing your usecase and your logic helps us to expand that attribute better to cover more cases.
>Passiveness of pointermoves and not blocking scrolling on the result of
>pointermove handlers makes the scrolling much faster. That is the whole intention 
>of that change. So if you declare the intention beforehand using the css
>properties browser can scroll much faster.

Well, preventDefault() works with touchmove, so how are you able to live with the speed of scrolling when those handlers are used, but not when the same client code plugs into pointermove?

What change are you referring to?  Did preventDefault() used to work with pointermove?

>What I'd like to know is your logic which you decide whether you want to
>prevent scrolling or not. As you can see touch-action has a whole bunch of
>values for handling different common use cases at the moment. Knowing your
>usecase and your logic helps us to expand that attribute better to cover more
>cases.

We distribute a library of JavaScript widgets with dynamic properties and methods to manipulate them.  We have our own event handler that subscribes and interprets browser events subject to widget configuration.  There is no way to simply describe when we might call preventDefault() as it's dynamic and may depend upon widget configuration, position, and/or other events it receives.


Status: WontFix (was: Assigned)
> Well, preventDefault() works with touchmove, so how are you able to live with
> the speed of scrolling when those handlers are used, but not when the same
> client code plugs into pointermove?

If there are any touchmove handlers at all it makes scrolling *janky*. Obviously how janky depends on a ton of other things like the hardware and how busy everything is at that moment.

> What change are you referring to?  Did preventDefault() used to work with pointermove?

Sorry I wasn't very clear. By change I meant introduction of pointerevents in general and them being passive. They have always been passive.

> We distribute a library of JavaScript widgets with dynamic properties and 
> methods to manipulate them.  We have our own event handler that subscribes 
> and interprets browser events subject to widget configuration.  There is no
> way to simply describe when we might call preventDefault() as it's dynamic
> and may depend upon widget configuration, position, and/or other events it 
> receives.

If there is no way of coming up with a value for touch-action css property beforehand to explain your desired behavior and the behavior is so dynamic that you need to make the decision on every event then you need to stick to the touchmoves events.


Sign in to add a comment