我正在寻找一个我可以用JavaScript监听的DOM事件,当一个已经打开的select元素(但是没有更改选项)然后通过单击select元素,在某个地方(任何地方)其他地方关闭时页。
这不是select的blur
事件,因为select保留了焦点。同样,它不是某个其他元素或文档的focus
事件,也不是窗口,文档或正文中的mousedown
或click
。
这不是select的change
事件,因为select中的选项没有被更改。
我并不关心传统的Internet Explorer - 只需要符合标准的现代浏览器即可。专有黑客可能值得了解。
我创建了一个JSFiddle来演示问题:http://jsfiddle.net/premasagar/FpfnM/
所以问题是:可以添加哪些JavaScript,以便在点击选择框时记录事件?
(我在这里问了一个类似但不同的问题:
JavaScript on iOS: opening an HTML select element)
答案 0 :(得分:30)
不幸的是,没有标准事件可以知道何时关闭或打开选择框,因此您的代码对于不同的浏览器来说是非常多毛的。也就是说,我认为可以做到,并且我已经使用mouseup
事件在Firefox中找到了适合你的东西:
在Firefox中(我假设是Chrome),您需要非常仔细地跟踪该选择的状态。当按下escape
键或发生blur
事件时,您需要更新状态以将其标识为已关闭。我没有在我的演示中实现它,你可以看到如果你点击转义而不是点击选择会发生什么。
在Safari中,事情变得更容易,其中选择中的mousedown
事件表示打开选择,而选择的任何结束都由click
事件表示。
如果您发现某个浏览器没有触发这些事件,您可以尝试另外一个技巧。因为像select和textarea这样的表单小部件通常由操作系统呈现而不是在浏览器内部,所以您可以与它们进行交互,并且某些消息可能无法访问浏览器的事件处理程序。如果您在选择框打开时将屏幕上的透明文本区域放置在较低的z-index处,则可以使用它来跟踪该关闭点击。它可能能够捕获浏览器DOM元素可能遗漏的事件。
<强>更新强> Chrome在打开时会看到选中的mousedown,当选择打开时单击页面时,会在文档上看到鼠标。这是适用于Chrome的版本:
同样,您需要进行一些浏览器检测以处理每个浏览器中的正确行为。特别是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
其他事件有很多边缘情况表示关闭(转义按键,模糊等),但这些是处理用户点击选择框然后点击进入的情况的最小情况文件区。
希望这有帮助!
答案 1 :(得分:2)
如果您有超过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");
}
});
答案 2 :(得分:1)
我按照你的JSFiddle上的说明收到了以下事件:
BODY, mousedown, STRONG
#document, mousedown, STRONG
window, mousedown, STRONG
SELECT, blur, SELECT
BODY, click, STRONG
#document, click, STRONG
window, click, STRONG
这些是在选择菜单已经聚焦并展开后单击“HERE”时触发的所有事件。这是最新版本的Chrome。
这些中的任何一个都不足以满足您的目的吗?
编辑:如果你想确定它是你的Select元素失去焦点,设置一个全局Javascript变量,'selectFocused',并将其设置为False。当“选择”菜单获得焦点时将其设置为“真”,并在发生上述任何事件时将其设置为“假”。 'selectFocused'现在可以在代码中的任何位置使用,以检测您的Select元素当前是否具有焦点,当它更改值时,您知道您的Select元素已被选中或未被选中。
答案 3 :(得分:1)
我的第一直觉是实现这一目标的一个小迂回,它将使用您通常用于在外面按下关闭(自定义)下拉菜单的代码:
function clickInBody(){
functionToCallOnBlur();
}
function clickInBodyStop(event){
event.stopPropagation();
}
然后在您的正文标记上添加onClick="clickInBody()"
,并在您添加onClick="clickInBodyStop(event)"
的选择项目上添加functionToCallOnBlur()
。这应该在您每次点击页面时调用该事件,但如果您单击选择标记,它将停止传播,而不是调用{{1}}
答案 4 :(得分:1)
前提条件:使用jQuery!这可能只解决部分问题,但如果您在单击某个元素时正在寻找要触发的事件,则可以使用叠加div。 / p>
当用户点击选择框时:
$('#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:)
答案 5 :(得分:0)
如果我们考虑在选择框外单击,则可以是结束选择事件的信号。
以下jQuery可以做到这一点。 Here是小提琴中的代码
$(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代码:
<select multiple id="selectId">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>