我有一个菜单,我想在输入聚焦时显示它,所以我使用输入的聚焦和模糊事件来触发显示或隐藏菜单的功能。
问题是,当我想在菜单中添加事件(例如点击事件(时,输入的模糊事件总是首先触发,因此菜单的点击事件永远不会触发
下面是一个示例代码来说明我的问题:https://jsfiddle.net/f7xvg1L9/27/
function hide () {
document.getElementById('box').style.display = 'none';
}
function show () {
document.getElementById('box').style.display = 'block';
}
function select () {
document.getElementById('select').innerHTML = 'selected';
}
document.getElementById('input').addEventListener('blur', hide)
document.getElementById('input').addEventListener('focus', show)
document.getElementById('box').addEventListener('click', select)
#box {
width: 100px;
height: 50px;
background-color: red;
display: none;
}
<input type='text' id='input'/>
<div id='box'>Test</div>
<p id='select'></p>
(select((函数从未被调用(
提前感谢
您可以用CSS而不是Javascript做很多事情。
这里,为选择器input:focus + #box, #box:active
设置一个CSS规则,它显示box
。
#box:active
在盒子消失之前注册点击,没有它就无法工作。
document.getElementById('box').addEventListener('click',() => {
document.getElementById('select').innerHTML = 'selected';
});
#box {
width: 100px;
height: 50px;
background-color: red;
display: none;
}
input:focus + #box, #box:active{
display: block;
}
<input type='text' id='input'/>
<div id='box'>
Test
</div>
<p id='select'></p>
这是一个不幸的副作用。但是,使用不同的事件可以很容易地解决这个问题。
不使用焦点/模糊处理程序,您只需对所有这三个事件使用单击事件,因为聚焦输入与在输入内部单击相同。模糊输入与在输出外部单击相同。
因此,如果我们在点击输入时显示框,那么我们可以向文档的其余部分添加不同的点击事件。在该点击事件中,我们可以检查当前点击是否在框内,并采取相应的行动。
var box = document.getElementById('box');
var input = document.getElementById('input');
var change_text = function() {
box.innerHTML = 'selected';
};
var outside_click = function( event ) {
if ( !box.contains(event.target) ) {
box.style.display = 'none';
document.removeEventListener('click', outside_click);
}
};
var show_box = function( event ) {
event.stopPropagation();
box.style.display = 'block';
document.addEventListener('click', outside_click);
};
box.addEventListener('click', change_text);
input.addEventListener('click', show_box);
#box {
width: 100px;
height: 50px;
background-color: red;
display: none;
}
<input type='text' id='input'/>
<div id='box'>Test</div>
编辑:但是上面发布的CSS解决方案是一个更好更容易的解决方案。
你可以使用两种东西:
-
event.relatedTarget-这仅对上的
focus
和blur
事件有效。仅当relatedTarget
具有tabindex=1
或更大值时才包含一个值。 -
addEventListener
的useCapture
阶段,它允许您在大多数事情发生之前了解事件。
在下面的例子中,我同时使用了它们,尽管我实际上只需要使用event.relatedTarget
,因为这让我看到用户正在单击#box
,并阻止关闭框。
function hide (evt) {
if (evt.relatedTarget && evt.relatedTarget.id === 'box') {
document.getElementById('box').style.display = 'none';
document.getElementById('input').focus();
}
else {
document.getElementById('box').style.display = 'none';
}
}
function show (evt) {
document.getElementById('box').style.display = 'block';
}
function select (evt) {
document.getElementById('select').innerHTML = 'selected';
}
document.getElementById('input').addEventListener('blur', hide);
document.getElementById('input').addEventListener('focus', show);
document.getElementById('box').addEventListener('click', select, true);
#box {
width: 100px;
height: 50px;
background-color: red;
display: none;
}
<input type="text" id="input"/>
<div id="box" tabindex="1">
Test
</div>
<p id="select"></p>
我认为最快速、最简单的方法是在hide
函数中使用setTimeout
。
function hide () {
setTimeout(function(){
document.getElementById('box').style.display = 'none';
}, 300)
}
function show () {
document.getElementById('box').style.display = 'block';
}
function select () {
document.getElementById('select').innerHTML = 'selected';
}
document.getElementById('input').addEventListener('blur', hide)
document.getElementById('input').addEventListener('focus', show)
document.getElementById('box').addEventListener('click', select)
#box {
width: 100px;
height: 50px;
background-color: red;
display: none;
}
<input type='text' id='input'/>
<div id='box'>Test</div>
<p id='select'></p>