对话框元素“打开”事件

问题描述 投票:0回答:4

对于对话框元素

<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();
javascript html dialog modal-dialog html-5.2
4个回答
6
投票

不,没有

open
事件。

对话框有一个

open
属性可以确定它是否打开,但不幸的是,当这个转换时没有任何事件。


2
投票

解决您问题的一个简单方法是:

<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)
  })

1
投票

正如此处的评论/回答中提到的,可以使用 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 对象上使用他们的事件方法。
它们的优点是独特,并且使代码更具可读性。
因此不妨添加这个,而不是创建特定的自定义事件!

第二个解决方案:

(() =>  // 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>


0
投票

找到这个帖子并想发布我的解决方案:自定义事件。

设置

document.querySelector('dialog').showModal();
呼叫后,您可以添加
document.querySelector('dialog').dispatchEvent(new Event('open'));
。然后预期的
document.querySelector('dialog').addEventListener('open', e => {...});
就起作用了!

© www.soinside.com 2019 - 2024. All rights reserved.