Detect IF hovering over element with jQuery

I'm not looking for an action to call when hovering, but instead a way to tell if an element is being hovered over currently. For instance:

$('#elem').mouseIsOver(); // returns true or false

Is there a jQuery method that accomplishes this?

Answers:

Answer

Original (And Correct) Answer:

You can use is() and check for the selector :hover.

var isHovered = $('#elem').is(":hover"); // returns true or false

Example: http://jsfiddle.net/Meligy/2kyaJ/3/

(This only works when the selector matches ONE element max. See Edit 3 for more)

.

Edit 1 (June 29, 2013): (Applicable to jQuery 1.9.x only, as it works with 1.10+, see next Edit 2)

This answer was the best solution at the time the question was answered. This ':hover' selector was removed with the .hover() method removal in jQuery 1.9.x.

Interestingly a recent answer by "allicarn" shows it's possible to use :hover as CSS selector (vs. Sizzle) when you prefix it with a selector $($(this).selector + ":hover").length > 0, and it seems to work!

Also, hoverIntent plugin mentioned in a another answer looks very nice as well.

Edit 2 (September 21, 2013): .is(":hover") works

Based on another comment I have noticed that the original way I posted, .is(":hover"), actually still works in jQuery, so.

  1. It worked in jQuery 1.7.x.

  2. It stopped working in 1.9.1, when someone reported it to me, and we all thought it was related to jQuery removing the hover alias for event handling in that version.

  3. It worked again in jQuery 1.10.1 and 2.0.2 (maybe 2.0.x), which suggests that the failure in 1.9.x was a bug or so not an intentional behaviour as we thought in the previous point.

If you want to test this in a particular jQuery version, just open the JSFidlle example at the beginning of this answer, change to the desired jQuery version and click "Run". If the colour changes on hover, it works.

.

Edit 3 (March 9, 2014): It only works when the jQuery sequence contains a single element

As shown by @Wilmer in the comments, he has a fiddle which doesn't even work against jQuery versions I and others here tested it against. When I tried to find what's special about his case I noticed that he was trying to check multiple elements at a time. This was throwing Uncaught Error: Syntax error, unrecognized expression: unsupported pseudo: hover.

So, working with his fiddle, this does NOT work:

var isHovered = !!$('#up, #down').filter(":hover").length;

While this DOES work:

var isHovered = !!$('#up,#down').
                    filter(function() { return $(this).is(":hover"); }).length;

It also works with jQuery sequences that contain a single element, like if the original selector matched only one element, or if you called .first() on the results, etc.

This is also referenced at my JavaScript + Web Dev Tips & Resources Newsletter.

Answer

It does not work in jQuery 1.9. Made this plugin based on user2444818's answer.

jQuery.fn.mouseIsOver = function () {
    return $(this).parent().find($(this).selector + ":hover").length > 0;
}; 

http://jsfiddle.net/Wp2v4/1/

Answer

Set a flag on hover:

var over = false;
$('#elem').hover(function() {
  over = true;
},
function () {
  over = false;
});

Then just check your flag.

Answer

Couple updates to add after working on this subject for a while:

  1. all solutions with .is(":hover") break on jQuery 1.9.1
  2. The most likely reason to check if the mouse is still over an element is to attempt to prevent events firing over each other. For example, we were having issues with our mouseleave being triggered and completed before our mouseenter event even completed. Of course this was because of a quick mouse movement.

We used hoverIntent https://github.com/briancherne/jquery-hoverIntent to solve the issue for us. Essentially it triggers if the mouse movement is more deliberate. (one thing to note is that it will trigger on both mouse entering an element and leaving - if you only want to use one pass the constructor an empty function )

Answer

You can filter your elment from all hovered elements. Problematic code:

element.filter(':hover')

Save code:

jQuery(':hover').filter(element)

To return boolean:

jQuery(':hover').filter(element).length===0
Answer

Expanding on @Mohamed's answer. You could use a little encapsulation

Like this:

jQuery.fn.mouseIsOver = function () {
    if($(this[0]).is(":hover"))
    {
        return true;
    }
    return false;
}; 

Use it like:

$("#elem").mouseIsOver();//returns true or false

Forked the fiddle: http://jsfiddle.net/cgWdF/1/

Answer

I like the first response, but for me it's weird. When attempting to check just after page load for the mouse, I have to put in at least a 500 millisecond delay for it to work:

$(window).on('load', function() {
    setTimeout(function() {
        $('img:hover').fadeOut().fadeIn();
    }, 500);
});

http://codepen.io/molokoloco/pen/Grvkx/

Answer

Setting a flag per kinakuta's answer seems reasonable, you can put a listener on the body so you can check if any element is being hovered over at a particular instant.

However, how do you want to deal with child nodes? You should perhaps check if the element is an ancestor of the currently hovered element.

<script>

var isOver = (function() {
  var overElement;
  return {

    // Set the "over" element
    set: function(e) {
      overElement = e.target || e.srcElement;
    },

    // Return the current "over" element
    get: function() {
      return overElement;    
    },

    // Check if element is the current "over" element
    check: function(element) {
      return element == overElement;
    },

    // Check if element is, or an ancestor of, the 
    // current "over" element
    checkAll: function(element) {
      while (overElement.parentNode) {
         if (element == overElement) return true;
         overElement = overElement.parentNode;
      }
      return false;
    }
  };
}());


// Check every second if p0 is being hovered over
window.setInterval( function() {
  var el = document.getElementById('p0');
  document.getElementById('msg').innerHTML = isOver.checkAll(el);
}, 1000);


</script>

<body onmouseover="isOver.set(event);">
  <div>Here is a div
    <p id="p0">Here is a p in the div<span> here is a span in the p</span> foo bar </p>
  </div>
  <div id="msg"></div>
</body>
Answer

Use:

var hovered = $("#parent").find("#element:hover").length;

jQuery 1.9+

Answer

The accepted answer didn't work for me on JQuery 2.x .is(":hover") returns false on every call.

I ended up with a pretty simple solution that works:

function isHovered(selector) {

    return $(selector+":hover").length > 0

}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.