-
Notifications
You must be signed in to change notification settings - Fork 62
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
preventDefault on mousedown and touchstart by default? #9
Comments
There’s a partial workaround for the inability to capture events with mousedown.preventDefault: listen to |
If we mousedown.preventDefault:
If we don’t mousedown.preventDefault:
If we touchstart.preventDefault:
If we don’t touchstart.preventDefault:
|
👍
Given this, I agree that it's best to have the most standards compliant and forward looking behavior be the default for D3 4.0. |
Thanks for replying. I think I’m leaning towards keeping things mostly the same with D3 3.x (although D3 4.0 will be more easily customizable, should you want different behavior) for now. When the Chrome bug is fixed, I might switch to mousedown.preventDefault, but then I’d need to figure out how to focus. When Pointer Events are supported, we could use those instead of touch events, and then we should be able to pointerdown.preventDefault to prevent pinch-and-zoom without suppressing click. But it’s all a big if, since the nature of the preventDefault API is that it doesn’t let you explicitly specify what you intend to prevent. |
Pointer events have landed in Chrome in the meantime: https://caniuse.com/#feat=pointer |
The |
There’s a long history here (d3/d3#1322, particularly @jfirebaugh’s comment) but I think it may be best to mousedown.preventDefault and touchstart.preventDefault by default, rather than allow the defaults and then subsequently try to prevent them selectively later.
Here’s my rationale:
It’s a Chrome bug that calling mousemove.preventDefault prevents text selection, drag-and-drop, and scrolling (see issue 485892). The mousemove event is defined as having no default action. Thus, the only standards-compliant way of preventing these default behaviors is to do it on mousedown.
Yes, this prevents capturing mouse events outside an iframe in Chrome due to another bug (issue 269917), but when Pointer Events are implemented (issue 471824) we’ll have element.setPointerCapture as the standard way of capturing events without needing the window hack for mousemove and mouseup.
If multiple touches start on the same element, you must call touchstart.preventDefault to disable pinch-and-zoom. We’ve ignored this in the past because the old drag behavior assumed the touches were always on different elements (e.g., distinct SVG circles). The new d3-drag is agnostic about the DOM structure, and it should be usable even if the circles are rendered with Canvas. It would be brittle and inconsistent to allow the default behavior on touchstart if there’s only one touch (on a given element) and not allow it if there are multiple touches.
Calling touchstart.preventDefault prevents a subsequent click. That’s somewhat unfortunate because this is not true of mousedown.preventDefault, and in the future, pointerdown.preventDefault:
However, you could still implement clickable and draggable things by calling element.click on drag end (if there’s no movement), and this is probably more obvious than checking click.defaultPrevented. I’ll have to test whether it’s possible to call element.click to explicitly click during a mouse-based drag, while still suppressing the default click…
The selectstart event is a working draft specification and not yet available in Firefox (Standard). Yes, Firefox supports -moz-user-select, but that’s vendor-prefixed (and buggy; see issue 648624). Given the inconsistency of default behaviors across browsers and input modes, trying to prevent them selectively has been an ongoing headache.
Whatever we choose as the default behavior of d3-drag (no pun intended!), that behavior is just the default and can be overridden or disabled. So if we decide that d3-drag should mousedown.preventDefault and touchstart.preventDefault by default, users can disable this behavior by calling drag.on and removing the
.nodefault
listener, and then do whatever they want. In contrast to D3 3.x, it is not necessary to fork the implementation.The Chrome bug is unfortunate. But it feels like we should assume that this will eventually be fixed when Pointer Events are implemented, and that the most future-proof way to implement d3-drag will be to mousedown.preventDefault and touchstart.preventDefault (and eventually, pointerdown.preventDefault). Changing d3-drag’s default behavior in regards to preventing browser default behaviors in the future should probably be considered a breaking change, so it’d be great to commit to doing it now as part of the D3 4.0 major release.
/cc @jfirebaugh @jasondavies
The text was updated successfully, but these errors were encountered: