ftlabs / fastclick

Polyfill to remove click delays on browsers with touch UIs
MIT License
18.66k stars 3.22k forks source link

Ghost focus problem #27

Closed zeroonea closed 11 years ago

zeroonea commented 12 years ago

Click on a button to transition (css3 slide) to next page, if on next page there is an input right there the position of the button on previous page, the input will get focus and soft keyboard open up.

jsfiddle: http://jsfiddle.net/sX3WJ/ open it in mobile browser: http://fiddle.jshell.net/sX3WJ/show/

mattcg commented 12 years ago

Thank you for reporting. What browser/OS/device is this on?

zeroonea commented 12 years ago

Thanks for fast response. My environtment: web app + phonegap on android 4.1 galaxy nexus. I updated test case

steverandy commented 11 years ago

Having similar issue with contenteditable. Any quick temp hack to prevent it?

yfarooq commented 11 years ago

i have the same problem, any idea how to prevent it ?

mattcg commented 11 years ago

@steverandy and @yfarooq are you both encountering the problem on Android?

dryabov commented 11 years ago

I reproduced the issue on Android 2.3.5 (caret in input field is moved to the position of click). To log sequence of events, I've modified fiddler code in the following way: http://jsfiddle.net/HXRFM/ (http://fiddle.jshell.net/HXRFM/show/) To my surprise, this version works correctly, so I don't know what is the difference (either browser processes "bubbled" events in special way, or a delay because of logger does matter).

steverandy commented 11 years ago

@mattcg, it happens on mobile safari ios 6 for me.

ghost commented 11 years ago

Thank you Mattcg for response, i am facing the problem on iOS . i am not sure if i am implementing it properly however the response of buttons changed. i want fast click to target all the buttons and links I am using Jquerymobile and this is how i am implementing.

    <script type="application/javascript" src="js/fastclick.js"></script> 
    <script type="application/javascript">
        window.addEventListener('load', function () {
          new FastClick(document.body);
        }, false);
    </script> 

after body start i have a div class with id FastClick

all my pages are here.

Cheers ,

mattcg commented 11 years ago

Thanks @yamafarooq. That looks like a different issue. Will you create a test case and open a new ticket please?

mattcg commented 11 years ago

@dryabov thanks for that. I think the DOM manipulation caused by the logging is causing the browser to behave differently.

dryabov commented 11 years ago

You are right, I've postponed manipulations with setTimeout and the issue comes back. But the list of caught events was the same, so I've included other events to log (http://jsfiddle.net/HXRFM/2/show/). Result is:

touchstart DIV#btn DIV#btn null click DIV#btn DIV#btn DIV#btn touchend DIV#btn DIV#btn null mousedown INPUT#text INPUT#text INPUT#text mouseup INPUT#text INPUT#text INPUT#text

So, the problem is that browser emulates mouse events after touchend.

dryabov commented 11 years ago

From http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html

If the user taps a nonclickable element, no events are generated. If the user taps a clickable element, events arrive in this order: mouseover, mousemove, mousedown, mouseup, and click. The mouseout event occurs only if the user taps on another clickable item. Also, if the contents of the page changes on the mousemove event, no subsequent events in the sequence are sent.

From http://jquerymobile.com/demos/1.2.0/docs/api/events.html

Webkit based browsers synthesize mousedown, mouseup, and click events roughly 300ms after the touchend event is dispatched. The target of the synthesized mouse events are calculated at the time they are dispatched and are based on the location of the touch events and, in some cases, the implementation specific heuristics which leads to different target calculations on different devices and even different OS versions for the same device. This means the target element within the original touch events could be different from the target element within the synthesized mouse events.

Most likely a minor modifying of DOM would be the way to cancel mouse events generation. Or, alternatively, maybe it's possible to stop mousedown or mouseup (or both) event propagation like it's done for click event.

steverandy commented 11 years ago

@mattcg, this is a screen recording, showing the issue that I'm having. https://dl.dropbox.com/u/2271268/ghostclick.mov

I'm not sure if it's because of the css3 animation or the confirm box.

dryabov commented 11 years ago

@zeroonea try this version: https://raw.github.com/dryabov/fastclick/master/lib/fastclick.js If it works, I'll create pull request.

The issue is because of EventDispatcher::dispatchSimulatedClick() method in WebKit (https://trac.webkit.org/browser/trunk/Source/WebCore/dom/EventDispatcher.cpp#L222) dispatches mouseover, mousedown, mouseup, and click events. And fastclick.js "disables" click only. Fortunately, we can stop other simulated events as well (as I did in above fork). Unfortunately, dispatchSimulatedClick() calls to node->setActive(true) so the node (that will be under touch position in 300 ms after touchend) will be activated (but not focused).

PS. Next week I'll try to fix setActive() issue using call to this.focus(oldTargetElement); in simulated click event. Hope it will allow to "undo" all effects of dispatchSimulatedClick().

mattcg commented 11 years ago

@dryabov that's brilliant work tracking down the cause of the issue. спасибо!

Please do make a pull request if this does work.

steverandy commented 11 years ago

Managed to fix my issue by using defer to wrap the function that will show the confirm dialog box.

dryabov commented 11 years ago

@mattcg it does work in the sense that inputbox in @zeroonea example is not focused. But WebKit (Android 2.3.5, stock browser) highlight it with a border. It's better than nothing, but doesn't correspond to initial behaviour (without fastclick.js input box is not highlighted after click).

tonyawad88 commented 11 years ago

That did it for me too "https://raw.github.com/dryabov/fastclick/master/lib/fastclick.js"

Thank you !

mattcg commented 11 years ago

The patched version was merged into master in 17aea9437a218bf174dbd308a969699517ee2bd1.