javascript 如何通过单击对话框外部来关闭对话框?

owfi6suc  于 2023-02-18  发布在  Java
关注(0)|答案(5)|浏览(303)

除了单击Esc按钮外,如何通过单击dialog框外部来关闭dialog框?

<!DOCTYPE html>
<html>
<body>

<p>Click the button to show the dialog.</p>

<button onclick="myFunction()">Show dialog</button>

<p><b>Note:</b> Use the "Esc" button to close the modal.</p>
<p><b>Note:</b> The dialog element is only supported in Chrome 37+, Safari 6+ and Opera 24+.</p>

<dialog id="myDialog">This is a dialog window</dialog>

<script>
function myFunction() { 
  document.getElementById("myDialog").showModal(); 
} 
</script>

</body>
</html>
mm5n2pyu

mm5n2pyu1#

HTMLDialogElement接口的showModal()方法将对话框显示为模式对话框,位于可能存在的任何其他对话框的顶部。它与::background伪元素一起显示在顶层。对话框外部的交互被阻止,对话框外部的内容被呈现为惰性。MDN documentation
正如你所看到的,在dialog之外,所有其他的html节点都将被阻塞。但是,我们可以添加一个子节点作为我们内容的 Package 器,这样我们就把我们的内容与外部区域分开了。让我们用css从dialog中移除额外的填充,并将其添加到模态类中。

const dialog = document.getElementById('myDialog');
const button = document.querySelector('button');

function openDialog() {
  dialog.showModal();
}

function closeDialog(event) {
  // If the target dialog is
  if (!event.target.contains(dialog)) return;
  dialog.close();
}

button.addEventListener('click', openDialog);
document.addEventListener('click', closeDialog);
dialog {
  padding: 0;
}

.modal {
  display: flex;
  padding: 1rem;
}

dialog::backdrop {
  background-color: rgba(255, 0, 0, 0.25);
}
<p>Click the button to show the dialog.</p>

<button>Show dialog</button>

<p><b>Note:</b> Use the "Esc" button to close the modal.</p>
<p><b>Note:</b> The dialog element is only supported in Chrome 37+, Safari 6+ and Opera 24+.</p>

<dialog id="myDialog">
  <div class="modal">
    <p>This is a dialog window</p>
  </div>
</dialog>
xnifntxz

xnifntxz2#

一般来说,你可以使用onblur-或者onfocusout-事件,当你离开元素或者点击另一个元素时,这两个事件都会触发(尽管我还没有用对话框专门测试过)。

<dialog onblur="yourFunction()">
lmyy7pcs

lmyy7pcs3#

我知道这有点不切实际,但你可以添加一个像整个屏幕一样大的div,当你点击“显示对话框”时,div的显示是块,当你点击屏幕大小的div时,对话框消失。

<!DOCTYPE html>
<html>
<body>

<p>Click the button to show the dialog.</p>

<button onclick="myFunction()">Show dialog</button>

<p><b>Note:</b> Use the "Esc" button to close the modal.</p>
<p><b>Note:</b> The dialog element is only supported in Chrome 37+, Safari 6+ and Opera 24+.</p>

<div id="close-dialog-element" onclick="closeDialog()">
    <dialog close id="myDialog">This is a dialog window</dialog>
</div>

<style>
#close-dialog-window {
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 10;
}

#myDialog {
    z-index: 11;
}
</style>

<script>
function closeDialog() {
    document.getElementById('close-dialog-element').style.display = 'none';
    document.getElementById('myDialog').close();
}

function myFunction() { 
  document.getElementById("myDialog").showModal(); 
} 
</script>

</body>
</html>
qxgroojn

qxgroojn4#

.showModal()使用了一个::backdrop,它是一个伪元素,对于DOM是不可见的,因此是不可触及的。下面的示例显示了如何使用.show()方法,以便在<dialog>之外进行单击。

    • 详细信息在示例中注解**
// Reference <dialog> and <button>
const modal = document.querySelector('.modal');
const open = document.querySelector('.open');

// Bind click event to <button>
open.onclick = openModal;
// Bind click event to <main>
document.querySelector('main').onclick = closeModal;
// Bind keydown event close the <dialog> when Esc key is clicked
document.onkeydown = e => {
  if (e.key === "Escape") {
    closeModal(e);
  }
}

function openModal(e) {
  // This opens <dialog> with no ::backdrop
  modal.show();
  // A .open to <html> so it appears there's a ::backdrop
  document.documentElement.classList.add('open');
  // Disable <button>
  this.disabled = true;
}

function closeModal(e) {
  // Reference the tag the user clicked
  const clk = e.target;
  /*
  If the user clicked the <dialog> or anything within the
  <dialog> OR the <button>...
  ... do nothing...
  ... otherwise close <dialog>...
  ... remove .open from <html>...
  ... enable <button>
  */
  if (modal.contains(clk) || clk.matches('.open')) {
    return
  }
  modal.close();
  document.documentElement.classList.remove('open');
  open.disabled = false;
}
/* Simulate a ::backdrop */
:root.open {
  overflow: hidden;
  background-color: rgba(0, 0, 0, 0.2);
}

/* Cover all of viewport */
main {
  width: 100%;
  min-height: 100vh;
}

/* When <dialog> is open <button> should be inert */
.open .open {
  pointer-events: none;
}
<!DOCTYPE html>
<html>

<body>
  <!-- Wrap everything with <main> -->
  <main>
    <p>Click the button to show the dialog.</p>

    <button class='open'>Show Modal</button>

    <dialog class="modal">
      <p><b>Note:</b> Use the "Esc" button to close the modal.</p>
      <p><b>Note:</b> Or click outside of modal to close it.</p>
    </dialog>

  </main>
</body>

</html>
xnifntxz

xnifntxz5#

你也可以试试亚当·阿盖尔描述的方法:https://web.dev/building-a-dialog-component/#adding-light-dismiss
1.获取对话框元素并向对话框元素添加事件侦听器

const dialog = document.querySelector('dialog);

    dialog.addEventListener('click', lightDismiss);

1.创建处理函数,检查dialog元素是否触发了事件。如果是,调用.close()方法。这是因为,默认情况下,dialog元素创建了一个背景,覆盖了页面上的所有其他元素,然后点击那里===点击dialog元素本身。这不会影响dialog内部的子元素,所以点击那里不会关闭对话框。

const lightDismiss = ({target:dialog}) => {
      if (dialog.nodeName === 'DIALOG')
        dialog.close('dismiss')
    }

顺便说一句,我推荐阅读这本精彩的dialog tutorial

相关问题