处理JavaScript中显示对话框/模态的最有效方法是什么?

时间:2011-12-01 09:10:22

标签: javascript javascript-events modal-dialog mouseevent mousemove

[更新:]这是一个测试链接(如果你不想克隆回购)http://jsfiddle.net/integralist/g9EPu/

当鼠标悬停在网络应用中的某些链接上时,我需要显示很多对话框/模式。

目录(tl; dr)

  • 我以前如何处理它
  • 我最近怎么试过
  • 哪个更好?
  • mouseenter / leave怎么样?

我以前如何处理它

我通常这样做的方式是使用事件委托。

所以我将一个事件处理程序添加到容器中,然后检查相关元素是否成为目标,然后显示相关对话框。

我通常有一个对话框,我更改了内容并重新定位(保存了大量不同的HTML标记)。

如果鼠标悬停事件(链接)被触发,则显示对话框。

如果mouseout事件(对于链接)被触发,那么我隐藏了对话框。

如果我鼠标移开触发事件处理程序的链接,那么我通常需要设置一个计时器来延迟隐藏对话框(足够长),这样我就可以鼠标悬停在对话框上,该对话框本身清除鼠标输出所设置的计时器链接。

然后我将鼠标输出事件绑定到对话框,这样当用户将鼠标从对话框上移开时,我就可以隐藏对话框。

我在这个阶段遇到了两个问题,第一个问题几乎一直发生,另一个是我最近注意到的边缘情况,这促使我尝试找到更好的解决方案......

  1. 对话框中有'x'个子元素,将鼠标滚动到子元素上会导致触发对话框的mouseout事件,因此我需要检查元素是否有父元素是对话框本身,如果是,那么不要试图隐藏对话框。

  2. 在< table>上使用此技术时element我发现当鼠标移动太快时,鼠标输出/事件不会被触发。

  3. 我最近怎么试过

    例如代码请参阅: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个以上的计时器!

    mouseenter / leave怎么办?

    我知道这些事件存在,如果所有浏览器都支持它,那么我可以安全地使用第一个版本而不必检查导致错误的mouseout / over事件被触发的子元素。但是,无论我不相信这会修复事件日历的例子,其中移动鼠标太快意味着< td>的mouseout / over事件没有被浏览器触发。无论哪种方式,我知道你可以填充这个,因为jQuery提供了mouseenter / leave事件,但查看他们的代码我无法让它为我的脚本工作(因为我不使用jQuery或任何其他通用库 - ps,和我不希望,所以请不要建议作为一种选择)。

    非常感谢有人可以提供给我的任何帮助/建议或指导。

    亲切的问候, 标记

1 个答案:

答案 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 ...
}