javascript - 隐藏弹出框功能 恢复打开弹出框功能

标签 javascript html dom dom-events

我想制作一个由按钮激活的“弹出”框,以减少所有其他元素的不透明度。当用户点击框外时,它应该消失并且不透明度应该恢复正常。然而,这两个功能是相互冲突的。它需要我单击按钮两次才能调用 showBox() 。除非我在浏览器控制台中重新调用 hideOnClickOutside(document.querySelector('div')); ,否则单击框外不会执行任何操作。

为什么我必须单击“新音频”两次,并且为什么除非重新调用,否则 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() 函数取自 another StackOverflow answer

编辑

我发现它需要两次单击,因为在第一次单击时,showBox() 被调用,但紧接着,outsideClickListener 也被调用,此时元素现在可见,并且用户已单击元素“外部”。这将恢复 showBox() 的样式更改。

最佳答案

最简单的解决方法是存储对“新音频”按钮的引用,并检查它是否是点击文档<的目标/。如果是这样,则从函数返回而不更新DOM

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

请记住,使用您当前的代码,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>

另一个问题是,一旦调用 showBox 函数,您实际上可能希望在外部考虑 button。让我们重构您的代码以存储对 showButtonbox 的引用,添加一个标志来禁用 showButton 并且仅如果单击 showButton,则将事件监听器添加到文档,并仅在显示该框时删除事件监听器。

您可以稍后重构它以适合您的特定用例。这个想法是考虑该应用程序可能处于的各种状态并创建函数来管理该状态。

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>

关于javascript - 隐藏弹出框功能 恢复打开弹出框功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60728755/

相关文章:

facebook - 如何使 DOM 元素即使在重新加载页面时也始终可见?

javascript - 总结数组的对象

javascript - 如何在使用 node.js 时将数据发送到指定连接

html - CSS div 样式在 HTML 中不起作用

html - max-height max-width 100% 但在调整浏览器大小时拉伸(stretch)图像

dom - Google Chrome 扩展 - 访问 DOM

javascript - AWS CORS 问题 : Ajax response comes as Error even after getting 200 status code

javascript - mdDatepicker 在 AngularJS 1.5.9 和 1.6 中被破坏

javascript - Phonegap - Android 4.4 - html5 音频长度错误(javascript 和媒体插件)

javascript - 使用 JavaScript 拆分和连接四个文本字段的名称