Dialog を Modal で使うための最小のコード


この記事は dialog を使ってるので Chrome でみてください。

最小のコード

HTML で Modal Dialog を使う最小のコードはこんな感じ。

<dialog id=Dialog>
    Hello<br>
    <input id=DialogCancel type=button value=Cancel>
</dialog>
<input id=OpenDialog type=button value=Open>
<br>
Result: <span id=Result></span>
const I = $ => document.getElementById( $ )
const dialog = I( 'Dialog' )
I( 'DialogCancel' ).onclick = ev => dialog.close( 'Cancel' )
I( 'OpenDialog'   ).onclick = ev => {
  dialog.showModal()
  dialog.oncancel = ev => dialog.close( 'Escape' ) 
  dialog.onclose  = ev => I( 'Result' ).textContent = dialog.returnValue
}

こうすると以下の2つの場合にダイアログは終了する。

  • ボタンが押された時
  • エスケープキーが押された時

ボタンの onclick でダイアログをクローズしてやって、その時に引数に渡したものが dialog の onclose 時に returnValue に入ってくるのでそれで何ボタンが押されたか判断すればいい。

エスケープキーが押された場合のために、dialog の oncancel で close に何か(ここでは Escape という文字列)を渡す。

See the Pen GRpgwwQ by Satachito (@satachito) on CodePen.

バックドロップのクリックで閉じたい場合

バックドロップ(モーダルダイアログが出てる時のページの輝度の下がっている部分)でクリックされた時も閉じたい場合はちょっと工夫がいる。以下輝度の下がっていない部分は「本体」

<dialog id=Dialog>
  <div>
    Hello<br>
    <input id=DialogCancel type=button value=Cancel>
  </div>
</dialog>
<input id=OpenDialog type=button value=Open>
<br>
Result: <span id=Result></span>
dialog {
; padding : 0 
}
  const I = $ => document.getElementById( $ )
  const dialog = I( 'Dialog' )
  I( 'DialogCancel' ).onclick = ev => dialog.close( 'Cancel' )
  dialog.onclick              = ev => ev.target == dialog ? dialog.close( 'Backdrop' ) : void 0
  I( 'OpenDialog'   ).onclick = ev => {
    dialog.showModal()
    dialog.oncancel = ev => dialog.close( 'Escape' ) 
    dialog.onclose  = ev => I( 'Result' ).textContent = dialog.returnValue
  }
  • dialog の onclick で ev.target に実際にクリックされたエレメントが入ってくる。
  • バックドロップも dialog の一部なので、クリックされた場合 ev.target は dialog になる。
  • dialog の本体がクリックされた場合、直下の div が本体全体を覆っているので ev.target は直下の div になる。
  • なので dialog の onclick で、ev.target が dialog であればバックドロップでクリックされている。

ここで注意点は以下の2つ

  • dialog の直下に div を置く
  • dialog の padding を 0 にする

これをやらないと本体の余白の部分でクリックした時も close してしまう。

padding が必要な場合は、直下の div につけてやればいい。

See the Pen LYpEXPY by Satachito (@satachito) on CodePen.