简体   繁体   English

隐藏弹出框功能恢复打开的弹出框功能

[英]Hide popup box function reverting open popup box function

I want to make a "popup" box activated by a button that reduces the opacity of all other elements.我想制作一个由按钮激活的“弹出”框,以减少所有其他元素的不透明度。 When the user clicks out of the box, it should disappear and the opacity should go back to normal.当用户单击开箱即用时,它应该消失并且不透明度应该恢复正常。 However, these two functions are conflicting with each other.但是,这两个功能是相互冲突的。 It requires me to click the button TWICE in order for showBox() to be called.它需要我单击showBox()按钮才能调用showBox() And clicking out of the box does nothing unless I reinvoke hideOnClickOutside(document.querySelector('div'));除非我重新调用hideOnClickOutside(document.querySelector('div')); in the browser's console.在浏览器的控制台中。

Why do I have to click "New Audio" twice and why does hideOnClickOutside() not work unless reinvoked?为什么我必须单击“新音频”两次,为什么除非重新调用,否则hideOnClickOutside()不起作用?

 function showBox() { document.body.style.opacity = "0.5"; document.querySelector('div').style.display = "block"; } document.querySelector('button').addEventListener('click', showBox); const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js function hideOnClickOutside(element) { const outsideClickListener = event => { if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null element.style.display = 'none'; removeClickListener() document.body.style.opacity = "1"; } } const removeClickListener = () => { document.removeEventListener('click', outsideClickListener) } document.addEventListener('click', outsideClickListener) } hideOnClickOutside(document.querySelector('div'));
 <button>New Audio</button> <div style="display: none"> <button>Record Directly</button> </div>

hideOnClickOutside() function was taken from another StackOverflow answer hideOnClickOutside()函数取自另一个 StackOverflow 答案

Edit编辑

I figured out that it requires two clicks because on the first click, showBox() is called, but immediately after, so is outsideClickListener, and at this point the element is NOW visible AND the user has clicked "outside" the element.我发现它需要点击两次,因为在第一次点击时, showBox()调用,但紧接着,outsideClickListener 也是如此,此时元素现在可见,并且用户点击了元素的“外部”。 This reverts the style changes of showBox() .这将恢复showBox()的样式更改。

The easiest fix is to store the reference to the "New Audio" button and check to see if that is the target of the click on document .最简单的解决方法是存储对“新音频” button的引用并检查它是否是单击documenttarget If so, then return from the function without updating DOM .如果是,则从函数return而不更新DOM

const button = document.querySelector('button')
button.addEventListener('click', showBox);
// ..
function hideOnClickOutside(element) {
  const outsideClickListener = event => {
    if (event.target === button) return 
// ..

Keep in mind, with the current code you have, the hideOnClickOutside function only gets until the first time isVisible is true and the target is not button , since you remove the event listener on that condition.请记住,使用您拥有的当前代码, hideOnClickOutside函数仅在第一次isVisible为 true 并且target不是button时才会获取,因为您在该条件下删除了事件侦听器。

 function showBox(e) { document.body.style.opacity = "0.5"; document.querySelector('div').style.display = "block"; } const button = document.querySelector('button') button.addEventListener('click', showBox); const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js function hideOnClickOutside(element) { const outsideClickListener = event => { if (event.target === button) return if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null element.style.display = 'none'; removeClickListener() document.body.style.opacity = "1"; } } const removeClickListener = () => { document.removeEventListener('click', outsideClickListener) } document.addEventListener('click', outsideClickListener) } hideOnClickOutside(document.querySelector('div'));
 <button>New Audio</button> <div style="display: none"> <button>Record Directly</button> </div>

The other problem is that once the showBox function is called, you actually probably want the button to be considered outside.另一个问题是,一旦调用了showBox函数,您实际上可能希望将button考虑在外部。 Let's refactor your code to store references to the showButton and box , add a flag to disable the showButton and only add the event listener to the document if the showButton is clicked and remove the event listener only when the box is displayed.让我们重构您的代码以存储对showButtonbox引用,添加一个标志以disable showButton并仅在单击showButton将事件侦听器添加到文档,并仅在显示框时移除事件侦听器。

You can later refactor this to fit your particular use case.您可以稍后重构它以适合您的特定用例。 The idea is to think of the various states this application can be in and create functions to manage that state.这个想法是考虑这个应用程序可以处于的各种状态并创建函数来管理该状态。

 const box = document.querySelector('#box'); const showButton = document.querySelector('#show-button'); showButton.addEventListener('click', showBox); let isDisabled = false; const isVisible = elem => !!elem && !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js function toggleDisabled(bool) { showButton.attributes.disabled = bool; isDisabled = bool; } function toggleDisplay(display, opacity) { document.body.style.opacity = opacity; box.style.display = display; } function showBox(event) { if (!isDisabled) { event.preventDefault(); event.stopPropagation(); toggleDisplay("block", 0.5); toggleDisabled(true); document.addEventListener('click', outsideClickListener); } } function outsideClickListener(event) { if (!box.contains(event.target) && isVisible(box)) { // or use: event.target.closest(selector) === null toggleDisplay("none", 1); toggleDisabled(false); document.removeEventListener('click', outsideClickListener) } }
 <button id="show-button">New Audio</button> <div id="box" style="display: none"> <button>Record Directly</button> </div>

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

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