Bug 171105

Summary: Normalizing touch events mouse compatibility event bubbling
Product: WebKit Reporter: Patrick H. Lauke <redux>
Component: UI EventsAssignee: Nobody <webkit-unassigned>
Status: RESOLVED DUPLICATE    
Severity: Enhancement CC: cdumez, dino, rbyers, rmondello, rniwa, simon.fraser, thorton, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: Safari 10   
Hardware: iPhone / iPad   
OS: iOS 10   
Attachments:
Description Flags
Testcase
none
Test case showing lack of event bubbling
none
Click handler on the body none

Patrick H. Lauke
Reported 2017-04-21 01:44:42 PDT
Currently, a touchscreen tap on an arbitrary (non-focusable, non-actionable) part of a document results in mouse compatibility events (the classic mouseover > mouseenter > mousemove > mousedown > focus > mouseup > click that follow after the touchstart > touchend) on that particular part of the document that do not bubble as expected; likewise, if an element is currently focused (e.g. a <button>) from a previous tap interaction, this tap outside of it on an arbitrary element also does not send the mouseout > mouseleave > blur event sequence to that focused element (although the focus does seem to move away from the element?). This has been partially documented (through trial and error) here https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html (and I usually mention it in workshops, see https://patrickhlauke.github.io/getting-touchy-presentation/#202) It's likely that this behavior was introduced (together with the old "Making Elements Clickable" technique, which required authors to add empty event onclick handlers to their elements in order to be able to get the mouse compat events on that element itself - see https://patrickhlauke.github.io/getting-touchy-presentation/#204 - which is a behavior that has since been removed in iOS) for performance optimization reasons back in the early days of iOS' event handling. However, this heuristic behavior is currently not documented on developer.apple.com, and it causes problems with event delegation approaches. As a real-world example, I recently spent some time adding iOS hacks to Bootstrap's core scripting to enable things such as dropdowns and tooltips closing when a user taps outside of them (see https://github.com/twbs/bootstrap/pull/22426). The hack involved dynamically adding/removing noop mouse handlers to the child elements of <body>, in order to coax iOS/Safari into bubbling the mouse compatibility events. Admittedly, one could argue that on touch devices one shouldn't rely on event bubbling of mouse compat events, and instead write explicit touchstart/touchend handlers. However, this would make the resulting code far more complex. AND event bubbling as a result of touch happens correctly in all other tested platforms (e.g. Windows 10 Mobile, Android, touch-enabled Windows laptops with Chrome, Firefox). Is it possible to reconsider iOS' current quirky and undocumented event bubbling for mouse events? If the concern was performance, this may have held true back in the days when the behavior was first devised, but on modern/current iOS devices, I'd posit the perf impact may be minimal (particularly since other browsers on other platforms seem to manage this). Failing that, it would still be good to get this documented officially somewhere.
Attachments
Testcase (1.11 KB, text/html)
2018-01-03 18:10 PST, Simon Fraser (smfr)
no flags
Test case showing lack of event bubbling (3.24 KB, text/html)
2018-01-04 06:25 PST, Patrick H. Lauke
no flags
Click handler on the body (608 bytes, text/html)
2018-01-04 11:27 PST, Simon Fraser (smfr)
no flags
Patrick H. Lauke
Comment 1 2017-10-20 02:29:46 PDT
Any chance to at least document this on developer.apple.com?
Radar WebKit Bug Importer
Comment 2 2017-10-20 10:56:51 PDT
Simon Fraser (smfr)
Comment 3 2018-01-02 13:24:04 PST
Ping to self
Simon Fraser (smfr)
Comment 4 2018-01-03 18:10:38 PST
Created attachment 330428 [details] Testcase In this simple testcase, bubbling of the synthetic click works fine.
Patrick H. Lauke
Comment 5 2018-01-04 06:24:52 PST
Simon, that test case works because you already have a click handler attached to the elements. The issue does not manifest itself when you have: * target element is a link or form control * target or any ancestor (up to but not including body) has explicit mouse or click handler (even if only empty function) * target or any ancestor (up to and including document) has cursor:pointer https://patrickhlauke.github.io/getting-touchy-presentation/#221 The problem with bubbling/delegation happens when you don't have any of the above. For instance, user taps on a <div> but listens for click on the body (as many event delegation frameworks do). As an example, see https://patrickhlauke.github.io/touch/bubbling/div.html (attached as single file testcase here too)
Patrick H. Lauke
Comment 6 2018-01-04 06:25:26 PST
Created attachment 330463 [details] Test case showing lack of event bubbling
Patrick H. Lauke
Comment 7 2018-01-04 06:26:39 PST
There are more permutations I tested for this at https://patrickhlauke.github.io/touch/ (under the "iOS event bubbling" section)
Simon Fraser (smfr)
Comment 8 2018-01-04 11:27:57 PST
Created attachment 330475 [details] Click handler on the body This testcase shows the bug.
Simon Fraser (smfr)
Comment 9 2018-01-04 11:43:40 PST
This happens because Frame::qualifyingNodeAtViewportLocation() doesn't include the body for some reason.
Simon Fraser (smfr)
Comment 10 2018-01-04 11:44:46 PST
And there's some crazy code that looks at CSS cursor styles to decide which nodes are clickable, which seems bizarre.
Simon Fraser (smfr)
Comment 11 2018-01-04 11:54:03 PST
This is a really old issue, covered by rdar://problem/5844416. It seems like we're trying to avoid having the tap highlight show up over the entire page, but I think we could fix that without breaking handlers on the body.
Simon Fraser (smfr)
Comment 12 2018-01-04 12:44:53 PST
*** This bug has been marked as a duplicate of bug 151933 ***
Note You need to log in before you can comment on or make changes to this bug.