How do I check if the mouse is over an element in jQuery?

JqueryMouseover

Jquery Problem Overview


Is there a quick & easy way to do this in jQuery that I'm missing?

I don't want to use the mouseover event because I'm already using it for something else. I just need to know if the mouse is over an element at a given moment.

I'd like to do something like this, if only there was an "IsMouseOver" function:

function hideTip(oi) {
	setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}

Jquery Solutions


Solution 1 - Jquery

This code illustrates what happytime harry and I are trying to say. When the mouse enters, a tooltip comes out, when the mouse leaves it sets a delay for it to disappear. If the mouse enters the same element before the delay is triggered, then we destroy the trigger before it goes off using the data we stored before.

$("someelement").mouseenter(function(){
    clearTimeout($(this).data('timeoutId'));
    $(this).find(".tooltip").fadeIn("slow");
}).mouseleave(function(){
    var someElement = $(this),
        timeoutId = setTimeout(function(){
            someElement.find(".tooltip").fadeOut("slow");
        }, 650);
    //set the timeoutId, allowing us to clear this trigger if the mouse comes back over
    someElement.data('timeoutId', timeoutId); 
});

Solution 2 - Jquery

A clean and elegant hover check:

if ($('#element:hover').length != 0) {
    // do something ;)
}

Solution 3 - Jquery

WARNING: is(':hover') is deprecated in jquery 1.8+. See this post for a solution.

You can also use this answer : https://stackoverflow.com/a/6035278/8843 to test if the mouse is hover an element :

$('#test').click(function() {
    if ($('#hello').is(':hover')) {
        alert('hello');
    }
});

Solution 4 - Jquery

Set a timeout on the mouseout to fadeout and store the return value to data in the object. Then onmouseover, cancel the timeout if there is a value in the data.

Remove the data on callback of the fadeout.

It is actually less expensive to use mouseenter/mouseleave because they do not fire for the menu when children mouseover/mouseout fire.

Solution 5 - Jquery

You can use jQuery's hover event to keep track manually:

$(...).hover(
    function() { $.data(this, 'hover', true); },
    function() { $.data(this, 'hover', false); }
).data('hover', false);

if ($(something).data('hover'))
    //Hovered!

Solution 6 - Jquery

I needed something exactly as this (in a little more complex environment and the solution with a lot of 'mouseenters' and 'mouseleaves' wasnt working properly) so i created a little jquery plugin that adds the method ismouseover. It has worked pretty well so far.

//jQuery ismouseover  method
(function($){ 
	$.mlp = {x:0,y:0}; // Mouse Last Position
	function documentHandler(){
		var $current = this === document ? $(this) : $(this).contents();
		$current.mousemove(function(e){jQuery.mlp = {x:e.pageX,y:e.pageY}});
		$current.find("iframe").load(documentHandler);
	}
	$(documentHandler);
	$.fn.ismouseover = function(overThis) {  
		var result = false;
		this.eq(0).each(function() {  
				var $current = $(this).is("iframe") ? $(this).contents().find("body") : $(this);
				var offset = $current.offset();				
				result = 	offset.left<=$.mlp.x && offset.left + $current.outerWidth() > $.mlp.x &&
							offset.top<=$.mlp.y && offset.top + $current.outerHeight() > $.mlp.y;
		});  
		return result;
	};  
})(jQuery);

Then in any place of the document yo call it like this and it returns true or false:

$("#player").ismouseover()

I tested it on IE7+, Chrome 1+ and Firefox 4 and is working properly.

Solution 7 - Jquery

In jQuery you can use .is(':hover'), so

function IsMouseOver(oi)
{
   return $(oi).is(':hover');
}

would now be the most concise way to provide the function requested in the OP.

Note: The above does not work in IE8 or lower

As less succinct alternative that does work in IE8 (if I can trust IE9's IE8 modus), and does so without triggering $(...).hover(...) all over the place, nor requires knowing a selector for the element (in which case Ivo's answer is easier):

function IsMouseOver(oi)
{
    return oi.length && 
           oi.parent()
             .find(':hover')
             .filter(function(s){return oi[0]==this})
             .length > 0;
}

Solution 8 - Jquery

I took SLaks' idea and wrapped it in a small class.

function HoverWatcher(selector){
  this.hovering = false;
  var self = this; 
   
  this.isHoveringOver = function() { 
    return self.hovering; 
  } 
     
    $(selector).hover(function() { 
      self.hovering = true; 
    }, function() { 
      self.hovering = false; 
    }) 
} 
 
var box1Watcher = new HoverWatcher('#box1');
var box2Watcher = new HoverWatcher('#box2');
 
 
 
$('#container').click(function() {
  alert("box1.hover = " + box1Watcher.isHoveringOver() +
        ", box2.hover = " + box2Watcher.isHoveringOver());
});

Solution 9 - Jquery

> JUST FYI for future finders of this.

I made a jQuery plugin that can do this and a lot more. In my plugin, to get all elements the cursor is currently hovered over, simply do the following:

$.cursor("isHover"); // will return jQ object of all elements the cursor is 
                     // currently over & doesn't require timer

As I mentioned, it also has alot of other uses as you can see in the

jsFiddle found here

Solution 10 - Jquery

As I cannot comment, so I will write this as an answer!

Please understand the difference between css selector ":hover" and the hover event!

":hover" is a css selector and was indeed removed with the event when used like this $("#elementId").is(":hover"), but in it's meaning it has really nothing to do with the jQuery event hover.

if you code $("#elementId:hover"), the element will only be selected when you hover with the mouse. the above statement will work with all jQuery versions as your selecting this element with pure and legit css selection.

On the other hand the event hover which is

$("#elementId").hover(
     function() { 
         doSomething(); 
     }
); 

is indeed deprecaded as jQuery 1.8 here the state from jQuery website:

> When the event name "hover" is used, the event subsystem converts it > to "mouseenter mouseleave" in the event string. This is annoying for > several reasons: > > Semantics: Hovering is not the same as the mouse entering and leaving > an element, it implies some amount of deceleration or delay before > firing. Event name: The event.type returned by the attached handler is > not hover, but either mouseenter or mouseleave. No other event does > this. Co-opting the "hover" name: It is not possible to attach an > event with the name "hover" and fire it using .trigger("hover"). The > docs already call this name "strongly discouraged for new code", I'd > like to deprecate it officially for 1.8 and eventually remove it.

Why they removed the usage is(":hover") is unclear but oh well, you can still use it like above and here is a little hack to still use it.

(function ($) {
   /** 
    * :hover selector was removed from jQuery 1.8+ and cannot be used with .is(":hover") 
    * but using it in this way it works as :hover is css selector! 
    *
    **/
    $.fn.isMouseOver = function() {
        return $(this).parent().find($(this).selector + ":hover").length > 0;
    };
})(jQuery);

Oh and I would not recomment the timeout version as this brings a lot of complexity, use timeout functionalities for this kind of stuff if there is no other way and believe me, in 95% percent of all cases there is another way!

Hope I could help a couple people out there.

Greetz Andy

Solution 11 - Jquery

Thanks to both of you. At some point I had to give up on trying to detect if the mouse was still over the element. I know it's possible, but may require too much code to accomplish.

It took me a little while but I took both of your suggestions and came up with something that would work for me.

Here's a simplified (but functional) example:

$("[HoverHelp]").hover (
	function () {
		var HelpID = "#" + $(this).attr("HoverHelp");
		$(HelpID).css("top", $(this).position().top + 25);
		$(HelpID).css("left", $(this).position().left);
		$(HelpID).attr("fadeout", "false");
		$(HelpID).fadeIn();
	},
	function () {
		var HelpID = "#" + $(this).attr("HoverHelp");
		$(HelpID).attr("fadeout", "true");
		setTimeout(function() { if ($(HelpID).attr("fadeout") == "true") $(HelpID).fadeOut(); }, 100);
	}
);

And then to make this work on some text this is all I have to do:

<div id="tip_TextHelp" style="display: none;">This help text will show up on a mouseover, and fade away 100 milliseconds after a mouseout.</div>

This is a <span class="Help" HoverHelp="tip_TextHelp">mouse over</span> effect.

Along with a lot of fancy CSS, this allows some very nice mouseover help tooltips. By the way, I needed the delay in the mouseout because of tiny gaps between checkboxes and text that was causing the help to flash as you move the mouse across. But this works like a charm. I also did something similar for the focus/blur events.

Solution 12 - Jquery

You can test with jQuery if any child div has a certain class. Then by applying that class when you mouse over and out out a certain div, you can test whether your mouse is over it, even when you mouse over a different element on the page Much less code this way. I used this because I had spaces between divs in a pop-up, and I only wanted to close the pop up when I moved off of the pop up, not when I was moving my mouse over the spaces in the pop up. So I called a mouseover function on the content div (which the pop up was over), but it would only trigger the close function when I moused-over the content div, AND was outside the pop up!

$(".pop-up").mouseover(function(e) { $(this).addClass("over"); });

$(".pop-up").mouseout(function(e) { $(this).removeClass("over"); });

$("#mainContent").mouseover(function(e){ if (!$(".expanded").hasClass("over")) { Drupal.dhtmlMenu.toggleMenu($(".expanded")); } });

Solution 13 - Jquery

I see timeouts used for this a lot, but in the context of an event, can't you look at coordinates, like this?:

function areXYInside(e){  
        var w=e.target.offsetWidth;
        var h=e.target.offsetHeight;
        var x=e.offsetX;
        var y=e.offsetY;
        return !(x<0 || x>=w || y<0 || y>=h);
}

Depending on context, you may need to make sure (this==e.target) before calling areXYInside(e).

fyi- I'm looking at using this approach inside a dragLeave handler, in order to confirm that the dragLeave event wasn't triggered by going into a child element. If you don't somehow check that you're still inside the parent element, you might mistakenly take action that's meant only for when you truly leave the parent.

EDIT: this is a nice idea, but does not work consistently enough. Perhaps with some small tweaks.

Solution 14 - Jquery

This would be the easiest way of doing it!

  function(oi) 
  {
   if(!$(oi).is(':hover')){$(oi).fadeOut(100);}
  }

Solution 15 - Jquery

Here's a technique which doesn't rely on jquery and uses the native DOM matches API. It uses vendor prefixes to support browsers going back to IE9. See matchesselector on caniuse.com for full details.

First create the matchesSelector function, like so:

var matchesSelector = (function(ElementPrototype) {
var fn = ElementPrototype.matches ||
          ElementPrototype.webkitMatchesSelector ||
          ElementPrototype.mozMatchesSelector ||
          ElementPrototype.msMatchesSelector;

return function(element, selector) {
  return fn.call(element, selector);
};

})(Element.prototype);

Then, to detect hover:

var mouseIsOver = matchesSelector(element, ':hover');

Solution 16 - Jquery

I have answered this in another question, with all details you may need:

https://stackoverflow.com/questions/8981463/detect-if-hovering-over-element-with-jquery/8981521#8981521 (has 99 upvotes at the time of writing)

Basically, you can do something like:

var ishovered = oi.is(":hover");

This works only if oi is a jQuery object containing a single element. If there are multiple elements matched, you need to apply to each element, for example:

var hoveredItem = !!$('ol>li').filter(function() { return $(this).is(":hover"); });
                  // not .filter(':hover'), as we can't apply :hover on multiple elements

This was tested starting jQuery 1.7.

Solution 17 - Jquery

Here is a function which helps you check if the mouse is inside an element or not. The only thing you should do is to call the function where you can have a live mouse-associated EventObject. something like this:

$("body").mousemove(function(event){
     element_mouse_is_inside($("#mycontainer", event, true, {});
});

You can see the source code here in github or at the bottom of the post:

https://github.com/mostafatalebi/ElementsLocator/blob/master/elements_locator.jquery.js

function element_mouse_is_inside  (elementToBeChecked, mouseEvent, with_margin, offset_object)
{
    if(!with_margin)
    {
        with_margin = false;
    }
    if(typeof offset_object !== 'object')
    {
        offset_object = {};
    }
    var elm_offset = elementToBeChecked.offset();
    var element_width = elementToBeChecked.width();
    element_width += parseInt(elementToBeChecked.css("padding-left").replace("px", ""));
    element_width += parseInt(elementToBeChecked.css("padding-right").replace("px", ""));
    var element_height = elementToBeChecked.height();
    element_height += parseInt(elementToBeChecked.css("padding-top").replace("px", ""));
    element_height += parseInt(elementToBeChecked.css("padding-bottom").replace("px", ""));
    if( with_margin)
    {
        element_width += parseInt(elementToBeChecked.css("margin-left").replace("px", ""));
        element_width += parseInt(elementToBeChecked.css("margin-right").replace("px", ""));
        element_height += parseInt(elementToBeChecked.css("margin-top").replace("px", ""));
        element_height += parseInt(elementToBeChecked.css("margin-bottom").replace("px", ""));
    }

    elm_offset.rightBorder = elm_offset.left+element_width;
    elm_offset.bottomBorder = elm_offset.top+element_height;

    if(offset_object.hasOwnProperty("top"))
    {
        elm_offset.top += parseInt(offset_object.top);
    }
    if(offset_object.hasOwnProperty("left"))
    {
        elm_offset.left += parseInt(offset_object.left);
    }
    if(offset_object.hasOwnProperty("bottom"))
    {
        elm_offset.bottomBorder += parseInt(offset_object.bottom);
    }
    if(offset_object.hasOwnProperty("right"))
    {
        elm_offset.rightBorder += parseInt(offset_object.right);
    }
    var mouseX = mouseEvent.pageX;
    var mouseY = mouseEvent.pageY;

    if(  (mouseX > elm_offset.left && mouseX < elm_offset.rightBorder)
        && (mouseY > elm_offset.top && mouseY < elm_offset.bottomBorder) )
    {
        return true;
    }
    else
    {
        return false;
    }
}

Solution 18 - Jquery

Extending on what 'Happytime harry' said, be sure to use the .data() jquery function to store the timeout id. This is so that you can retrieve the timeout id very easily when the 'mouseenter' is triggered on that same element later, allowing you to eliminate the trigger for your tooltip to disappear.

Solution 19 - Jquery

You can use jQuery's mouseenter and mouseleave events. You can set a flag when the mouse enters the desired area and unset the flag when it leaves the area.

Solution 20 - Jquery

$(document).hover(function(e) {
    alert(e.type === 'mouseenter' ? 'enter' : 'leave');
});

FIDDLE

Solution 21 - Jquery

I combined ideas from this topic and came up with this, which is useful for showing/hiding a submenu:

$("#menu_item_a").mouseenter(function(){
   clearTimeout($(this).data('timeoutId'));
   $("#submenu_a").fadeIn("fast");
}).mouseleave(function(){
   var menu_item = $(this);

   var timeoutId = setTimeout(function(){
      if($('#submenu_a').is(':hover'))
      {
        clearTimeout(menu_item.data('timeoutId'));
      }
      else
      {
        $("#submenu_a").fadeOut("fast");
      }
   }, 650);

    menu_item.data('timeoutId', timeoutId); 
});

 $("#submenu_a").mouseleave(function(){
   $(this).fadeOut("fast");
 });

Seems to work for me. Hope this helps someone.

EDIT: Now realizing this approach is not working correctly in IE.

Solution 22 - Jquery

I couldn't use any of the suggestions above.
Why I prefer my solution?
This method checks if mouse is over an element at any time chosen by You.
Mouseenter and :hover are cool, but mouseenter triggers only if you move the mouse, not when element moves under the mouse.
:hover is pretty sweet but ... IE

So I do this:

No 1. store mouse x, y position every time it's moved when you need to,
No 2. check if mouse is over any of elements that match the query do stuff ... like trigger a mouseenter event

// define mouse x, y variables so they are traced all the time
var mx = 0;	//  mouse X position
var my = 0;	//  mouse Y position

// update mouse x, y coordinates every time user moves the mouse
$(document).mousemove(function(e){
    mx = e.pageX;
    my = e.pageY;
});

// check is mouse is over an element at any time You need (wrap it in function if You need to)
$("#my_element").each(function(){
    boxX = $(this).offset().left;
    boxY = $(this).offset().top;
    boxW = $(this).innerWidth();
    boxH = $(this).innerHeight();
    if ((boxX <= mx) &&
        (boxX + 1000 >= mx) &&
        (boxY <= my) &&
        (boxY + boxH >= my))
    {
        // mouse is over it so you can for example trigger a mouseenter event
        $(this).trigger("mouseenter");
    }
});

Solution 23 - Jquery

Just a note about the popular and helpful Arthur Goldsmith answer above: If you're moving your mouse from one element to another in IE (at least until IE 9) you may have some trouble getting this to work correctly if the new element has a transparent background (which it would by default). My workaround was the give the new element a transparent background image.

Solution 24 - Jquery

You can use is(':visible'); in jquery And for $('.item:hover') it is working in Jquery also.

this is a htm code snnipet :

    <li class="item-109 deeper parent">
<a class="root" href="/Comsopolis/index.php/matiers"><span>Matiers</span></a>
<ul>
<li class="item-110 noAff">
<a class=" item sousMenu" href="/Comsopolis/index.php/matiers/tsdi">
<span>Tsdi</span>
</a>
</li>
<li class="item-111 noAff">
<a class="item" href="/Comsopolis/index.php/matiers/reseaux">
<span>Réseaux</span>
</a>
</li>
</ul>
</li>

and this is the JS Code :

$('.menutop > li').hover(function() {//,.menutop li ul

    $(this).find('ul').show('fast');
	
},function() {
	if($(this).find('ul').is(':hover'))
    $(this).hide('fast');
	
});

 $('.root + ul').mouseleave(function() {
	if($(this).is(':visible'))
    $(this).hide('fast');
	
});

this what i was talking about :)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve WorthamView Question on Stackoverflow
Solution 1 - JqueryArthur GoldsmithView Answer on Stackoverflow
Solution 2 - JqueryIvoView Answer on Stackoverflow
Solution 3 - JquerytalView Answer on Stackoverflow
Solution 4 - JquerymothmonstermanView Answer on Stackoverflow
Solution 5 - JquerySLaksView Answer on Stackoverflow
Solution 6 - JqueryIvan CastellanosView Answer on Stackoverflow
Solution 7 - JquerytowrView Answer on Stackoverflow
Solution 8 - Jqueryripper234View Answer on Stackoverflow
Solution 9 - JquerySpYk3HHView Answer on Stackoverflow
Solution 10 - JqueryPhenixView Answer on Stackoverflow
Solution 11 - JquerySteve WorthamView Answer on Stackoverflow
Solution 12 - JqueryNateView Answer on Stackoverflow
Solution 13 - JquerydloView Answer on Stackoverflow
Solution 14 - JqueryKareemView Answer on Stackoverflow
Solution 15 - JqueryAndrew NewdigateView Answer on Stackoverflow
Solution 16 - JqueryMeligyView Answer on Stackoverflow
Solution 17 - JqueryMostafa TalebiView Answer on Stackoverflow
Solution 18 - JqueryArthur GoldsmithView Answer on Stackoverflow
Solution 19 - JquerymikerobiView Answer on Stackoverflow
Solution 20 - JqueryyckartView Answer on Stackoverflow
Solution 21 - JqueryTwo PiersView Answer on Stackoverflow
Solution 22 - JqueryHyper MotionView Answer on Stackoverflow
Solution 23 - JqueryJishView Answer on Stackoverflow
Solution 24 - JqueryucefkhView Answer on Stackoverflow