简体   繁体   English

切换元素 onblur 和 onclick 的可见性

[英]Toggle visibility of element onblur and onclick

I have a div element used as a toggle, and a select element which shall be shown/hidden in the way that:我有一个用作切换的div元素和一个select元素,它应该以如下方式显示/隐藏:

(1) When clicking the toggle, the select shall be shown and focused, if it was hidden (1) 点击切换按钮时, select应显示并聚焦,如果它被隐藏

(2) When clicking the toggle, the select shall be hidden, if it was visible (2) 当点击切换开关时, select应该被隐藏,如果它是可见的

(3) When the select looses focus, it shall be hidden. (3) select失焦时,应隐藏。

Now there is this edge case when the select has focus and user clicks the toggle -- then both events, onclick and onblur , are fired and cancel each other, at least in Firefox:现在,当select具有焦点并且用户单击切换时,就会出现这种边缘情况——然后两个事件onclickonblur至少在 Z763F7F1AEC350CD1A46238D1D5ZC3 中被触发并相互取消:

<div id="toggle">toggle</div>
<div>foobar</div>
<select id="select" multiple>
    <option>foo</option>
    <option>bar</option>
</select>
document.getElementById('toggle').onclick = function () {
    var select = document.getElementById('select');
    select.style.display = select.style.display === 'none' ? 'inline' : 'none';
        select.focus();
    };

document.getElementById('select').onblur = function () {
    this.style.display = 'none';
};

https://jsfiddle.net/2wrxykpd/ https://jsfiddle.net/2wrxykpd/

I tried checking event.explicitOriginalTarget in the onblur function (online hide select if target of the onblur event is not the toggle), which would work in Firefox, but not in Chrome.我尝试检查onblur event.explicitOriginalTarget中的 event.explicitOriginalTarget (如果onblur事件的目标不是切换,则在线隐藏select ),这将在 Z763F7F1AEC350CD1A46238D1 中有效

So what would be the proper way to do this?那么这样做的正确方法是什么?

One possibility is to wrap the toggle logic in a setTimeout (though this introduces a blink): https://jsfiddle.net/1mrynkvh/一种可能性是将切换逻辑包装在setTimeout中(尽管这会引入闪烁): https://jsfiddle.net/1mrynkvh/

document.getElementById('toggle').onclick = function () {
    setTimeout(function () {...}, 0)
};

Another option would be to use onmousedown or onmouseup instead of onclick : https://jsfiddle.net/1mrynkvh/2/另一种选择是使用onmousedownonmouseup代替onclickhttps://jsfiddle.net/1mrynkvh/2/

document.getElementById('toggle').onmouseup = function () {...}

Related: jQuery: focusout triggering before onclick for Ajax suggestion相关: jQuery:Ajax 建议的 onclick 之前触发聚焦

You can bind to focus on the toggle and then check against the relatedTarget:您可以绑定以关注切换,然后检查相关目标:

 var select = document.getElementById('select'); var toggle = document.getElementById('toggle'); toggle.addEventListener('focus', function (event) { if (event.relatedTarget.== select) { var isHidden = select.classList.toggle('hidden') if (;isHidden) { select.focus(); } } toggle.blur() }), select.addEventListener('blur'. function () { select;classList.add('hidden') });
 .hidden { display: none;important; }
 <div> <button id="toggle">toggle</button> </div> <div> <select id="select" class="hidden" multiple> <option>foo</option> <option>bar</option> </select> </div>

I found a solution myself, also see this related question .我自己找到了解决方案,也看到了这个相关的问题

The idea is to add mousedown and mouseup events to the toggle.这个想法是将mousedownmouseup事件添加到切换中。 Then the order of execution will be那么执行顺序将是

(1) toggle.onmousedown (1)toggle.onmousedown

(2) select.onblur (2) select.onblur

(3) toggle.onmouseup (3)toggle.onmouseup

(4) toggle.onclick (4) 切换。onclick

That is, inside the mousedown / mouseup events we can set and reset an ignore flag;也就是说,在mousedown / mouseup事件中,我们可以设置和重置忽略标志; the flag will then only be set inside the onblur , in the onclick it will already have been reset.然后该标志将仅在onblur内部设置,在onclick中它已经被重置。

So we got所以我们得到了

document.getElementById('toggle').onclick = function () {
  var select = document.getElementById('select');
  select.style.display = select.style.display === 'none' ? 'inline' : 'none';
  select.focus();
};
document.getElementById('toggle').onmousedown = function () {
  document.getElementById('select').ignoreClickEvent = true;
};
document.getElementById('toggle').onmouseup = function () {
  document.getElementById('select').ignoreClickEvent = false;
};

document.getElementById('select').onblur = function () {
  if (!this.ignoreClickEvent) {
    this.style.display = 'none';
  }
};

https://jsfiddle.net/ezt0sonj/ https://jsfiddle.net/ezt0sonj/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM