New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 595112 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 625198
Owner:
Closed: Jul 2016
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux
Pri: 2
Type: Bug

Blocked on:
issue 417534



Sign in to add a comment

Touchstart on the edge of an anchor fires mousedown

Reported by maciek.k...@gmail.com, Mar 15 2016

Issue description

UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36

Steps to reproduce the problem:
1. Go to http://jsbin.com/ruciworipa/edit?js,console,output
2. Open dev tools and enable device mode
3. tap on the edge of the orange box, covering more area on the outside of the box
4. 

What is the expected behavior?

What went wrong?
you will see that browser detected mousedown event, instead of touchstart event.

Did this work before? N/A 

Chrome version: 49.0.2623.75  Channel: stable
OS Version: 
Flash Version: Shockwave Flash 20.0 r0

It also happens on Chrome for Android
 
Components: -Blink Blink>Input
Labels: Hotlist-Input-Dev
I managed to overcome the problem. The solution is too add touchstart event listener to the other element that is clicked and causes the bug and call event.preventDefault() from there.
Well, unfortunately it worked only in the simple example. This bug still breaks my application and there seems to be no way for work-around. 

Comment 4 by rbyers@chromium.org, Mar 17 2016

Cc: rbyers@chromium.org
What you're seeing here is a feature called "touch adjustment".  See https://docs.google.com/presentation/d/1-n1qyzewpagREbzW2zm0wOalq33UhbtbSkWf9mEdly8/edit#slide=id.gba38d212_099 (video at https://www.youtube.com/watch?v=DujfpXOKUp8).

Most touch browsers have some such feature but it's not well documented and the details differ between browsers.  Basically the design is that touch events represent the low level input from the hardware, but the synthetic mouse/click events represent a higher level concept - that the user is trying to activate something in particular.  For the higher level idea of activation we try to apply some smarts, looking at ALL elements under the finger to decide what the user is likely trying to target.

To know what the best solution is for your situation I need to better understand your scenario.  What are you using the touch / mouse listeners for?  

If you really just want to handle activation (taps/clicks) then you should consider ignoring the touch events (relying on other mechanisms to ensure you get fastclick behavior) and just pay attention to "click".  But if you really want low-level input (eg. to handle drags, button state, etc.) then that should be using touch+mouse events.

One challenge here is properly handling the mouse events for a real mouse while handling only touch events for a touchscreen (and ignoring the synthetic mouse events to avoid double handling).  For that Chrome has a new API on UIEvent called sourceCapabilities.firesTouchEvents.  See https://developers.google.com/web/updates/2015/10/inputdevicecapabilities

Does this help?

Comment 5 by rbyers@chromium.org, Mar 17 2016

See also issue 417534, which (if we can do it) will hopefully avoid the confusion in scenarios like this jsbin which are already mobile optimized (so don't benefit much from the touch adjustment feature).

Comment 6 by rbyers@chromium.org, Mar 17 2016

Blockedon: 417534
Labels: Needs-Feedback
Cc: dtapu...@chromium.org
Thanks for your answer. The situation is very complex, it's far from simply tapping. It is a vertical menu with anchors. I have 2 classes of events, one for the whole menu, which handles sliding and scrolling (custom scrolling) and the other one for anchors: tapping, tapping and holding, dragging anchors. 

The separator is very small, 5px tall and anchor is 34px. So most likely when I touch separator, I also touch 2 anchors around it. So now I understand that the element is too small to be detected, that's why I can't get event handlers for the separator to fire, hence the potential solution in Comment 2 didn't work.

Now if I could only detect separator touch and do it before anchor event fires, I could just set the event type to touchstart instead of mousedown. But the element is just too small and nothing can be done, right?

As a last resort I could remove separators completely and add some handlers to elements around the menu (which are much bigger than the separator). I'm not that keen on removing it, because this application is built on top of another one, like a plugin and I don't have much control on the structure of this menu, only js manipulation can remove it. 

Comment 9 by rbyers@chromium.org, Mar 17 2016

If I understand correctly, you want to be able to touch-drag (not just tap to activate) a separator which visually needs to be very small (5px)?

Assuming that you're only interested in dragging on the separator, then you should definitely be calling preventDefault on touchstart there.  The separator is responsible for fully handling all touches that start on top of it.  That way if a user does actually manage to activate the separator, there won't also be mouse/click events getting generated that could hit the anchor.  As long as the finger center-point lands on the separator and you call preventDefault, then the anchors will not receive any mouse/click events.

But if it's only 5px, it's still going to be extremely hard for users to use reliably with touch. In general touch-friendly UI needs to have hit targets that are at least 25px-40px or so in order for users to be able to manipulate them reliably.  One compromise is to give the separator a larger hit area without changing it's visual appearance by putting a transparent div on top of it that's at least 25px or so (opacity:0 elements still receive input events).  This is what, for example, we do in ChromeOS for resizing windows (the touch handles extend beyond a window much further than the visual window border indicates).  But then you of course need to worry about what UI elements might get stuck behind that transparent overlay.

Project Member

Comment 10 by sheriffbot@chromium.org, Mar 17 2016

Labels: -Needs-Feedback Needs-Review
Owner: rbyers@chromium.org
Status: Assigned (was: Unconfirmed)
Thank you for providing more feedback. Assigning to requester "rbyers@chromium.org" for another review.

For more details visit https://sites.google.com/a/chromium.org/dev/issue-tracking/autotriage - Your friendly Sheriffbot
No the separator doesn't do anything. I just wanted to attach a touchstart handler to it to call preventDefault, to prevent firing mousedown event on anchor But it doesn't happen, there seems to be no way to attach a touch handler to the eparator, it just doesn't work as long as there is an event attached to anchors. I'm unable to reproduce this issue in jsbin. 
So the anchor has it's own touch listener that calls preventDefault, and so normally shouldn't get any mouse events from touch, right?

Mouse event and touch event hit testing works the same way, so if your separator can receive 'mousedown' events, then it should also be able to receive 'touchstart' events.  One option to add some logging to listen on the window for all touchstart and mousedown events and report their Event.target property.  Before the anchor gets a mousedown, you should see a touchstart going somewhere, and calling preventDefault in a handler attached to that 'target' should prevent the mousedown from getting generated in the first place.

If you've got a repro (even outside jsbin), I'd be happy to take a look.

That said, if your goal is just to ensure the anchor only handles mouse* events for a real physical mouse, then the InputDeviceCapabilities API I mentioned above is the easiest way to do that (but Chrome-specific at the moment, but there's a polyfill you can use).
Reacting to this subject as it's linked to the issue I had today.
I have links with anchors to avoid empty href even if it's allowed in HTML5. Something like
`<a href="#" class="js-doSomething">Some text</a>`

On mobile devices I use touchstart instead of click, the issue is that if you click on the edge of the link and not on the text the touchstart event is not fired but click event is. Resulting in the browser taking in account the anchor since I don't have any `event.preventDefault()` which is bound to touchstart.
I solved the issue by disabling click on this kind of links, but I expect a touch event to occur and not a click.
Cc: chongz@chromium.org
Mergedinto: 625198
Status: Duplicate (was: Assigned)
I filed  issue 625198  to explain and track the bigger picture issue here.  Please star it to follow along there.

Sign in to add a comment