有没有一种快速简便的方法可以在我缺少的 jQuery 中做到这一点?
我不想使用 mouseover 事件,因为我已经将它用于其他事情。我只需要知道鼠标在给定时刻是否在一个元素上。
我想做这样的事情,只要有一个“IsMouseOver”功能:
function hideTip(oi) {
setTimeout(function() { if (!IsMouseOver(oi)) $(oi).fadeOut(); }, 100);
}
这段代码说明了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);
});
干净优雅的悬停检查:
if ($('#element:hover').length != 0) {
// do something ;)
}
在 mouseout 上设置超时以淡出并将返回值存储到对象中的数据中。然后onmouseover,如果数据中有值则取消超时。
删除淡出回调的数据。
使用 mouseenter/mouseleave 实际上更便宜,因为当儿童 mouseover/mouseout 触发时,它们不会触发菜单。
您可以使用 jQuery 的hover
事件手动跟踪:
$(...).hover(
function() { $.data(this, 'hover', true); },
function() { $.data(this, 'hover', false); }
).data('hover', false);
if ($(something).data('hover'))
//Hovered!
我需要一些完全一样的东西(在一个更复杂的环境中,并且有很多'mouseenters'和'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);
然后在文档的任何地方你都这样称呼它,它返回真或假:
$("#player").ismouseover()
我在 IE7+、Chrome 1+ 和 Firefox 4 上对其进行了测试,并且运行正常。
在 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;
}
我接受了 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());
});
仅供未来发现者参考。
我制作了一个 jQuery 插件,它可以做到这一点以及更多。在我的插件中,要获取光标当前悬停的所有元素,只需执行以下操作:
$.cursor("isHover"); // will return jQ object of all elements the cursor is
// currently over & doesn't require timer
由于我无法发表评论,所以我会写这个作为答案!
请理解 css 选择器 ":hover" 和悬停事件之间的区别!
":hover" 是一个 css 选择器,并且在这样使用时确实与事件一起被删除$("#elementId").is(":hover")
,但它的意思是它实际上与 jQuery 事件悬停无关。
如果您编写代码$("#elementId:hover")
,则仅当您将鼠标悬停时才会选择该元素。上面的语句将适用于所有 jQuery 版本,因为您使用纯合法的 css 选择来选择此元素。
另一方面,事件悬停是
$("#elementId").hover(
function() {
doSomething();
}
);
确实不推荐使用 jQuery 1.8 这里来自 jQuery 网站的状态:
当使用事件名称“hover”时,事件子系统将其转换为事件字符串中的“mouseenter mouseleave”。这很烦人,有几个原因:
语义:悬停与鼠标进入和离开元素不同,它意味着在触发之前有一定的减速或延迟。事件名称:附加处理程序返回的 event.type 不是 hover,而是 mouseenter 或 mouseleave。没有其他事件会这样做。选择“悬停”名称:无法附加名称为“悬停”的事件并使用 .trigger(“悬停”) 触发它。文档已经将此名称称为“强烈反对新代码”,我想在 1.8 中正式弃用它并最终将其删除。
为什么他们删除了使用 is(":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% 的情况下还有另一种方法!
希望我能帮助那里的几个人。
问候安迪
感谢你们俩。在某些时候,我不得不放弃尝试检测鼠标是否仍在元素上方。我知道这是可能的,但可能需要太多代码才能完成。
我花了一点时间,但我接受了你的两个建议,并想出了一些对我有用的东西。
这是一个简化(但功能强大)的示例:
$("[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 之外,这还允许一些非常好的鼠标悬停帮助工具提示。顺便说一句,我需要延迟鼠标移出,因为复选框和文本之间的微小间隙导致当您移动鼠标时帮助闪烁。但这就像一个魅力。我也为焦点/模糊事件做了类似的事情。
您可以测试jQuery
是否有任何子 div 具有某个类。然后,当您将鼠标悬停在某个 div 上并移出某个 div 时,通过应用该类,您可以测试您的鼠标是否在该 div 上,即使您将鼠标悬停在页面上的不同元素上也可以这样使用更少的代码。我之所以使用它是因为我在弹出窗口中的 div 之间有空格,并且我只想在离开弹出窗口时关闭弹出窗口,而不是当我将鼠标移到弹出窗口中的空格上时。所以我在内容 div 上调用了一个 mouseover 函数(弹出窗口结束了),但它只会在我将鼠标悬停在内容 div 上时触发关闭函数,并且在弹出窗口之外!
$(".pop-up").mouseover(函数(e) { $(this).addClass("over"); }); $(".pop-up").mouseout(函数(e) { $(this).removeClass("over"); }); $("#mainContent").mouseover(function(e){ if (!$(".expanded").hasClass("over")) { Drupal.dhtmlMenu.toggleMenu($(".expanded")); } });
我看到很多用于此的超时,但是在事件的上下文中,您不能像这样查看坐标吗?:
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 事件不是通过进入子元素触发的。如果您不以某种方式检查您是否仍在父元素内,您可能会错误地采取仅适用于您真正离开父元素的操作。
编辑:这是一个好主意,但不能始终如一地工作。也许有一些小的调整。
这将是最简单的方法!
function(oi)
{
if(!$(oi).is(':hover')){$(oi).fadeOut(100);}
}
这是一种不依赖 jquery 并使用本机 DOM matches
API的技术。它使用供应商前缀来支持可追溯到 IE9 的浏览器。有关完整详细信息,请参阅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');
我已经在另一个问题中回答了这个问题,您可能需要的所有详细信息:
使用 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 开始测试的。
这是一个可以帮助您检查鼠标是否在元素内的函数。您唯一应该做的就是调用函数,您可以在其中拥有一个与鼠标相关的活动对象。像这样的东西:
$("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;
}
}
扩展“Happytime harry”所说的内容,请务必使用 .data() jquery 函数来存储超时 ID。这样您就可以在稍后在同一元素上触发“mouseenter”时非常轻松地检索超时 id,从而消除触发工具提示消失的触发器。
您可以使用 jQuery 的 mouseenter 和 mouseleave 事件。您可以在鼠标进入所需区域时设置标志,并在鼠标离开该区域时取消设置标志。
我结合了这个主题的想法并想出了这个,这对于显示/隐藏子菜单很有用:
$("#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 中无法正常工作。
我无法使用上述任何建议。
为什么我更喜欢我的解决方案?此方法在You 选择的任何时间
检查鼠标是否在元素上。Mouseenter和:hover很酷,但是 mouseenter 仅在您移动鼠标时触发,而不是当元素在鼠标下方移动时触发。
:hover 很可爱但是... IE
所以我这样做:
没有 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");
}
});
只是关于上面流行且有用的 Arthur Goldsmith 回答的注释:如果您在 IE 中将鼠标从一个元素移动到另一个元素(至少在 IE 9 之前),如果新元素具有透明背景(默认情况下)。我的解决方法是给新元素一个透明的背景图像。
您可以is(':visible');
在 jquery 中使用 $('.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');
});
这就是我所说的:)