如何检查鼠标是否在jQuery中的元素上?

时间:2009-08-13 17:51:16

标签: jquery mouseover

有没有快速的&在我缺少的jQuery中执行此操作的简单方法是什么?

我不想使用mouseover事件,因为我已经将它用于其他事情。我只需要知道鼠标在给定时刻是否在元素上。

如果只有“IsMouseOver”功能,我想做这样的事情:

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

24 个答案:

答案 0 :(得分:268)

此代码说明了happytime harry和我想说的内容。当鼠标进入时,工具提示出现,当鼠标离开时,它会设置延迟消失。如果鼠标在触发延迟之前输入相同的元素,那么我们会在使用之前存储的数据将其触发之前销毁该触发器。

$("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); 
});

答案 1 :(得分:232)

干净优雅的悬停检查:

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

答案 2 :(得分:121)

警告:jquery 1.8+中不推荐使用is(':hover')。有关解决方案,请参阅this post

您也可以使用此答案:https://stackoverflow.com/a/6035278/8843来测试鼠标是否悬停元素:

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

答案 3 :(得分:95)

将mouseout上的超时设置为淡出并将返回值存储到对象中的数据。然后onmouseover,如果数据中有值,则取消超时。

删除淡出回调的​​数据。

使用mouseenter / mouseleave实际上更便宜,因为当儿童鼠标悬停/鼠标移开时,它们不会触发菜单。

答案 4 :(得分:34)

您可以使用jQuery的hover事件来手动跟踪:

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

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

答案 5 :(得分:24)

我需要的东西与此完全相同(在一个更复杂的环境中,并且有很多'鼠标'和'鼠洞'的解决方案无法正常工作)所以我创建了一个小的jquery插件,添加了方法ismouseover。到目前为止它运作良好。

//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);

然后在文档的任何地方,你都这样称呼它,它返回true或false:

$("#player").ismouseover()

我在IE7 +,Chrome 1+和Firefox 4上进行了测试,并且运行正常。

答案 6 :(得分:10)

在jQuery中你可以使用.is(':hover'),所以

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

现在将是提供OP中所请求功能的最简洁方式。

注意:上述内容在IE8或更低版本

中无效

作为在IE8中工作的不那么简洁的替代品(如果我可以信任IE9的IE8模式),并且在不触发$(...).hover(...)的情况下这样做,也不需要知道元素的选择器(在这种情况下Ivo的答案更容易):

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

答案 7 :(得分:7)

我接受了SLaks的想法并将其包裹在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());
});

答案 8 :(得分:6)

  

仅供参考,因为未来的发现者。

我制作了一个jQuery插件,可以做到这一点,还有更多。在我的插件中,要获取光标当前悬停的所有元素,只需执行以下操作:

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

正如我所提到的,它还有很多其他用途,您可以在

jsFiddle found here

中看到

答案 9 :(得分:3)

由于我无法评论,所以我会写这个作为答案!

请理解css选择器“:hover”和悬停事件之间的区别!

“:hover”是一个css选择器,当使用像$("#elementId").is(":hover")这样的事件时,确实被删除了,但是它意味着它与jQuery事件悬停没有任何关系。

如果您编码$("#elementId:hover"),则只有在使用鼠标悬停时才会选择该元素。上面的语句将适用于所有jQuery版本,因为您选择了具有纯粹和合法的CSS选择的元素。

另一方面,事件悬停是

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

确实被jQuery 1.8作为jQuery 1.8在这里从jQuery网站中删除:

  

当使用事件名称“hover”时,事件子系统会​​对其进行转换   在事件字符串中“mouseenter mouseleave”。这很烦人   有几个原因:

     

语义:悬停与鼠标进入和离开不同   一个元素,它意味着之前的一些减速或延迟   射击。事件名称:附加的处理程序返回的event.type是   不是悬停,而是mouseenter或mouseleave。没有其他事件   这个。选择“悬停”名称:无法附加   名为“hover”的事件,并使用.trigger(“hover”)触发它。该   docs已经把这个名字称为“强烈劝阻新代码”,我会   喜欢正式弃用1.8并最终删除它。

为什么他们删除了用法(“:hover”)还不清楚,但是哦,你仍然可以像上面那样使用它,这里仍然有点使用它。

(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);

哦,我不推荐超时版本,因为带来了很多复杂性,如果没有别的办法可以使用这种东西的超时功能并相信我,在 95%的情况下还有另一种方式

希望我可以帮助那里的几个人。

Greetz Andy

答案 10 :(得分:2)

我看到很多时间用于此,但在事件的上下文中,你不能看看这样的坐标吗?:

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);
}

根据上下文,您可能需要在调用areXYInside(e)之前确保(this == e.target)。

fyi-我正在看一个在dragLeave处理程序中使用这种方法,以确认dragLeave事件不是通过进入子元素触发的。如果你没有以某种方式检查你是否仍然在父元素中,你可能会错误地采取仅仅在你真正离开父母时的行动。

编辑:这是一个不错的主意,但不能始终如一地运作。也许还有一些小调整。

答案 11 :(得分:2)

这是一种不依赖于jquery并使用原生DOM matches API的技术。它使用供应商前缀来支持浏览器返回IE9。有关详细信息,请参阅matchesselector on caniuse.com

首先创建matchesSelector函数,如下所示:

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);

然后,检测悬停:

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

答案 12 :(得分:2)

如果任何子div具有某个类,您可以使用jQuery进行测试。然后通过在鼠标上下移动某个div时应用该类,您可以测试鼠标是否在它上面,即使鼠标悬停在页面上的其他元素上也是如此。我使用了这个因为我在弹出窗口中有div之间的空格,我只想在弹出弹出窗口时关闭弹出窗口,而不是当我将鼠标移动到弹出窗口中的空格时。所以我在内容div(弹出窗口已经结束)上调用了鼠标悬停功能,但它只会在我对内容div进行鼠标悬停时触发关闭功能,并且在弹出窗口之外!


$(".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"));
        }
    });

答案 13 :(得分:2)

感谢你们两位。在某些时候,我不得不放弃尝试检测鼠标是否仍然在元素上。我知道这是可能的,但可能需要太多的代码来完成。

我花了一点时间,但我接受了你的两个建议,想出了一些对我有用的东西。

这是一个简化(但功能性)的例子:

$("[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);
    }
);

然后在一些文本上做这个工作,这就是我要做的全部:

<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.

除了很多花哨的CSS之外,这还允许一些非常好的鼠标悬停帮助工具提示。顺便说一句,我需要延迟鼠标输出,因为复选框和文本之间的间隙很小,导致帮助在鼠标移动时闪烁。但这就像一个魅力。我也为焦点/模糊事件做了类似的事情。

答案 14 :(得分:2)

这是最简单的方法!

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

答案 15 :(得分:1)

我已在另一个问题中回答了这个问题,并提供了您可能需要的所有细节:

Detect IF hovering over element with jQuery(在撰写本文时有99条赞成票)

基本上,您可以执行以下操作:

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

仅当oi是包含单个元素的jQuery对象时,此方法才有效。如果匹配了多个元素,则需要应用于每个元素,例如:

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

这是从jQuery 1.7开始测试的。

答案 16 :(得分:0)

这是一个帮助您检查鼠标是否在元素内部的函数。你唯一应该做的就是调用你可以拥有一个与鼠标相关的活动对象的函数。像这样的东西:

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

您可以在github或帖子底部看到源代码:

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;
    }
}

答案 17 :(得分:0)

关于上面流行且有用的Arthur Goldsmith答案的注释:如果你在IE中将鼠标从一个元素移动到另一个元素(至少在IE 9中),如果新的话,你可能会遇到一些麻烦element具有透明背景(默认情况下)。我的解决方法是给新元素一个透明的背景图像。

答案 18 :(得分:0)

我无法使用上述任何建议 为什么我更喜欢我的解决方案? 此方法检查鼠标是否在您选择的任何时间上的元素上方 鼠标中心:悬停很酷,但只有在移动鼠标时才会触发鼠标中心,而不是在元素在鼠标下移动时触发鼠标。
:悬停很可爱但是...... IE

所以我这样做:

否1。在您需要时每次移动时存储鼠标x,y位置,
No 2。检查鼠标是否在与查询匹配的任何元素上方执行操作...例如触发mouseenter事件

// 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");
    }
});

答案 19 :(得分:0)

我结合了这个主题的想法并提出了这个,这对于显示/隐藏子菜单很有用:

$("#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");
 });

似乎适合我。希望这有助于某人。

编辑:现在意识到这种方法在IE中无法正常工作。

答案 20 :(得分:0)

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

FIDDLE

答案 21 :(得分:0)

您可以使用jQuery的mouseenter和mouseleave事件。您可以在鼠标进入所需区域时设置标记,并在标记离开该区域时取消设置标记。

答案 22 :(得分:0)

扩展'Happytime harry'所说的,一定要使用.data()jquery函数来存储超时ID。这样,当稍后在同一元素上触发'mouseenter'时,您可以非常轻松地检索超时ID,从而消除工具提示消失的触发器。

答案 23 :(得分:-1)

您可以在jquery中使用is(':visible'); 而对于$('。item:hover'),它也在Jquery工作。

这是一个htm代码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>

这是JS代码:

$('.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');

});

这就是我所说的:)