Closed mattcg closed 11 years ago
I introduced setTimeout to have correct order of events, otherwise it's possible to get click
before touchend
in code like (as FastClick is bound to document.body
by default)
$(window).on('touchend click', function(){...});
It's rare case and compatibility has higher priority of course.
Thank you @dryabov. I'd like to keep your contribution so maybe we can add a different code path for iOS 4 that avoids the setTimeout and sends the click event instantly.
Actually in the http://ftlabs.github.com/fastclick/examples/focus.html example only "B" button works for me, but it's not iOs 4 - I'm using iOs6.1.2 with iphone 4s.
@restyler Noted, thanks for that. The regression was indeed caused by the setTimeout, which we introduced to preserve event order as @dryabov pointed out (some UI frameworks rely on that order). I'll try jQuery mobile/UI and Twitter Bootstrap without the setTimeout and see what we get.
Maybe the following flow would work:
this.layer
to correctly fire handlers of parent elements (note: check that FastClick doesn't process this event twice).That sounds like a good idea, and a better one than the one I was thinking of which was that in the special case of touchend
we let it bubble all the way up to window
, giving other third-party listeners a chance to do their thing before continuing. The problem with this is that those listeners may stop propagation before the event bubbles up to window
, or there may be UI framework listeners on window
.
Thinking about your idea, what if at stage 2 there is a UI framework listener on this.layer
that gets triggered twice - once when the original touchend
event first comes through and a second time when we fire the synthetic touchend
event? I suppose we could use the same technique that we use for click
, which is to make the listener capturing.
Yes, it's the problem, we cannot be sure that our event is the first in the list (moreover, DOM Event specification doesn't assert that events will be called in the order of addEventListener
calls). Workaround here could be to process touchend
event in capturing phase as it's rarely used by frameworks (and, correspondingly, trigger touchend
on target element).
Closing for now.
Safari on iOS 4 will only allow focus to be triggered on other elements from within a function if the first function in the call stack was triggered by a non-programmatic event. The call to setTimeout starts a new call stack, and some mechanism kicks in to prevent focus being set on the input.