代码之家  ›  专栏  ›  技术社区  ›  Steve Wortham

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

  •  257
  • Steve Wortham  · 技术社区  · 15 年前

    是否有快捷和快捷的方法;在jQuery中实现这一点的简单方法是我所缺少的?

    如果有一个“IsMouseOver”函数,我想这样做:

    function hideTip(oi) {
        setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
    }
    
    24 回复  |  直到 15 年前
        1
  •  271
  •   Community leo1    7 年前

    这段代码说明了什么 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); 
    });
    
        2
  •  265
  •   Ivo    12 年前

    干净优雅的悬停检查:

    if ($('#element:hover').length != 0) {
        // do something ;)
    }
    
        3
  •  127
  •   Community leo1    7 年前

    is(':hover') 在jquery 1.8+中不推荐使用。看见 this post 寻找解决办法。

    您也可以使用以下答案: https://stackoverflow.com/a/6035278/8843

    $('#test').click(function() {
        if ($('#hello').is(':hover')) {
            alert('hello');
        }
    });
    
        4
  •  100
  •   mothmonsterman    15 年前

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

    删除淡出回调时的数据。

    实际上,使用mouseenter/mouseleave的成本更低,因为当孩子们在mouseover/mouseout上点火时,它们不会为菜单点火。

        5
  •  34
  •   SLaks    13 年前

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

    $(...).hover(
        function() { $.data(this, 'hover', true); },
        function() { $.data(this, 'hover', false); }
    ).data('hover', false);
    
    if ($(something).data('hover'))
        //Hovered!
    
        6
  •  24
  •   Ivan Castellanos    12 年前

    //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+、Chrome1+和Firefox4上进行了测试,测试结果正常。

        7
  •  9
  •   towr    10 年前

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

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

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

    注:以上内容在IE8或更低版本中不起作用

    作为在IE8中工作的不那么简洁的替代方案(如果我可以信任IE9的IE8 MODU),并且这样做不会触发 $(...).hover(...)

    function IsMouseOver(oi)
    {
        return oi.length && 
               oi.parent()
                 .find(':hover')
                 .filter(function(s){return oi[0]==this})
                 .length > 0;
    }
    
        8
  •  7
  •   ripper234 Jonathan    13 年前

    我接受了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());
    });
    
        9
  •  6
  •   SpYk3HH    12 年前

    仅供未来发现者参考。

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

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

    jsFiddle found here

        10
  •  6
  •   Phenix    10 年前

    因为我不能评论,所以我将写下这篇文章作为回答!

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

    $("#elementId").is(":hover") ,但这意味着它实际上与jQuery事件悬停无关。

    $("#elementId:hover") ,仅当鼠标悬停时,才会选择该元素。上面的语句将适用于所有jQuery版本,因为您可以使用纯合法的css选择来选择此元素。

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

    确实被贬为jQuery 1.8,这里是jQuery网站的状态:

    到事件字符串中的“mouseenter mouseleave”。这对我来说很烦人 有几个原因:

    语义:悬停与鼠标进出不同 作为一个元素,它意味着之前的减速或延迟量 开火。事件名称:附加处理程序返回的Event.type为 不是悬停,而是mouseenter或mouseleave。没有其他活动能做到这一点 这选择“悬停”名称:无法附加 我想,文档已经把这个名字叫做“强烈反对新代码” 我想正式反对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%的病例有另一种方法

    希望我能帮助一些人。

    格里茨·安迪

        11
  •  2
  •   Steve Wortham    15 年前

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

    我花了一点时间,但我采纳了你的两个建议,想出了一些对我有用的办法。

    下面是一个简化(但功能性)的示例:

    $("[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,这允许一些非常好的鼠标悬停帮助工具提示。顺便说一句,我需要鼠标移出的延迟,因为复选框和文本之间的间隙很小,当你移动鼠标时,帮助会闪烁。但这很有魅力。我也为聚焦/模糊事件做了类似的事情。

        12
  •  2
  •   dlo    13 年前

    我经常看到超时用于此,但是在事件的上下文中,您不能像这样查看坐标吗

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

    仅供参考-我正在研究在dragLeave处理程序中使用这种方法,以确认dragLeave事件不是通过进入子元素触发的。如果不检查是否仍在父元素中,则可能会错误地采取仅适用于真正离开父元素时的操作。

    编辑:这是一个好主意,但不够一致。也许需要一些小的调整。

        13
  •  2
  •   Taryn user758618    12 年前

    您可以使用 jQuery

    $(".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"));
            }
        });
    
    
        14
  •  2
  •   Kareem    10 年前

    这将是最简单的方法!

      function(oi) 
      {
       if(!$(oi).is(':hover')){$(oi).fadeOut(100);}
      }
    
        15
  •  2
  •   Andrew Newdigate    9 年前

    这里有一种技术不依赖于jquery,而是使用本机DOM matches API . 它使用供应商前缀来支持返回IE9的浏览器。看见 matchesselector on caniuse.com 有关详细信息。

    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');
    
        16
  •  1
  •   Community leo1    7 年前

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

    Detect IF hovering over element with jQuery

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

    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
    

    这是从jQuery1.7开始测试的。

        17
  •  1
  •   Mostafa Talebi    8 年前

    这里有一个函数可以帮助您检查鼠标是否在元素内。您应该做的唯一一件事是调用函数,在该函数中可以有一个与实时鼠标关联的EventObject。大概是这样的:

    $("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;
        }
    }
    
        18
  •  0
  •   Arthur Goldsmith    15 年前

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

        19
  •  0
  •   mikerobi    14 年前

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

        20
  •  0
  •   Two Piers    12 年前

    我结合了本主题的想法,得出了以下结论,这对于显示/隐藏子菜单非常有用:

    $("#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中不能正常工作。

        21
  •  0
  •   Hyper Motion    12 年前

    我不能使用上面的任何建议。
    为什么我更喜欢我的解决方案?
    此方法检查鼠标是否位于 您选择的任何时间
    滑鼠 很酷,但mouseenter仅在移动鼠标时触发,而不是在元素在鼠标下移动时触发。
    :hover很可爱,但是。。。即

    所以我这样做:

    第一。 每次需要移动鼠标时,都会存储鼠标的x、y位置,
    二号。 检查鼠标是否位于任何与查询匹配的元素上。。。就像触发鼠标事件一样

    // 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");
        }
    });
    
        22
  •  0
  •   Jish    11 年前

        23
  •  0
  •   yckart Matthew Crumley    11 年前
    $(document).hover(function(e) {
        alert(e.type === 'mouseenter' ? 'enter' : 'leave');
    });
    

    FIDDLE

        24
  •  -1
  •   ucefkh    12 年前

    你可以用 is(':visible'); 在jquery中 对于$('.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');
    
    });
    

    这就是我所说的:)