我正在尝试为带有下拉菜单的按钮创建一个简单的跨浏览器插件。当用户单击此类按钮时,下方会出现一个带有各种选项的菜单,用户随后可以从中选择一个选项或将其关闭。
我已经创建了一个简单的 JSFiddle,其中包含三个这样的按钮来举例说明我想要实现的目标。我的 JSFiddle 代码执行了一些我已从下面的代码中排除的额外事件日志记录,但运行 JSFiddle 很明显我正在记录事件发生时。
这是我的 HTML:
我实现代码的方式需要下拉菜单可聚焦,因此tabindex
容器上的属性。
<div class="dropdown">
<a href="#" class="dropdown-toggle">Open sesame</a>
<ul class="dropdown-menu" tabindex="0">
<li><a href="#">Some option</a></li>
<li><a href="#">Option with longer text</a></li>
</ul>
</div>
我的脚本:
// menu opening and closing
$(".dropdown-toggle").mousedown(function(evt) {
evt.preventDefault();
var c = $(this).closest(".dropdown").toggleClass("open");
c.hasClass("open") && c.find(".dropdown-menu")[0].focus();
});
// menu closing when clicking anywhere
$(".dropdown-menu").focusout(function(evt) {
evt.stopPropagation();
$(this).closest(".dropdown").removeClass("open");
})
菜单的显示由 CSS 完成。如您所见,我几乎没有在容器上设置 CSS 类,并且当open
在容器上设置类时,CSS 提供了自动可见性。
预期行为
这是正确的方法,因为它应该起作用:
- 用户单击按钮并出现菜单
- 单击同一按钮应关闭菜单
- 点击菜单选项应该触发点击甚至选项(并可选择保持菜单打开)
- 如果打开,单击其他任何地方都应该关闭菜单。
浏览器问题
不同的浏览器似乎以不同且过度的方式触发事件。事件传播(冒泡)及其顺序阻止了上层步骤按预期执行。Chrome 似乎不会触发过多的事件。
Chrome
Chrome 似乎按预期工作。所有四个步骤都按应有的方式执行。单击菜单中的链接时,不会触发焦点输出作为焦点容器(菜单本身)中的链接。
Firefox 和 IE9
似乎步骤 #1、#2 和 #4 按预期工作,但 #3 失败,因为在检测和执行菜单选项单击之前, focusout首先触发并关闭菜单。
IE8 和 IE7
任何拥有它们的人都可以为我测试并告诉我上面的哪些步骤有效,哪些失败。我没有测试过,但也很想知道。
问题
此脚本的主要问题是focusout事件过早且过于频繁地触发。我不能使用模糊事件,因为它不会从菜单选项传播到菜单本身。
重要- 将点击处理程序绑定到
document
- 我知道我可以将点击事件绑定到我的document
,但我不能使用这种通常的方法,因为:
1.这将非常不可靠,因为我的表单上的一些其他控件可能会停止点击传播,因此菜单不会'在单击此类控件时不会关闭。
2.我的应用程序在一个 中运行iframe
,因此在它之外单击,也会使菜单保持打开状态。
有人想以跨浏览器的方式玩这些事件吗?