Javascript 当 HTML 选择元素关闭时,是否会触发 DOM 事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6207929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a DOM event that fires when an HTML select element is closed?
提问by Premasagar
I'm looking for a DOM event that I can listen to with JavaScript for when a select element that has been opened (but no options changed) is then closed by clicking off the select element, somewhere (anywhere) else on the page.
我正在寻找一个 DOM 事件,当一个已经打开(但没有更改选项)的选择元素然后通过单击页面上其他地方(任何地方)的选择元素关闭时,我可以用 JavaScript 收听该事件。
It's not the blur
event of the select, because the select retains focus. Likewise, it's not the focus
event of some other element or the document, or a mousedown
or click
on the window, document or body.
这不是blur
选择的事件,因为选择保留焦点。同样,这不是focus
一些其他元素或文档或事件mousedown
或click
窗口,文档或身体。
It's not the change
event of the select, since no option within the select has been changed.
这不是change
选择的事件,因为选择中的任何选项都没有改变。
I'm not concerned about legacy Internet Explorers - just something to work in standards compliant modern browsers. Proprietary hacks could be worth knowing though.
我不关心旧的 Internet Explorers - 只是在符合标准的现代浏览器中工作的东西。不过,专有黑客可能值得了解。
I've created a JSFiddle to demonstrate the problem: http://jsfiddle.net/premasagar/FpfnM/
我创建了一个 JSFiddle 来演示这个问题:http: //jsfiddle.net/premasagar/FpfnM/
- Click on the selectbox in the "Result" panel
- Click on the text marked "HERE" (or anywhere else) with a single click and see if any event is added to the log. There isn't an event in the latest Chrome or Firefox.
- 单击“结果”面板中的选择框
- 单击一次单击标记为“此处”(或其他任何位置)的文本,查看是否有任何事件添加到日志中。最新的 Chrome 或 Firefox 中没有事件。
So the question is: What JavaScript could be added, to get an event logged when clicking off the selectbox?
所以问题是:可以添加什么 JavaScript,以便在单击选择框时记录事件?
(I've asked a similar, but different question here:
JavaScript on iOS: opening an HTML select element)
(我在这里问了一个类似但不同的问题:
iOS 上的 JavaScript:打开一个 HTML 选择元素)
采纳答案by Jason Striegel
Unfortunately there's no standard event for knowing when a select box is closed or open, so your code is going to be pretty hairy with accommodations for different browsers. That said, I think it can be done, and I've gotten something working for you in Firefox using the mouseup
event:
不幸的是,没有标准事件可以知道选择框何时关闭或打开,因此您的代码对于不同浏览器的适应将非常繁琐。也就是说,我认为这是可以完成的,并且我已经使用该mouseup
事件在 Firefox 中为您提供了一些有用的东西:
In Firefox (and I'm assuming Chrome), you're going to need to track the state of that select pretty carefully. When an escape
key is pressed or blur
event occurs, you need to update the state to identify it as closed. I haven't implemented that in my demo, and you can see what happens if you hit escape instead of clicking off the select.
在 Firefox(我假设是 Chrome)中,您需要非常仔细地跟踪该选择的状态。当escape
按下某个键或blur
发生事件时,您需要更新状态以将其标识为已关闭。我没有在我的演示中实现它,你可以看到如果你点击转义而不是点击选择会发生什么。
Things were easier in Safari, where a mousedown
event on the select signifies opening the select, and any close of the select is signified by a click
event.
在 Safari 中事情更容易,其中mousedown
选择上的事件表示打开选择,选择的任何关闭都由click
事件表示。
If you find a browser where none of these events fire, you can try one additional trick. Because form widgets like select and textarea are often rendered by the OS and not inside the browser it's possible that you could interact with them and certain messages might not get down to the browser's event handler. If you were to position a transparent textarea covering the screen at a lower z-index when the select box is open, you might be able to use it to track that close click. It may be able to capture events that a browser DOM element may miss.
如果您发现浏览器没有触发这些事件,您可以尝试一个额外的技巧。因为像 select 和 textarea 这样的表单小部件通常由操作系统呈现而不是在浏览器内部呈现,所以您可能会与它们进行交互,并且某些消息可能不会进入浏览器的事件处理程序。如果您要在选择框打开时将覆盖屏幕的透明 textarea 放置在较低的 z-index 处,您也许可以使用它来跟踪关闭的点击。它可能能够捕获浏览器 DOM 元素可能错过的事件。
Update:Chrome sees a mousedown on the select when it opens and a mouseup on the document when the page is clicked with a select open. Here's a version that works with Chrome:
更新:Chrome 在打开时在选择上看到鼠标按下,在打开选择时单击页面时在文档上看到鼠标上移。这是一个适用于 Chrome 的版本:
Again, you'll need to do some browser detection to handle the right behavior in each one. One catch with Chrome, in particular, is that no event is fired when you click on the select a second time to close it. You can detect the page click, however.
同样,您需要进行一些浏览器检测以处理每个浏览器中的正确行为。特别是 Chrome 的一个问题是,当您第二次单击选择以关闭它时,不会触发任何事件。但是,您可以检测页面点击。
Quick Summary:
快速总结:
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
There are an awful lot of edge cases for other events that will signify a close (escape keypress, blur, etc.), but these are the minimum to handle the scenario where a user clicks the select box and then clicks off into the document area.
其他事件有很多边缘情况意味着关闭(退出按键、模糊等),但这些是处理用户单击选择框然后单击进入文档区域的情况的最低限度.
Hope this helps!
希望这可以帮助!
回答by Bogdan
When you have more then 1 dropdown:
当你有超过 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");
}
});
回答by sichinumi
I got the following events by following the directions on your JSFiddle to the letter:
我按照您的 JSFiddle 上的说明收到了以下事件:
BODY, mousedown, STRONG
#document, mousedown, STRONG
window, mousedown, STRONG
SELECT, blur, SELECT
BODY, click, STRONG
#document, click, STRONG
window, click, STRONG
These are all events that were triggered when I clicked "HERE" after the select menu was already in focus and expanded. This was in the latest version of Chrome.
这些都是在选择菜单已聚焦并展开后单击“此处”时触发的所有事件。这是在最新版本的 Chrome 中。
Shouldn't any one of these suffice for your purposes?
这些中的任何一个都不能满足您的目的吗?
Edit: If you want to make sure it's your Select element that's losing focus, set a global Javascript variable, 'selectFocused', and set it to False. Set it to True when your Select menu receives focus, and set it to False when any of the above events occurs. 'selectFocused' can now be used anywhere in your code to detect whether or not your Select element currently has focus, and when it changes values, you know your Select element has been selected or unselected.
编辑:如果您想确保是您的 Select 元素失去焦点,请设置全局 Javascript 变量“selectFocused”,并将其设置为 False。当您的选择菜单获得焦点时将其设置为 True,并在发生上述任何事件时将其设置为 False。'selectFocused' 现在可以在您的代码中的任何地方使用,以检测您的 Select 元素当前是否具有焦点,并且当它更改值时,您就知道您的 Select 元素已被选中或未选中。
回答by Tomas
My first instinct is a little roundabout in its way to achieve this, it would be to use the code you normally use for closing a (custom) dropdown menu on press outside:
我的第一直觉是实现这一点的方式有点迂回,这将是使用您通常用于在按下外部时关闭(自定义)下拉菜单的代码:
function clickInBody(){
functionToCallOnBlur();
}
function clickInBodyStop(event){
event.stopPropagation();
}
Then on your body tag you add onClick="clickInBody()"
and on your select item you add onClick="clickInBodyStop(event)"
. This should call the event every time you click on the page, but if you click on the select tag it will stop the propagation and not call functionToCallOnBlur()
然后在你的 body 标签上添加onClick="clickInBody()"
,在你选择的项目上添加onClick="clickInBodyStop(event)"
。这应该在您每次点击页面时调用该事件,但是如果您点击 select 标签,它将停止传播而不是调用functionToCallOnBlur()
回答by jbabey
precondition: using jQuery!This will probably only solve part of your problem, but if you are looking for an event to fire when you click off an element, you can use an overlay div.
前提:使用jQuery!这可能只能解决您的部分问题,但如果您正在寻找在单击元素时触发的事件,则可以使用叠加 div。
When the user clicks on the select box:
当用户点击选择框时:
$('#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);
});
Style for the overlay div:
叠加 div 的样式:
.overlayDiv {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
opacity:0;
z-index:1000;
}
You need to make sure that your select box menu is a higher Z-index so when the user clicks on the menu they get the menu and not the overlay div :)
您需要确保您的选择框菜单具有更高的 Z-index,因此当用户单击菜单时,他们会获得菜单而不是叠加 div :)
回答by yuxin Zhang
If we consider clicking outside the selection box can be a signal of the ending selection event.
如果我们认为在选择框外单击可能是结束选择事件的信号。
The following jQuery can do this. Hereis code in fiddle
下面的 jQuery 可以做到这一点。这是小提琴中的代码
$(function () {
let flag = 0;
$("#selectId").click(function (e) {
e.stopPropagation();
if (flag === 0) {
flag = 1;
$(document).one("click", function () {
flag = 0;
alert("select end");
});
}
});
});
Html code:
html代码:
<select multiple id="selectId">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>