当 HTML 选择元素关闭时,是否会触发 DOM 事件?

IT技术 javascript jquery html dom
2021-01-28 15:56:25

我正在寻找一个 DOM 事件,当一个已经打开(但没有更改选项)的选择元素然后通过单击页面上其他地方(任何地方)的选择元素关闭时,我可以用 JavaScript 收听该事件。

这不是blur选择事件,因为选择保留焦点。同样,这不是focus一些其他元素或文档或事件mousedownclick窗口,文档或身体。

这不是change选择事件,因为选择中的任何选项都没有改变。

我不关心旧的 Internet Explorers - 只是在符合标准的现代浏览器中工作的东西。不过,专有黑客可能值得了解。

我创建了一个 JSFiddle 来演示这个问题:http : //jsfiddle.net/premasagar/FpfnM/

  1. 单击“结果”面板中的选择框
  2. 单击一下标记为“HERE”(或其他任何地方)的文本,查看是否有任何事件添加到日志中。最新的 Chrome 或 Firefox 中没有事件。

所以问题是:可以添加什么 JavaScript,以便在单击选择框时记录事件?

(我在这里问了一个类似但不同的问题:
iOS 上的 JavaScript:打开一个 HTML 选择元素

6个回答

不幸的是,没有标准的事件可以知道选择框何时关闭或打开,因此您的代码将非常繁琐,可以适应不同的浏览器。也就是说,我认为这是可以做到的,而且我已经使用该mouseup事件在 Firefox 中为您提供了一些有用的东西

http://jsfiddle.net/FpfnM/50/

在 Firefox(我假设是 Chrome)中,您需要非常仔细地跟踪该选择的状态。escape按下某个键或blur发生事件时,您需要更新状态以将其标识为已关闭。我没有在我的演示中实现它,你可以看到如果你点击转义而不是点击选择会发生什么。

在 Safari 中事情更容易,其中mousedown选择上的事件表示打开选择,选择的任何关闭都由click事件表示

如果您发现浏览器没有触发这些事件,您可以尝试一个额外的技巧。因为像 select 和 textarea 这样的表单小部件通常由操作系统呈现,而不是在浏览器内部呈现,所以您可能会与它们交互,并且某些消息可能不会进入浏览器的事件处理程序。如果您在选择框打开时将覆盖屏幕的透明文本区域定位在较低的 z-index 处,您或许可以使用它来跟踪关闭的点击。它可能能够捕获浏览器 DOM 元素可能错过的事件。

更新: Chrome 在打开时在选择上看到鼠标按下,在打开选择时单击页面时在文档上看到鼠标上移。这是一个适用于 Chrome 的版本:

http://jsfiddle.net/FpfnM/51/

同样,您需要进行一些浏览器检测以处理每个浏览器中的正确行为。特别是 Chrome 的一个问题是,当您第二次单击选择以关闭它时,不会触发任何事件。但是,您可以检测页面点击。

快速总结:

Chrome/Safari: select.mousedown on open, document.mouseup on close
Firefox: select.click on open, document.mouseup on close
IE8/IE7: select.click on open, document.mouseup on close

其他事件有很多边缘情况意味着关闭(退出按键、模糊等),但这些是处理用户单击选择框然后单击进入文档区域的情况的最低限度.

希望这可以帮助!

在我的例子中,当鼠标离开时,我捕捉到关闭事件添加一个侦听器,如下所示: document.getElementById('selectId').addEventListener('mouseleave', ($event) => { console.log($event); });
2021-03-20 15:56:25
谢谢。是的,在 Chrome 中,如果选择的选项已更改,我只会收到记录的事件。如果我只是打开选择然后单击“此处”将其关闭,则不会收到事件。
2021-03-21 15:56:25
该 jsFiddle 仅切换“打开/关闭”消息,并不能准确反映实际事件。(例如,只需单击并选择一个项目,然后再做一次。)
2021-03-21 15:56:25
@Premasager - 我已经用 Chrome 示例更新了答案,并在 IE 上测试了该行为。IE/Firefox 似乎对打开和关闭处理程序的工作方式类似。Chrome/Safari 需要在打开时注意选择上的 mousedown,以及关闭文档时的 mouseup。
2021-03-27 15:56:25

当你有超过 1 个下拉菜单时:

        $("select").each(function () {
        var initDropdown = $(this);
        initDropdown.data("open", false);
        console.log(this.name + "   closed");

        initDropdown.on("blur", function () {
            var blurDdopdown = $(this);
            blurDdopdown.data("open", false);
            console.log(this.name + "   closed");
        });
    });

    $("select").bind("click", function () {
        var clickedDropdown = $(this);

        if (clickedDropdown.data('open') == false) {
            clickedDropdown.data('open', true);
            console.log(this.name + "   open");
        } else {
            clickedDropdown.data('open', false);
            console.log(this.name + "   closed");
        }
    });

我按照您的 JSFiddle 上的说明收到了以下事件:

BODY, mousedown, STRONG
#document, mousedown, STRONG
window, mousedown, STRONG
SELECT, blur, SELECT
BODY, click, STRONG
#document, click, STRONG
window, click, STRONG

这些都是在选择菜单已经处于焦点并展开后单击“此处”时触发的所有事件。这是在最新版本的 Chrome 中。

这些中的任何一个都不能满足您的目的吗?

编辑:如果您想确保是您的 Select 元素失去焦点,请设置全局 Javascript 变量“selectFocused”,并将其设置为 False。当您的选择菜单获得焦点时将其设置为 True,并在发生上述任何事件时将其设置为 False。'selectFocused' 现在可以在代码中的任何地方使用,以检测您的 Select 元素当前是否具有焦点,并且当它更改值时,您就知道您的 Select 元素已被选中或未选中。

唔。我也在 Chrome 13.0.772.0 dev(在 Linux 上)。当我单击关闭一次或在 Firefox 4.0.1 中时,我没有在那里得到模糊事件。
2021-03-27 15:56:25
在 Windows 上的 Firefox 4.0.1 上,在这些事件出现之前,需要再次单击 HERE。第一次点击 HERE 时不会触发任何事件。
2021-03-27 15:56:25
我也看到了这种行为:Chrome vs. 13.0.772.0 dev-m
2021-03-29 15:56:25
您是否只点击了一次“这里”?还是两次?在最新的 Chrome 中,blur当我只单击一次“HERE”时, <select> 不适合我。它仍然保持焦点。
2021-04-05 15:56:25
冰人,柏忌确定。我从 Firefox 中一无所获,该输出来自 Chrome(虽然我只点击了一次,Premasagar)。OP,这似乎是您应该提交给 bugzilla 的东西,因为 Chrome 和 IE 的行为都与我上面所说的一样,只有 Firefox 不注册任何事件。不过,不确定为什么 Linux 中的 Chrome 表现不一样。:(
2021-04-11 15:56:25

我的第一直觉是实现这一点的方式有点迂回,这将是使用您通常用于在按下外部时关闭(自定义)下拉菜单的代码:

function clickInBody(){
 functionToCallOnBlur();
}

function clickInBodyStop(event){
    event.stopPropagation();
}

然后在你的 body 标签上添加onClick="clickInBody()",在你选择的项目上添加onClick="clickInBodyStop(event)"这应该在您每次点击页面时调用该事件,但是如果您点击 select 标签,它将停止传播而不是调用functionToCallOnBlur()

我想我发现了问题,如this jsfiddle和firebug所示,问题clickInBody是没有定义,所以这是jsfiddle的问题而不是代码的问题,它应该在本地工作......
2021-03-16 15:56:25
然后在整个身体周围放置一个包装 div 并触发onclick事件。
2021-03-22 15:56:25
但问题是,如 JSFiddle 片段所示,click当用户单击打开的选择时,没有在正文上触发任何事件。
2021-03-24 15:56:25
我不明白。在身体周围放一个div?没有在任何元素上产生点击事件,所以我看不出这如何解决问题。
2021-04-03 15:56:25
正如我所说,如果 body 元素从不触发click事件(它似乎从未触发过)那么您提出的解决方案将无法工作
2021-04-07 15:56:25

前提条件:使用jQuery!这可能只能解决您的部分问题,但如果您正在寻找在单击元素时触发的事件,则可以使用叠加 div。

当用户点击选择框时:

$('#mySelectBox').click(function () {
    var myOverlayDiv = $('<div id="overlayDiv" class="overlayDiv"></div>')
    .click(function () {
        // call your "select lost focus" function here
        // which should include $('#overlayDiv').remove() somewhere!
    })
    .show()
    .appendTo(document.body);
});

叠加 div 的样式:

.overlayDiv {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
opacity:0;
z-index:1000;
}

您需要确保您的选择框菜单具有更高的 Z-index,因此当用户单击菜单时,他们会获得菜单而不是叠加 div :)

是的,我让它在使用一些自定义下拉菜单的网络应用程序中工作。
2021-03-20 15:56:25
我忘记了一件事(在我的应用程序和答案中) - 当叠加层 div 收到点击事件时,请确保将其从 DOM 中删除,以免每次都添加它们:P
2021-03-23 15:56:25
您还可以在该函数和“选择失去焦点”函数中添加一些简单的代码,以比较用户与之交互之前和之后的选择值。这将允许您查看值是否已更改或框是否仅打开和关闭。
2021-03-29 15:56:25
我很确定这行不通。通过单击选择框关闭选择时, <body> 元素不会收到“单击”事件,因此我不太相信 div 元素会收到。你有没有尝试过并让它工作。我会尝试一下。
2021-04-06 15:56:25