Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore jQuery hover (mouseenter, mouseleave) on touch devices

Having neither mouse nor pointer, the concept of hovering on-screen elements is not really applicable for touch devices. With many web sites relying on JavaScript hover events navigation or other purposes, some touch devices1 implements the mouseenter to be fired upon a single tap. If an event handler is also bound to the click this will only be raised on a second tap on the element.

Since jQuery's hover() function internally uses mouseenter and mouseleave, elements with both hover() and click() registrations requires two taps to trigger the latter2. For many use cases, this is exactly what you will want to happen. However, in applications where the hover() handling only adds emphasis (tooltip, glow, etc.) to the hovered element, it might make more sense to skip the event all together touch devices, going strait to the onclick handler.

I know how to listen specifically for touchstart and touchend events, allowing me to tailor the touch user experience. This is a valid solution to my problem, but I am hoping that there might be an "easier" way around this. I am imagining a method similar to hover() in its signature, only implemented in a way that only attaches the provided event handlers on non-touch devices.

Does jQuery have such method? Any plugins? Or am I overlooking something here?


1 Behavior confirmed on iPad, iPhone and a few Android handsets.

2 Run this JsFiddle demo on a desktop vs touch device to see what I am talking about.

like image 897
Jørn Schou-Rode Avatar asked Dec 30 '11 11:12

Jørn Schou-Rode


2 Answers

I am always wondering, too, what will happen doing so on the hybrid devices that support touch AND click/hover events. In this case once touched there will be no longer any hover or click events on the page available. What is when the user one time touches the screen (for what reason ever) and then might want to return using his mouse or touchpad? The site is broken then for him (at least if he not decides to consequently continue with touches).

I personally use the flag script below and check even the mouse enter and mouse leave events for eventual touches. I don’t know if this is a good technique. In my case it works quite fine.

var touched = false;

$("#someElement")
    .mouseenter( function() {
        if ( !touched ) {
            // some hover action
            // also secure to be in NO WAY triggered on touch device
        };
    }
    .mouseleave( function() {
        if ( !touched ) {
            // some mouse leave reset hover action
            // also secure to be in NO WAY triggered on touch device
        };
    }
    .click( function() {
        if ( !touched ) {
            // do something
            // no double trigger on touch device
        };
    }
    .on( 'touchstart', function() {
        touched = true;
        setTimeout( function() {
            touched = false;
        }, 300 );
        // do touchstart stuff (similar to click or not)
    };

I am not a professional coder. Any of those are invited to optimize that. On my webpage this seems to be the only way to avoid hidden (double) triggers on touch device (iPad tested).

I also know that this is not quite the answer to the question more an addition to the first answer (and its good comment) which in my eyes does not fully solve the hybrid problem even if widely in use.

Anyway hope this helps in its way.

like image 191
Garavani Avatar answered Oct 22 '22 09:10

Garavani


I recommend using Modernizr to detect the touchyness of the device and simply not bind the hover handler unless the html element has the "no-touch" class:

$('selector').click(...)
$('.no-touch selector').hover(...)

check out http://jsfiddle.net/juYf8/17/

like image 42
tobyodavies Avatar answered Oct 22 '22 07:10

tobyodavies