Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[future uncertain] Add support for pointer events #1389

Closed
wants to merge 5 commits into from
Closed

[future uncertain] Add support for pointer events #1389

wants to merge 5 commits into from

Conversation

syranide
Copy link
Contributor

@syranide syranide commented Apr 9, 2014

The future of pointer events seem uncertain, this PR should not be accepted until it is decided.

http://www.w3.org/TR/pointerevents/, only IE supports it at the moment it seems, you should be able to polyfill with http://handjs.codeplex.com/

  1. I have reused EnterLeaveEventPlugin to power both Mouse and Pointer, feedback on my rewrite appreciated. One possibility is to construct a lookup map instead for isMouseEvent/isPointerEvent/isOverEvent/isOutEvent/etc, but I'm thinking it might just make the code more complex.
  2. I took the liberty of stripping the alignment spacing in SimpleEventPlugin because I would still have had to realign everything, and this way makes future updates less likely to conflict. It's also consistent with ReactEventEmitter.
  3. Should mouseListenerNames in ReactDOMButton include pointer events? Touch events too? Are there actually any events that you want it to attach when it's disabled?
   raw     gz Compared to master @ b75d11c6039e4d2ab796bce2a1934e9e69b2b7e7
 +4806   +613 build/react-with-addons.js
 +2175   +431 build/react-with-addons.min.js
 +4813   +591 build/react.js
 +2177   +446 build/react.min.js

@syranide
Copy link
Contributor Author

syranide commented Apr 9, 2014

#499

@syranide
Copy link
Contributor Author

syranide commented Apr 9, 2014

cc @sebmarkbage

topLevelType === topLevelTypes.topPointerOut ||
topLevelType === topLevelTypes.topPointerOver
);
if (!isMouseEvent && !isPointerEvent) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you move isOverEvent and isOutEvent up, I think this can just be if (isOverEvent || isOutEvent)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spicyj It can be, but I still need to be able to separate isMouseEvent from isPointerEvent further down below. I guess we technically can save one unnecessary evaluation if we exit early at line 105. But other than that it should be identical, doesn't hurt though I guess :)

@sophiebits
Copy link
Collaborator

Do you want to add the appropriate pointer events to TapEventPlugin's dependencies? Otherwise I think this looks pretty reasonable. Haven't tested it.

@sebmarkbage
Copy link
Collaborator

@steida does this solve your use case?

@syranide
Copy link
Contributor Author

@spicyj Hmm I assume you mean because of isStartish and isEndish, intuitively it feels like I might've misunderstood something here, as pointer events won't provide any data that it isn't already aware of (but perhaps it's safer and more "future proof" to have both?).

@steida
Copy link

steida commented Apr 10, 2014

@sebmarkbage Not entirely. Please no PointerEvents Polyfils inside React. It's not as easy as it looks to polyfill such events. It's pretty hard and one can easily broke mobile touch experience with wrong implementation. The beauty of http://www.polymer-project.org/platform/pointer-events.html is its quality, lowlevel-ness and correct behaviour on mobile. For instance, you have to deal with scroll momentum to ignore/filter touches during HW accelerated animation. And more.

The only thing React should do is to allow pointer events event types to leverage native behaviour. Deal with it exactly like mouseover, mouseclick etc. plus add their interface. Polymer will fix the rest.

@syranide
Copy link
Contributor Author

@steida That's what this is, no polyfill, just the events.

@steida
Copy link

steida commented Apr 10, 2014

Then ok. I didn't have a time to test it with Polymer, so I believe you :-)

topLevelTypes.topPointerCancel,
topLevelTypes.topPointerDown,
topLevelTypes.topPointerMove,
topLevelTypes.topPointerUp,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no trailing comma plz

@syranide
Copy link
Contributor Author

Update, working in IE11, Leave/Enter broken in all other browsers when polyfilled with handjs. It makes no sense to me, Enter fire when moving red<->green and Leave does not fire at all when leaving red. I've looked up and down EnterLeaveEventPlugin and can't see anything amiss.

http://dev.cetrez.com/jsx/3/

@syranide
Copy link
Contributor Author

Found the issue:

IE11:
PointerOut relatedTarget = <toElement>
PointerOut fromElement = null
PointerOut toElement = null
PointerOut srcElement = <fromElement>
PointerOut target = <fromElement>
PointerOver relatedTarget = <fromElement>
PointerOver fromElement = null
PointerOver toElement = null
PointerOver srcElement = <toElement>
PointerOver target = <toElement>

HandJS:
PointerOut relatedTarget = null
PointerOut fromElement = null
PointerOut toElement = <fromElement>
PointerOut srcElement = <fromElement>
PointerOut target = <fromElement>
PointerOver relatedTarget = null
PointerOver fromElement = null
PointerOver toElement = <toElement>
PointerOver srcElement = <toElement>
PointerOver target = <toElement>

The way EnterLeaveEventPlugin is currently implemented it relies on the Out-event having both the to and from element, which it doesn't in the case of HandJS. I've submitted an issue to HandJS and they've responded, so it seems like they're considering it.

@syranide
Copy link
Contributor Author

After discussing a bit with @spicyj it seems like the best solution might be to actually to polyfill it ourselves (if we're ok with that), it should be a relatively straight-forward and small implementation within React and should be surprisingly well-functioning, as opposed to the universal polyfills. All universal polyfills seem very brittle, has poor browser support, are poorly maintained or doesn't seem to work all that well to begin with.

So far, HandJS seems like the only potential polyfill that seems to work consistently with great browser support. It is currently not compatible with React though because of a lack of either to/from-element information in the dispatched events, I've submitted and issue and we'll see what their response is (EDIT: Just got a response, seems like they're considering it). If the issue is resolved it seems like a capable solution, but my initial feeling is that I would probably not be confident in using it as a complete replacement for mouse/touch-events.

@sebmarkbage @zpao @spicyj etc, how would you feel about shipping a polyfill for Pointer events in React core given that it stays reasonably small and robust enough?

@steida
Copy link

steida commented Apr 11, 2014

Why yet another polyfil?
http://www.polymer-project.org/platform/pointer-events.html is ok. Keep
React modular please.

On Fri, Apr 11, 2014 at 1:18 PM, Andreas Svensson
notifications@git.luolix.topwrote:

After discussing a bit with @spicyj https://github.com/spicyj it seems
like the best solution might be to actually to polyfill it ourselves (if
we're ok with that), it should be a relatively straight-forward and small
implementation within React and should be surprisingly well-functioning, as
opposed to the universal polyfills. All universal polyfills seem very
brittle, has poor browser support, are poorly maintained or doesn't seem to
work all that well to begin with.

So far, HandJS seems like the only potential polyfill that seems to work
consistently with great browser support. It is currently not compatible
with React though because of a lack of either to/from-element information
in the dispatched events, I've submitted and issue and we'll see what their
response is. If the issue is resolved it seems like a capable solution, but
my initial feeling is that I would not be confident in using it as a
complete replacement for mouse/touch-events.

@sebmarkbage https://github.com/sebmarkbage @zpaohttps://github.com/zpaoetc, how would you feel about shipping a polyfill for Pointer events in
React core given that it stays reasonably small and robust enough?

Reply to this email directly or view it on GitHubhttps://github.com//pull/1389#issuecomment-40193441
.

@syranide
Copy link
Contributor Author

@steida Polymer does not support all browsers that React target, so while the implementation seems to work (although not 100% compatible), it's not an option for most people. Also, we would only polyfill if there is no native/polyfill already present, so it would only be a size-cost.

Chrome 18+, Safari 6+, IE 10, Firefox 14+
http://www.polymer-project.org/platform/pointer-events.html#full-support

@steida
Copy link

steida commented Apr 11, 2014

For IE8/IE9 click is enough. There is no such touch/tablet devices with IE and touch support.

@steida
Copy link

steida commented Apr 11, 2014

And as I already said. Polyfil must be very carefully crafted to not destroy mobile scroll experience.

@syranide
Copy link
Contributor Author

@steida Highly subjective seeing as a lack of pointer events would effectively break an application, supporting both mouse (and touch) and pointer events in an application seems like a significant headache to deal with.

A reasonable middle-ground could be that we only polyfill with equivalent mouse events if navigator.pointerEnabled isn't set, that way with touch events enabled and polymer pointer events older browsers would behave properly, new browsers would still support pointer events for mouse events even with touch events disabled and no pointer events polyfill provided. That is, if there are no browsers not supported by polymer pointer events (or other suitable polyfill) that do support touch, that could be expected to be encountered in the wild. That would be bad.

So the way I see it, pointer events walk a very thin line, if you can be sure that it works as it should for everyone then it's extremely beneficial, but if you can't be then it's not really all that useful except for certain edge-case users perhaps. So if it turns out there's a significant population using touch with browsers not listed in Chrome 18+, Safari 6+, IE 10, Firefox 14+ then it would seem pointer events would see limited use for the immediate future.

@syranide
Copy link
Contributor Author

Update, HandJS responded super fast and have issued 1.3.8 which adds support for relatedTarget. Brief testing shows encouraging results with it performing as it should in all major browsers and IE8+.

I'm still not 100% convinced that we couldn't provide a more suitable polyfill within React. My primary motivator here being that pointer events, just like the updated keyboard events, are superb features and I would hate to see it go unused for any technical reason.

@sophiebits
Copy link
Collaborator

React's source is already modular (and will stay that way), but there's no easy way to pull out certain parts in a build right now. Hopefully we can get React to a point where it's easier to do custom builds and to choose whether to include or not include certain polyfills, like this hypothetical pointer one. Ideally we could have a cross-browser pointer events shim that works in all browsers React supports while allowing you to bring your own polyfill if you want to use Polymer's or to save bytes if you just don't care about pointer events.

@facebook-github-bot
Copy link

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

@matthewoates
Copy link

I'm failing to see the issue with adding pointer events to React. If React has its own implementation, and these new pointer events have separate names from the touch and mouse events, then it could only potentially break when people use these new pointer events.

I hacked together a polyfill myself that's a jQuery plugin: https://github.com/matthewoates/jQuery.onetap/blob/master/jquery.tap.js

Basically, it listens for clicks and touch events. Whenever a touch event happens, we ignore click events for 1 second. That seemed like a solid way to not have multiple events fire for one click/tap.

Would a polyfill implemented in this way be acceptable?

@saschanaz
Copy link

A pointer events polyfill always should not break other events, if there is no bug. I think your 1-second method is currently the best one to prevent multiple event occurrence, while I have found that 700ms is just fine.

@zoomclub
Copy link

There is great interest but is any of this in React already? It would helpful to see a summary/post of what React can do now with events and then how to augment that with mixins.

Frankly, I'm confused about where things are at and are going with events in React. I just want a system where there are not separate calls for mouse and touch. I would also like a system that supports a pen input device, like the Wacom or SPen. Then absolutely I want a system where Myo Armband input can be easily done.

I'd like to see an article on the main React site detailing everything React does with events and how different input providers (mouse, touch, stylus, myo, etc) can/will be supported.

There has to be a unified approach and solution because there will always be more providers, mouse and touch are just scratching the surface :-)

@syranide
Copy link
Contributor Author

@zoomclub We all want something more than just this division between mouse and touch. But as is evident in the latest discussion in #499, the problem is that no one seems decided on what the real solution is.

The current design of React AFAIK is to stay as close as possible to HTML5, if PointerEvents become a standard then React will surely have it, but comitting to it without PointEvents becoming a standard is far from a simple decision. So for now I think we'll just have to wait and see what happens to PointerEvents.

An idea is to allow any non-standard event-handler specified on a ReactDOM-node to actually be listened to, not just standard events. That would allow people to plug in whatever polyfills/sugars they need, but it may hurt third-party components that would rarely be able to take advantage of it.

@zoomclub
Copy link

As long as The React synthetic event system can process events for different providers I'll live with it. I'm not so concerned about 3rd party components. I just want to be able to support alternate providers in my own app.

This is why in my pre React design I thought that it would be best to parse all events myself and pullout and track the details I'm interested in in a separate object. Then component handlers would use the tracked details and not have to implement the dedicated/limited mouse and separate touch and other provider calls all over the place and trip over themselves trying to manage the mess.

Component handlers should be working on their real purpose and not be filled with code that just wrestles with provider/event types. In Flux stores are abstracted, it seems logical to abstract event details from different providers too. This way component handlers just check the state of the tracker object and get on with what they are doing.

@zoomclub
Copy link

The MyoJS API has arrived and it attaches its hub to the window object. The Myo's frames should be available in any component but I'm not sure if it will be blocked by the React synthetic event system?

https://github.com/logotype/MyoJS

@syranide
Copy link
Contributor Author

@zoomclub You can always attach listeners yourself using addEventListener inside componentDidMount. The synthetic event system does not understand non-standard events unless you maintain your own branch with a custom event plugin.

@zoomclub
Copy link

@syranide Good to know there are mouse, touch, qwerty and now myo events available :-)

@syranide syranide changed the title Add support for pointer events [future uncertain] Add support for pointer events Sep 29, 2014
@sebmarkbage
Copy link
Collaborator

I'm putting a needs revision label on this until we have more discussion.

topInput: 'input',
topKeyDown: 'keydown',
topKeyPress: 'keypress',
topKeyUp: 'keyup',
topLostPointerCapture: 'lostpointercapture',
topMouseDown: 'mousedown',
topMouseMove: 'mousemove',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello

@chenglou
Copy link
Contributor

Btw Chrome is not adopting it: https://code.google.com/p/chromium/issues/detail?id=162757#c64

@iamdustan
Copy link
Contributor

Unless they see a lot of dev support for it in userland (one comment is no. 128 on that lengthy thread).
More commentary (from a while ago): https://docs.google.com/document/d/17BUdF-uSg_0CUwhyenaB5FZeob0HK9DcD85lC1sH6cA/edit

And it is an official w3c recommendation! http://www.w3.org/blog/news/archives/4430?pk_campaign=feed&pk_kwd=pointer-events-is-a-w3c-recommendation

@zoomclub
Copy link

flux-reactions is moving in a positive direction with view vs event separation of concerns. PointerEvents would make it ideal. It would be great for react to just manage input providers and event types themselves.

arqex/flux-reactions#1

UPDATE:

There seems to be a growing distaste for Flux and the increasing realization that a powerful event system is at the heart of the flow of data through a React app. Here are more examples of this:

http://qiita.com/kimagure/items/22cf4bb2a967fcba376e
https://medium.com/@cassiozen/flux-cargo-culting-3cae9ff27c0c

Looks like Rx and React are a natural pair.

@syranide
Copy link
Contributor Author

@iamdustan Interesting.

@iamdustan
Copy link
Contributor

@syranide in what way? 😉

@syranide
Copy link
Contributor Author

@zoomclub
Copy link

This is great news!

@syranide
Copy link
Contributor Author

@sebmarkbage Now that PointerEvents seem to be gaining traction, should we go ahead and add support to React core?

@sebmarkbage
Copy link
Collaborator

I think we need to make a major design choice soon about what we want our event system to be. The browser's naive model is clearly not enough for a lot of use cases (sliding gestures, touch responder negotation, custom bubbling rules such as through abstraction layers instead of DOM layers, etc.). Building our own event system is fundamentally incompatible with other frameworks since the delegation/ownership model doesn't interact well between subtrees. Even if we did it, other frameworks might not and we remain incompatible anyway. Maybe we need two different optional event systems. Yet, we want the out-of-the-box experience to also be nice. We're also backporting some of the event systems from React Native back to the DOM.

Essentially it boils down to the fact that the componentization of events is still an unsolved problem since there is still global negotiation needed.

Maybe we should support it for the DOM regardless, but I think there is a much bigger discussion to be had about our event strategy.

@syranide
Copy link
Contributor Author

Maybe we should support it for the DOM regardless, but I think there is a much bigger discussion to be had about our event strategy.

@sebmarkbage Definitely, but it seems to me that you'll always have to expose the (almost) raw underlying event APIs, either directly or indirectly. There are millions of targets and none are 100% capable or even agree on the keyboard and mouse interface, so a forced standardized interface seems wholly unrealistic.

If users could componentize custom event APIs on-top of that it would be fantastic, but I imagine it's two-fold. Custom event subsystems on a per-subtree/root basis (requires some level of coordination) and event callbacks on a per-node/component basis (totally independent) that depend on either native or custom event subsystems.

So one way or another it seems to me that React won't be harmed by exposing PointerEvents the same way all other HTML events are currently exposed, it's just more of the same.

@zoomclub
Copy link

It would be great to learn more about what is in store for events in React. In the meantime or as an alternative Rx looks like a perfectly logical way of handling events in React apps. The Rx.DOM implementation is robust and is armed with Pointer and Touch events ready to go. See here:

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/events.md

@gaearon
Copy link
Collaborator

gaearon commented Mar 26, 2016

I’m closing this PR because there doesn’t seem to be enough momentum behind it. I think we should get better at closing PRs that are low on momentum / support_cost number, so that is what I’m trying to do here.

Like anything, it’s a matter of prioritization. I think that a good time to revisit this would be when Chrome supports Pointer events (at the moment it doesn’t). Let’s track any future work on this in #499. I do hope we’ll get this in eventually.

Thank you for your work on this!

@gaearon gaearon closed this Mar 26, 2016
philipp-spiess added a commit to philipp-spiess/react that referenced this pull request Mar 31, 2018
This PR adds support for Pointer Events as discussed in facebook#499. It is
heavily based on previous work in facebook#1389 and will add most pointer events
to the `SimpleEventPlugin` and enter/leave events to
`EnterLeaveEventPlugin`.

I added a new DOM fixture to test all pointer events and make sure my
implementation does indeed work. I tested on Chrome 65 and Firefox 59
without seeing any issues. If you think the fixtures is not necessary
for future changes, I'm happy to remove them as well.

The only open question is if we want to add a polyfill. For the sake of
simplicity, I opted against a polyfill for this PR. However, this work
is compatible with [PEP][] (I've verified this behavior in Safari 11 by
loading PEP in `fixtures/dom/public/index.html`).

[PEP]: https://github.com/jquery/PEP
philipp-spiess added a commit to philipp-spiess/react that referenced this pull request Apr 9, 2018
This PR adds support for Pointer Events as discussed in facebook#499. It is
heavily based on previous work in facebook#1389 and will add most pointer events
to the `SimpleEventPlugin` and enter/leave events to
`EnterLeaveEventPlugin`.

I added a new DOM fixture to test all pointer events and make sure my
implementation does indeed work. I tested on Chrome 65 and Firefox 59
without seeing any issues. If you think the fixtures is not necessary
for future changes, I'm happy to remove them as well.

The only open question is if we want to add a polyfill. For the sake of
simplicity, I opted against a polyfill for this PR. However, this work
is compatible with [PEP][] (I've verified this behavior in Safari 11 by
loading PEP in `fixtures/dom/public/index.html`).

[PEP]: https://github.com/jquery/PEP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.