On virtually all current browsers (extensive details from patrickhlauke on github, which I summarised in an SO answer, and also some more info from QuirksMode), touchscreen touches trigger mouseover
events (sometimes creating an invisible pseudo-cursor that stays where the user touched until they touch elsewhere).
Sometimes this causes undesirable behaviour in cases where touch/click and mouseover are intended to do different things.
From inside a function responding to a mouseover event, that has been passed the event
object, is there any way I can check if this was a "real" mouseover from a moving cursor that moved from outside an element to inside it, or if it was caused by this touchscreen behaviour from a touchscreen touch?
The event
object looks identical. For example, on chrome, a mouseover event caused by a user touching a touchscreen has type: "mouseover"
and nothing I can see that would identify it as touch related.
I had the idea of binding an event to touchstart
that alters mouseover events then an event to touchend
that removes this alteration. Unfortunately, this doesn't work, because the event order appears to be touchstart
→ touchend
→ mouseover
→ click
(I can't attach the normalise-mouseover function to click without messing up other functionality).
I'd expected this question to have been asked before but existing questions don't quite cut it:
- How to handle mouseover and mouseleave events in Windows 8.1 Touchscreen is about C# / ASP.Net applications on Windows, not web pages in a browser
- JQuery .on(“click”) triggers “mouseover” on touch device is similar but is about jQuery and the answer is a bad approach (guessing a hard-coded list of touchscreen user agents, which would break when new device UAs are created, and which falsely assumes all devices are mouse or touchscreen)
- Preventing touch from generating mouseOver and mouseMove events in Android browser is the closest I could find, but it is only about Android, is about preventing not identifying mouseover on touch, and has no answer
- Browser handling mouseover event for touch devices causes wrong click event to fire is related, but they're trying to elumate the iOS two-tap interaction pattern, and also the only answer makes that mistake of assuming that touches and mouse/clicks are mutually exclusive.
The best I can think of is to have a touch event that sets some globally accessible variable flag like, say, window.touchedRecently = true;
on touchstart
but not click, then removes this flag after, say, a 500ms setTimeout
. This is an ugly hack though.
Note - we cannot assume that touchscreen devices have no mouse-like roving cursor or visa versa, because there are many devices that use a touchscreen and mouse-like pen that moves a cursor while hovering near the screen, or that use a touchscreen and a mouse (e.g. touchscreen laptops). More details in my answer to How do I detect whether a browser supports mouseover events?.
Note #2 - this is not a jQuery question, my events are coming from Raphael.js paths for which jQuery isn't an option and which give a plain vanilla browser event
object. If there is a Raphael-specific solution I'd accept that, but it's very unlikely and a raw-javascript solution would be better.