[英]What's the most efficient way to handle displaying a dialog/modal in JavaScript?
[UPDATE:] here is a link to test (if you don't want to clone the repo) http://jsfiddle.net/integralist/g9EPu/ [更新:] 这里是一个测试链接(如果你不想克隆 repo) http://jsfiddle.net/integralist/g9EPu/
I've got a lot of dialogs/modals that need to be displayed when mousing over certain links in a web app.当鼠标悬停在 Web 应用程序中的某些链接上时,我有很多对话框/模式需要显示。
The way I usually do this is to use event delegation.我通常这样做的方法是使用事件委托。
So I add one event handler to a container and then check for the relevant element to become the target and then display the relevant dialog.所以我向容器添加一个事件处理程序,然后检查相关元素是否成为目标,然后显示相关对话框。
I normally have one dialog which I change the content for and re-position (saves having lots of different HTML mark-up).我通常有一个对话框,我可以更改内容并重新定位(保存许多不同的 HTML 标记)。
If the mouseover
event (for the link) gets triggered then I display the dialog.如果
mouseover
事件(对于链接)被触发,那么我会显示对话框。
If the mouseout
event (for the link) gets triggered then I hide the dialog.如果
mouseout
事件(对于链接)被触发,那么我会隐藏对话框。
If I mouseout
of the link which triggered the event handler then I normally need to set a timer to delay hiding the dialog (just long enough) so I can then mouseover the dialog which itself clears the timer set by the mouseout
of the link.如果我
mouseout
触发事件处理程序的链接,那么我通常需要设置一个计时器来延迟隐藏对话框(足够长的时间),以便我可以将鼠标悬停在对话框上,该对话框本身会清除由链接的mouseout
设置的计时器。
I then have a mouseout
event bound to the dialog so I can then hide the dialog when the user rolls their mouse off the dialog.然后我有一个
mouseout
事件绑定到对话框,这样当用户将鼠标滚离对话框时,我可以隐藏对话框。
There are two problems I've encountered at this stage, the first happens practically all the time and the other is an edge case I noticed recently which prompted me to try and find a better solution...在这个阶段我遇到了两个问题,第一个几乎一直发生,另一个是我最近注意到的一个边缘情况,这促使我尝试找到更好的解决方案......
The dialog has 'x' number of child elements and rolling the mouse over a child element causes the mouseout
event for the dialog to be triggered hence I need to put in checks to see if the element has a parent which is the dialog itself and if so then don't try to hide the dialog.对话框有“x”个子元素,将鼠标滚动到子元素上会导致触发对话框的
mouseout
事件,因此我需要检查该元素是否有一个父元素,即对话框本身,如果所以不要试图隐藏对话框。
When using this technique on a <table> element I've found that when the mouse moves too quickly the mouseout/over events don't get triggered.在 <table> 元素上使用这种技术时,我发现当鼠标移动太快时,鼠标移出/悬停事件不会被触发。
For example code see: https://github.com/Integralist/Mouse-Over-Out-Script (you should be able to just clone the repo and run the index.html file locally to see what's happening)例如代码请参见: https : //github.com/Integralist/Mouse-Over-Out-Script (您应该能够克隆 repo 并在本地运行 index.html 文件以查看发生了什么)
But to give a brief explanation...但要给一个简短的解释......
We bind a mousemove
event to the document.documentElement
element (but you could do it on the document.body if you wanted) and then we store the x/y co-ordinates of the mouse position.我们将
mousemove
事件绑定到document.documentElement
元素(但如果您愿意,您可以在 document.body 上进行),然后我们存储鼠标位置的 x/y 坐标。 We provide public API access to a 'check' method which lets us know if the position of the mouse is over the element we've provided to 'check' (we measure the elements dimensions and add those onto its x/y co-ordinates).我们提供对“检查”方法的公共 API 访问,该方法让我们知道鼠标的位置是否在我们提供给“检查”的元素上(我们测量元素尺寸并将其添加到其 x/y 坐标上)。
In the above repo we have a calendar which shows a dialog whenever a particular date has an event on.在上面的 repo 中,我们有一个日历,当特定日期有事件时,它会显示一个对话框。 We're storing all <td>'s that have an event and we set-up a timer for each of those <td>'s (this is because we need to keep calling the 'check' method to see if that <td> has the mouse over it).
我们正在存储所有具有事件的 <td> 并为每个 <td> 设置一个计时器(这是因为我们需要不断调用“检查”方法以查看 <td > 将鼠标悬停在其上)。
So potentially there could be 31+ (because we're showing the first few days of the following month) opportunities for a dialog to be shown and so 31+ timers set!因此,可能有 31 次以上(因为我们显示的是下个月的前几天)显示对话框的机会,因此设置了 31 次以上的计时器!
This example repo works now, where as the first version where I was using event delegation wasn't.这个示例 repo 现在可以工作,因为我使用事件委托的第一个版本不是。
I'm worried about performance on the mousemove
version because it can potentially use a lot of timers (depending on how many dialogs you need in a single page).我担心
mousemove
版本的性能,因为它可能会使用很多计时器(取决于单个页面中需要多少个对话框)。 In my calendar example above there is up to 31+ timers that could be running!在我上面的日历示例中,最多可以运行 31 个以上的计时器!
I know these events exist and if all browsers supported it then I could safely use the first version and not have to check for child elements causing erroneous mouseout/over events to be triggered.我知道这些事件存在,如果所有浏览器都支持它,那么我可以安全地使用第一个版本,而不必检查导致错误的 mouseout/over 事件被触发的子元素。 But regardless I don't believe this would have fixed the example with the event calendar where moving the mouse too quickly was meaning the mouseout/over events for the <td>'s weren't being triggered by the browser.
但无论如何,我不相信这会修复事件日历的示例,其中将鼠标移动得太快意味着 <td> 的鼠标悬停/悬停事件没有被浏览器触发。 Either way, I know you can polyfill this as jQuery provides mouseenter/leave events but looking through their code I couldn't get that to work for my script (as I don't use jQuery or any other general purpose library - ps, and I don't wish to, so please do not suggest that as an option).
无论哪种方式,我都知道您可以对它进行 polyfill,因为 jQuery 提供了 mouseenter/leave 事件,但是查看他们的代码我无法让它为我的脚本工作(因为我不使用 jQuery 或任何其他通用库 - ps,和我不希望,所以请不要建议将其作为一种选择)。
Many thanks for any help/advice or guidance someone can provide me.非常感谢有人可以为我提供的任何帮助/建议或指导。
The dialog has 'x' number of child elements and rolling the mouse over a child element causes the mouseout event for the dialog to be triggered hence I need to put in checks to see if the element has a parent which is the dialog itself and if so then dont try to hide the dialog.
对话框有“x”个子元素,将鼠标滚动到子元素上会导致触发对话框的 mouseout 事件,因此我需要检查该元素是否有一个父元素,即对话框本身,如果所以不要试图隐藏对话框。
To solve this: in your event code, simply use the function "isAncestor" (see below)要解决这个问题:在您的事件代码中,只需使用函数“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 );
}
So in your mouseout code for your element (let's call it "itemElement"), you'd check it like:所以在你的元素的 mouseout 代码中(我们称之为“itemElement”),你会像这样检查它:
//We're really mousing out, close dialog
if ( !isAncestor( mouseOutEvent.target, itemElement ) )
{
...do something ...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.