Как закрыть новый тег html <dialog>, щелкнув по его фону:: backdrop

Я не нашел встроенного решения или обходного пути для закрытия элемента html5, щелкнув по его фону (:: backdrop), хотя это явно базовая функциональность.

Ответ 1

Фоновые клики могут быть обнаружены с помощью ограничивающего диалога.

var dialog = document.getElementByTagName('dialog');
dialog.showModal();
dialog.addEventListener('click', function (event) {
    var rect = dialog.getBoundingClientRect();
    var isInDialog=(rect.top <= event.clientY && event.clientY <= rect.top + rect.height
      && rect.left <= event.clientX && event.clientX <= rect.left + rect.width);
    if (!isInDialog) {
        dialog.close();
    }
});

Ответ 2

Другим более эффективным решением является обертка dialog -content в div с помощью padding: 0. Таким образом, вы можете проверить event.target события click-event, который ссылается на диалог в случае фона и любого другого элемента в div в случае фактического модального.

Не проверяя фактические размеры, мы можем предотвратить циклы компоновки.

Ответ 3

Для тех, кто наткнулся на этот вопрос и хочет следовать решению, рекомендованному @meaku, вот как я решил использовать a для инкапсуляции элемента и не работать с вычислением getBoundingClientRect():

const popup = document.getElementById('popup');
const popupDialog = document.getElementById('popup-dialog');
popup.addEventListener('click', function(e){
  console.info(e.target.tagName);
  if (e.target.tagName === 'DIALOG') popupDialog.close()
});
<div id="popup" style="padding: 0">
    <dialog id="popup-dialog" style="display:none;">
        <h4>Dialog Title</h4>
        <footer class="modal-footer">
            <button id="popup-close" type="button">close</button>
            <button id="popup-ok" type="button">ok</button>
        </footer>
    </dialog>
</div>

Ответ 4

Я разобрался с очень простым решением этой проблемы. Добавьте контейнер div внутри <dialog>. Затем проверьте, является ли это родителем всего этого. Если нет, то это сам диалог, и он может быть закрыт.

HTML

<dialog id="favDialog">
  <div class="test">
  Hello
  </div>
</dialog>

JS

document.querySelector('dialog').addEventListener('click', function(e) {
  if(!e.target.closest('div')) {
    e.target.close();
  }
});

Ответ 5

Другой простой метод, похожий на метод div, упомянутый другими, заключается в предоставлении самого диалога padding: 0 (как, например, Chrome, как правило, дает заполнение диалогового окна) и добавление события click в диалог. Элемент form в любом случае улавливает разницу, поэтому нет необходимости в дополнительном div. Я заметил, что форма не использовалась ни в одном из приведенных выше примеров, поэтому я подумал, что ее стоит добавить, поскольку она является частью стандарта при работе с кнопками в диалоговом окне.

<dialog style="padding: 0; border: 0;">
  <form method="dialog">
    <button>Click here</button>
  </form>
</dialog>

<script>
  onClick(event) {
    if (event.target === dialog) {
      dialog.close();
    }
  }

  const dialog = document.querySelector('dialog');
  dialog.addEventHandler('click', onClick);
  dialog.showModal();
</script>