鼠标离开浏览器窗口时的Javascript事件

时间:2009-11-04 07:13:08

标签: javascript ajax safari prototypejs mouseout

当鼠标离开浏览器窗口时,我想要运行一些Javascript代码。我只需要支持Safari(WebKit。)

我尝试在窗口上放置一个mouseout处理程序。当鼠标离开浏览器窗口时,可以可靠地调用该处理程序。但是由于冒泡,当鼠标在文档中的元素之间移动时也会调用它。我无法弄清楚如何确定鼠标何时实际离开窗口以及何时只在元素之间移动。

当鼠标离开窗口时,只生成一个事件,目标元素看起来是鼠标实际上的元素。因此,检查目标元素是窗口还是文档是不起作用的。并且将整个页面包装在一个不可见的包含div中也不起作用:如果div是不可见的,那么鼠标永远不会超过它,所以没有任何改变。

(如果我把处理程序放在document或document.body上会发生同样的事情,除了令人惊讶的document.body在鼠标进入或离开窗口的空白部分时没有鼠标悬停/鼠标输出事件,例如空通过绝对定位底部元素创建的垂直空间:0。对于该空间,文档和窗口将获得mouseover / mouseout事件,目标为< html>,但document.body不会。)

我有一些想法:

  • 在每个mouseout事件中,获取鼠标的实际位置,看看它是否实际上在窗口上。但我不知道这是否真的可行,听起来消除所有竞争条件都会很棘手。
  • 还注册一个鼠标悬停处理程序,并检测鼠标悬停未进行鼠标移除(或紧接着a)鼠标悬停的情况。但这需要一个计时器。

我们使用prototype.js,所以理想情况下我想用原型的Event.observe来表达解决方案,但我可以想出那部分。

感谢您的任何建议!

7 个答案:

答案 0 :(得分:12)

摘要:这可以通过在mouseout事件期间检查relatedTarget属性来干净地完成。如果relatedTarget不是文档的子项,则鼠标刚离开窗口。你自己很容易做到,但是如果你不想这样做,一些库(Mootools,未来的Prototype ......)具有烘焙功能,而其他库(当前的Prototype)则具有扩展功能。在IE上,你可以使用mouseleave,这是一个非冒泡的mouseout版本。

详细说明:

IE有一些名为mouseenter和mouseleave的事件,它们是mouseover和mouseout的非冒泡版本。其他浏览器没有,但如果他们这样做,在窗口或文档上设置mouseleave监听器就行了。

一位名叫Ken Snyder的绅士来救援:

  

鼠标悬停时,relatedTarget   属性引用来自的节点   指针来了。在mouseout上,   relatedTarget属性引用   指针所在的节点   任何事件,范围都是节点   哪个事件是附加的。当时   relatedTarget是一个不是孩子的   currentTarget,一个mouseover事件   相当于一个mouseenter事件和一个   mouseout事件相当于a   mouseleave事件。

- http://kendsnyder.com/archives/6-MouseEnter-and-MouseLeave.html

这使得在其他浏览器中实现mouseenter和mouseleave成为可能。实际上,Ken提供了相同的Prototype代码:http://kendsnyder.com/sandbox/enterleave/MouseEnterLeave.js

Duroth在评论中指出,MooTools已经包含了类似的内容。 (感谢Duroth。)听起来即将发布的Prototype版本(1.6.2)可能包含此功能,但我找不到任何明确的内容。

答案 1 :(得分:9)

仅使用javascript,没有原型或jquery等。

<html>
<head>
<script type="text/javascript">
  var mouseX = 0;
  var mouseY = 0;
  var counter = 0;
var mouseIsIn = true;
function wireEvent() {
window.addEventListener("mouseout",
    function(e){
        mouseX = e.pageX;
        mouseY = e.pageY;
        if ((mouseY >= 0 && mouseY <= window.innerHeight)
        && (mouseX >= 0 && mouseX <= window.innerWidth))
            return;
        //do something for mouse out
        counter++;
        mouseIsIn = false;
        document.getElementById('in_out').innerHTML='out' + counter;
    },
    false);
window.addEventListener("mouseover",
    function(e){
        if(mouseIsIn)
            return;
        //do something for mouse over
        counter++;
        mouseIsIn = true;
        document.getElementById('in_out').innerHTML='in' + counter;
    },
    false);
}
</script> 
</head>
<body onload="wireEvent();">
<div id="in_out">&nbsp;</div>
<div style="width:300px; height: 200px; background: red;">Dummy element</div>
</body>
</html>

<强>更新
添加了在移入/移出正文中的元素时触发的mouseout上的鼠标位置检查。如果它在窗口内,则不会触发mouseout事件 还使用mouseIsIn为鼠标'in'或'out'的当前状态引入了一个标志。如果是true,则mouseover也不会触发。

答案 2 :(得分:1)

也许您可以设置mouseover和mouseout documentbody或其他一些包装整个文档的元素的监听器,并使用它(通过保存它发生)作为触发器来确定是否它是窗口上有效的鼠标输出?

如果不这样做,你的第一个想法(关于位置检查)应该工作得很好。任何事件都会在事件发生时沿着X / Y传递。如果它比窗口的高度/宽度更远,则离开实际窗口。如果它是负面的,你就离开了窗户。而且,如果它正好是高度/宽度或正好是顶部:0或左:0,那么你就离开了窗口。

答案 3 :(得分:1)

当鼠标离开任何元素(包括窗口)时,窗口对象将触发mouseout事件并传递event对象。

事件对象中的一个项称为toElement,它是指向鼠标离开旧元素时刚刚输入的元素的指针。但是当鼠标离开窗口时,没有这样的toElement,因此该项目变为null

通过测试null事件中此项是否为mouseout,您可以判断鼠标是否离开了窗口。这是代码:

window.onmouseout=function(event){ 
  if(event.toElement===null) console.log('the mouse left the window'); 
}

答案 4 :(得分:0)

您的问题来自为窗口内 元素生成的mouseout事件,然后按照W3C events spec中的描述冒泡。您可以检查事件实际触发的元素:

function mouseoutFunction(event) {
  event = event || window.event;
  var sender = event.srcElement || event.target;
}

答案 5 :(得分:0)

这是我的基于计时器的解决方案。这里的计时器基本上用于在确定mosue不在窗口之前为其他事件处理程序(特别是onmouseover)执行。 1ms的超时(实际上大约33ms,有一个最小的定时器分辨率)给鼠标悬停提供了一点时间,如果它还没有。

var inWin=0;
window.onmouseout = function(e)
{
   inWin--;
   setTimeout(checkIfOut, 1);
}
window.onmouseover = function(e)
{
   inWin++;
}

function checkIfOut()
{
   if(!inWin)
   {
     //Yay! Mouse is out of the window (probably)
   }
}

答案 6 :(得分:-1)

您可以在窗口上使用onmouseout事件