对话框元素"打开"事件



对于对话框元素<dialog>,是否有某种"打开"事件在正常或作为模态显示时触发?

规范对此并不完全清楚,MDN 只列出了一堆继承的事件。

close事件确实触发了,但我似乎无法获得任何类型的open事件。

示例 HTML:

<dialog>
  <h1>Oh hey, a dialog...</h1>
</dialog>

在 JavaScript 中:

document.querySelector('dialog').addEventListener('open', (e) => {
  console.log(e);
});
document.querySelector('dialog').showModal();

不,没有open事件。

该对话框具有一个 open 属性,可以确定它是否已打开,但不幸的是,当此转换时没有事件。

一个简单的问题解决方案是这样的:

<dialog id="dial">
  <h3> dialog element </h3>
  <button id="close">x</button>
</dialog>
<button id="buttonDialog" > Open   </button>
<button id="buttonDialog2"> Open 2 </button>
const
  dialog  = document.getElementById('dial')
, close   = document.getElementById('close')
, button  = document.getElementById('buttonDialog')
, button2 = document.getElementById('buttonDialog2')
  ;
button.addEventListener('click', event => {
  dialog.showModal()
  })
close.addEventListener('click', event => {
  dialog.close()
  })
let observer = new MutationObserver(function()  {
  if (event[0].attributeName == 'open') console.log('updated')
  });
observer.observe(dialog, { attributes: true })
  ;
button2.addEventListener('click', event => {
  dialog.setAttribute('open', true)
  })

正如这里的注释/anwers中提到的,可以使用MutationObserver((生成此事件。

由于这里的答案似乎非常不完整(甚至是错误的(,我做了自己的实验来组成一个容易被利用的答案。

注 :_ <dialog> JS 对象始终具有 open 属性,并且它是一个布尔值(true 或 false(,即使此属性不存在在 HTML 声明中也是如此。

第一个解决方案:

(() =>  // IIFE => add  event 'dialog-open' to all Dialog elements
  {
  const
    OpenEvent = new CustomEvent('dialog-open') 
  , ObserverM = new MutationObserver( recs =>
    {
    recs.forEach( ({attributeName: attr, target: dial }) =>
      {
      if (attr === 'open' && dial.open )
        dial.dispatchEvent( OpenEvent );    
      })
    });
  document.querySelectorAll('dialog').forEach( dial =>
    {
    ObserverM.observe( dial, { attributes: true } );
    })
  })() // IIFE end...
const
  btShowDial = document.querySelector('#bt-show_mDialog')
, dialogBox  = document.querySelector('#dialog-box')
, dialBForm  = document.querySelector('#dialog-box form')
  ;
btShowDial.onclick =_=>
  {
  dialogBox.showModal()
  }
dialogBox.addEventListener('dialog-open', () =>
  {
  dialBForm.inNum.valueAsNumber =  0 | Math.random() *10**4
  dialogBox.returnValue = 'exit with Escape key'
  })
dialogBox.onclose=_=>
  {
  console.log(`${dialBForm.inNum.value } is ${dialogBox.returnValue}` )
  }
<button id="bt-show_mDialog">show modal dialog..</button>
<dialog id="dialog-box">
  <form method="dialog">
    <h3>Dialog -1-</h3>
    <label> mumeric : <input type="number" name="inNum"></label>
    <br>
    <button value="good"> good </button>
    <button value="bad" > bad </button>
  </form>
</dialog>

就个人而言,我更喜欢直接在 DOM Objects.
上使用他们的事件方法它们的优点是独一无二,并使代码更具可读性.
所以不妨添加这个,而不是创建一个特定的自定义事件!

第二个解决方案:

(() =>  // IIFE => add  event 'dialog-open' to all Dialog elements
  {
  const Dialogs = document.querySelectorAll('dialog');
  Dialogs.forEach( dial => dial.onOpen = function(){} )  // add onOpen empty method.
  const ObserverM = new MutationObserver( recs =>
    {
    recs.forEach( ({attributeName: attr, target: dial }) =>
      {
      if (attr === 'open' && dial.open ) dial.onOpen();  // call onOpen Method...  
      })
    });
  Dialogs.forEach( dial => ObserverM.observe( dial, { attributes: true }))
  })() // IIFE end...
const
  btShowDial = document.querySelector('#bt-show_mDialog')
, dialogBox  = document.querySelector('#dialog-box')
, dialBForm  = document.querySelector('#dialog-box form')
  ;
btShowDial.onclick =_=>
  {
  dialogBox.showModal()
  }
dialogBox.onOpen =_=>
  {
  dialBForm.inNum.valueAsNumber =  0 | Math.random() *10**4
  dialogBox.returnValue         = 'exit with Escape key'
  }
dialogBox.onclose=_=>
  {
  console.log(`${dialBForm.inNum.value } is ${dialogBox.returnValue}` )
  }
dialog::backdrop {
  background: #00ddff5d;
  }
<button id="bt-show_mDialog">show modal dialog..</button>
<dialog id="dialog-box">
  <form method="dialog">
    <h3>Dialog -1-</h3>
    <label> mumeric : <input type="number" name="inNum"></label>
    <br>
    <button value="good"> good </button>
    <button value="bad" > bad </button>
  </form>
</dialog>

最新更新