Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery why does :hover work only once?

I have been using the following snippet to determine in Chrome/Safari & FF if a user is hovering over an anchor.

var isURL = $("a", obj).is(":hover");

I've seen varying posts about :hover being a CSS selector but what I can't get my head around is why the code returns true if there is 1 link within obj but throws a javascript unrecognized expression hover error if there are 2 or more.

Here is a fiddle of :hover working: - http://jsfiddle.net/2kyaJ/122/

Same but multiple elements (not working): - http://jsfiddle.net/2kyaJ/121/

Can anyone explain this to me?

By the way I have seen this... How do I check if the mouse is over an element in jQuery?

4 years on is this still the best and seemingly only way to determine if a user is hovering over an element? If yes would anyone be able to provide an example?

Edit: had to go fishing for exactly what I needed but it turns out this, as simple as it is works really well.

I am currently using it inside a plugin with jQuery 1.9.1 where I am triggering an animation on a mouseover of a parent element (obj). Hope someone else finds it useful in future. Use .length instead of .size as .size is deprecated from version 1.8 onwards.

        function isMouseOver() {
            if ($('a:hover', obj).length != 0) {
                return true;
            } else {
                return false;
            }                           
        }

Usage:

var isURL = isMouseOver();
like image 610
KryptoniteDove Avatar asked Feb 26 '13 01:02

KryptoniteDove


3 Answers

:hover is not documented at http://api.jquery.com/ -- as such I wouldn't trust it to work in any particular way. The problem seems to be that Sizzle is getting confused by this pseudo-selector when there is more than one element to iterate over in the collection, although I can't really tell whey by looking at the code.

The fact that it is even working in your first example seems to be a bug: http://jsfiddle.net/2kyaJ/122/ -- it does not work with jQuery 1.9

As for how to tell if an element is hovered -- I'm not sure what circumstances you would need to do that. Instead, it's better to take action when a hover is triggered. You can bind to a "hover-like" event with mouseover and mouseenter. There is, of course, the CSS pseudo-selector :hover.

like image 155
Explosion Pills Avatar answered Oct 23 '22 02:10

Explosion Pills


Try this fiddle http://jsfiddle.net/2rU4U/:

setInterval(function(){
    var $sample = $(".sample");

    $sample.each(function(index) {
        if($(this).is(":hover")) {
           $(this).css("background", "yellow");
        }
        else {
           $(this).css("background", "");
        }
    });  
}, 200);

As mentioned in the comment above, this respects the fact that a collection of elements might be returned, not just a single one. Might cause quite a bit of overhead with lots of elements of course...!

like image 39
J Griffiths Avatar answered Oct 23 '22 02:10

J Griffiths


As to why it doesn't work your way, I'd say it could be a bug or it could be that it's undocumented. I don't really know.

However, here's an example that works in jQuery 1.7.1, 1.9, and 2.0.0b1: http://jsfiddle.net/2kyaJ/125/

Basically instead of using .is() you can query for all hovered elements and then check that there is at least one match ($(".sample:hover").length rather than $(".sample").is(":hover")).

I got the impression you wanted to highlight all the .sample elements when any of them are hovered, hence the first jsfiddle. However, if you only want to highlight the hovered element, you could try something like this: http://jsfiddle.net/2kyaJ/126/

Also, if you're simply looking to bind something to the hover event, rather than checking more or less every 0.2 seconds you could just use the .hover() function: http://jsfiddle.net/2kyaJ/127/

like image 23
redbmk Avatar answered Oct 23 '22 03:10

redbmk