[更新:]这是一个测试链接(如果你不想克隆回购)http://jsfiddle.net/integralist/g9EPu/
当鼠标悬停在网络应用中的某些链接上时,我需要显示很多对话框/模式。
我通常这样做的方式是使用事件委托。
所以我将一个事件处理程序添加到容器中,然后检查相关元素是否成为目标,然后显示相关对话框。
我通常有一个对话框,我更改了内容并重新定位(保存了大量不同的HTML标记)。
如果鼠标悬停事件(链接)被触发,则显示对话框。
如果mouseout事件(对于链接)被触发,那么我隐藏了对话框。
如果我鼠标移开触发事件处理程序的链接,那么我通常需要设置一个计时器来延迟隐藏对话框(足够长),这样我就可以鼠标悬停在对话框上,该对话框本身清除鼠标输出所设置的计时器链接。
然后我将鼠标输出事件绑定到对话框,这样当用户将鼠标从对话框上移开时,我就可以隐藏对话框。
我在这个阶段遇到了两个问题,第一个问题几乎一直发生,另一个是我最近注意到的边缘情况,这促使我尝试找到更好的解决方案......
对话框中有'x'个子元素,将鼠标滚动到子元素上会导致触发对话框的mouseout事件,因此我需要检查元素是否有父元素是对话框本身,如果是,那么不要试图隐藏对话框。
在< table>上使用此技术时element我发现当鼠标移动太快时,鼠标输出/事件不会被触发。
例如代码请参阅:https://github.com/Integralist/Mouse-Over-Out-Script(您应该能够克隆存储库并在本地运行index.html文件以查看发生的情况)
但是要做一个简短的解释......
我们将mousemove事件绑定到document.documentElement元素(但如果需要,可以在document.body上执行),然后我们存储鼠标位置的x / y坐标。我们提供公共API访问“检查”方法,让我们知道鼠标的位置是否在我们提供的“检查”元素上方(我们测量元素尺寸并将其添加到其x / y坐标上) )。
在上面的回购中,我们有一个日历,当特定日期有事件时,它会显示一个对话框。我们存储了所有包含事件的< td>并且我们为每个< td>设置了一个计时器(这是因为我们需要继续调用'check'方法来查看是否存在< td>将鼠标移到它上面。)
因此可能有31个以上(因为我们正在显示下个月的前几天)显示对话框的机会,因此设置了31个以上的计时器!
这个示例repo现在可以使用,其中我使用事件委托的第一个版本不是。
我担心'mousemove'版本的性能,因为它可能会使用很多计时器(取决于你在一个页面中需要多少对话框)。在上面的日历示例中,最多可以运行31个以上的计时器!
我知道这些事件存在,如果所有浏览器都支持它,那么我可以安全地使用第一个版本而不必检查导致错误的mouseout / over事件被触发的子元素。但是,无论我不相信这会修复事件日历的例子,其中移动鼠标太快意味着< td>的mouseout / over事件没有被浏览器触发。无论哪种方式,我知道你可以填充这个,因为jQuery提供了mouseenter / leave事件,但查看他们的代码我无法让它为我的脚本工作(因为我不使用jQuery或任何其他通用库 - ps,和我不希望,所以请不要建议作为一种选择)。
非常感谢有人可以提供给我的任何帮助/建议或指导。
亲切的问候, 标记
答案 0 :(得分:0)
对话框中有'x'个子元素,并且将鼠标滚动到子元素上会导致触发对话框的mouseout事件,因此我需要检查元素是否有父元素是对话框本身,如果是这样,那就不要试图隐藏对话框。
要解决此问题:在您的事件代码中,只需使用“isAncestor”功能(见下文)
/*
* element = the "target" in your mouseout event handler
* other = the node you really want to check if you're over
*/
isAncestor: function(element, other)
{
while ( element && element != other ) element = element.parentNode;
return ( element != null && element != undefined );
}
因此,在你的元素的mouseout代码中(我们称之为“itemElement”),你会检查它:
//We're really mousing out, close dialog
if ( !isAncestor( mouseOutEvent.target, itemElement ) )
{
...do something ...
}