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

有没有快速的&简单的方法做到这一点在jQuery,我错过了?

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

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

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

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

删除淡出的回调数据。

使用mouseenter/mouseleave实际上成本更低,因为当child鼠标悬停/鼠标退出触发时,它们不会触发菜单。

谢谢你们俩。在某种程度上,我不得不放弃尝试检测鼠标是否仍然停留在元素上。我知道这是可能的,但可能需要太多的代码来实现。

我花了一点时间,但我接受了你们的建议,并想出了适合我的办法。

下面是一个简单的例子:

$("[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,这允许一些非常漂亮的鼠标悬停帮助工具提示。顺便说一下,我需要在鼠标退出时延迟,因为复选框和文本之间的微小间隙导致当你移动鼠标时帮助会闪烁。但这就像一个魔法。我也为焦点/模糊事件做了类似的事情。

如果任何子div具有特定的类,则可以使用jQuery进行测试。然后,当你把鼠标移到某个div上或移出某个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"));
}
});


扩展什么'Happytime harry'说,一定要使用.data() jquery函数来存储超时id。这样,当'mouseenter'在同一个元素上被触发时,你可以很容易地检索超时id,允许你消除触发,让你的工具提示消失。

这段代码说明了快乐时光哈利和我想说的。当鼠标进入时,会出现一个工具提示,当鼠标离开时,它会为工具提示的消失设置一个延迟。如果鼠标在触发延迟之前输入了相同的元素,那么我们使用之前存储的数据在触发器触发之前销毁它。

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

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

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


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

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

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

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.t target)。

我正在考虑在dragLeave处理程序中使用这种方法,以确认dragLeave事件不是由进入子元素触发的。如果您没有以某种方式检查您是否仍然在父元素中,那么您可能会错误地执行仅在真正离开父元素时才执行的操作。

编辑:这是一个很好的想法,但并不能始终如一地工作。也许要做一些小调整。

我需要的东西正是这样的(在一个更复杂的环境和解决方案有很多'mouseenter '和'mouseleaves'没有正常工作),所以我创建了一个小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上进行了测试,运行正常。

我采用了SLaks的想法,并将其包装在小类中。

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

警告:is(':hover')在jquery 1.8+中已弃用。参见这篇文章的解决方案。

你也可以使用这个答案:https://stackoverflow.com/a/6035278/8843来测试鼠标是否悬停在一个元素上:

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

只是供未来的发现者参考。

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

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

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

jsFiddle found here

中看到

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

提琴

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

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

一个干净优雅的悬停检查:

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

我不能使用上面的任何建议 为什么我更喜欢我的解决方案?
这个方法检查鼠标是否在您选择的任何时间的元素上 Mouseenter:徘徊很酷,但是只有当你移动鼠标时mouseenter才会触发,而不是当元素在鼠标下面移动时触发 :盘旋很可爱,但是…即< / p >

所以我这样做:

没有1。存储鼠标x, y位置,当你需要移动时,
没有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");
}
});
jquery中可以使用is(':visible'); 对于$('.item:hover'),它也在Jquery中工作

这是一个HTM代码片段:

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


});

这就是我说的:)

上面Arthur Goldsmith的回答很流行也很有用:如果你在IE中将鼠标从一个元素移动到另一个元素(至少在IE 9之前),如果新元素的背景是透明的(默认情况下是透明的),你可能会遇到一些麻烦。我的解决办法是给新元素一个透明的背景图像。

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

这将是最简单的方法!

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

我已经在另一个问题中回答了这个问题,以及你可能需要的所有细节:

用jQuery检测IF悬停在元素上(在撰写本文时有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开始测试的。

因为我不能评论,所以我将写这作为一个答案!

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

":hover"是一个css选择器,当像$("#elementId").is(":hover")这样使用时,它确实与事件一起被删除了,但它的意思是它真的与jQuery事件无关。

如果编码为$("#elementId:hover"),则只有当鼠标悬停时,元素才会被选中。上面的语句将适用于所有jQuery版本,因为你选择这个元素与纯合法的css选择。

另一方面,事件悬停

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

在jQuery 1.8的时候已经被弃用了。

当使用事件名称“hover”时,事件子系统将对其进行转换 在事件字符串中输入“mouseenter mouseleave”。这很烦人 几个原因:< / p >

语义:鼠标悬停和鼠标进出不一样 一个元素,它意味着一定程度的减速或延迟 射击。事件名称:事件。附加处理程序返回的类型为 不是悬停,而是鼠标进入或鼠标离开。没有其他事件可以 这一点。使用“hover”名称:不可能附加 事件,并使用.trigger("hover")触发它。的 文档已经称这个名字为“强烈反对新代码”,我想 喜欢在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安迪

这里有一个技术,它不依赖于jquery,并使用本机DOM matches API。它使用厂商前缀支持回到IE9的浏览器。详见caniuse.com上的Matchesselector

首先创建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');

下面是一个函数,它可以帮助你检查鼠标是否在元素中。惟一需要做的是调用函数,在这里可以有一个与鼠标相关的活动eventtobject。就像这样:

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

使用evt.originalEvent.composedPath()

MouseEvent给出了鼠标最近与之交互的HTMLElement的数组。最后一个元素是最外层的(即它总是Window)。

MouseEvent composedPath()示例如下:

一个显示HTML元素数组的控制台

通过检查该数组中是否存在可点击的元素,您将知道是否在特定元素上有鼠标悬停…

$(window).on("mouseup", onMouseUp);
const $someButton = $("a.yourButton");


function onMouseUp(evt) {
const path = evt.originalEvent.composedPath();
if(path.indexOf($someButton[0]) !== -1){
// released mouse over button
}else{
// did not release mouse over button
}
}