Parallels Desktop 20%OFFセール中Check!

【JavaScript】dialog要素を使ってダイアログを自作する

JavaScriptでダイアログを作る方法

JavaScriptでダイアログボックスを表示するとき、一般的にはalert(), confirm(), prompt()などのメソッドを使います。ただし、この方法で表示させるダイアログはカスタマイズができないんですよね。

この記事では、HTMLの<dialog>要素を使ってダイアログボックスを作り、JavaScriptで制御する方法を解説します。ダイアログボックスの見た目や表示内容をオシャンティにカスタマイズできちゃいます。

目次

dialog要素とは

<dialog>はウェブページにダイアログボックスを表示するためのHTML要素です。次のように記述します。

<dialog open>
  <p>一度入信したら、もう後戻りはできません。</p>
  <button>OK</button>
</dialog>

上記の例では<dialog>要素の中に<p><button>を入れましたが、何でも入れることができます。見出しをつけたり、フォームとか画像とか表とか何でもOKです。

<dialog>要素にopen属性を指定するとダイアログが表示されます。open属性を指定しなければ非表示になります。ただし、このopen属性を使うのは非推奨となっています。ダイアログの表示・非表示を制御するにはJavaScriptのshow()およびclose()メソッドを使います。

ダイアログをJavaScriptで制御する

ダイアログの表示と非表示

ダイアログの表示・非表示を制御するには、JavaScriptのshow()およびclose()メソッドを使います。

<dialog id="myDialog">
  <p>一度入信したら、もう後戻りはできません。</p>
  <button class="button ok">OK</button>
</dialog>

<button id="showButton">ダイアログを開く</button>

<script>
  //各要素を変数に代入
  const dialog = document.querySelector('#myDialog');
  const okButton = document.querySelector('#myDialog .button.ok');
  const showButton = document.querySelector('#showButton');

  //「ダイアログを開く」ボタンがクリックされたらダイアログを開く
  showButton.addEventListener('click', function () {
    dialog.show();
  });
  //「OK」ボタンがクリックされたらダイアログを閉じる
  okButton.addEventListener('click', function () {
    dialog.close();
  });
</script>

16行目、dialog.show();でダイアログが開きます。そして20行目、dialog.close();でダイアログが閉じます。

モーダルダイアログとモードレスダイアログ

ダイアログにはモーダルダイアログモードレスダイアログがあります。これらの違いを理解して、適切なダイアログ設計をしましょう。

モーダルダイアログモードレスダイアログ
概要ダイアログを開いている間は、親ページの操作ができないダイアログを開いている間も、親ページの操作ができる
ダイアログの背景暗くなる暗くならない
親ウインドウをスクロールしたとき追従しない追従する
escキーを押したとき閉じる閉じない

で、上記で解説したshow()メソッドで開くダイアログは、モードレスダイアログです。モーダルダイアログを開くにはshowModal()メソッドを使います。

dialog.showModal();

closeイベントとcancelイベント

ダイアログを閉じるとcloseイベントが発生します。これはイベントリスナーやイベントハンドラで使うことができます。

//イベントリスナーを使う例
dialog.addEventListener('close', function () {
  alert('closeイベントが発生しました');
});

//イベントハンドラを使う例
dialog.onclose = function () {
  alert('closeイベントが発生しました');
};

モーダルダイアログを閉じるためにキーボードのescキーを押すとcancelイベントが発生します。

//イベントリスナーを使う例
dialog.addEventListener('cancel', function () {
  alert('cancelイベントが発生しました');
});

//イベントハンドラを使う例
dialog.oncancel = function () {
  alert('cancelイベントが発生しました');
};

ダイアログを閉じたときの戻り値

ダイアログに2つ以上のボタンがあって、どのボタンがクリックされたかを判別したいときがあります。そのような場合はclose()メソッドに引数を与えることで戻り値を受け取ることができます。

<dialog id="myDialog">
  <p>本当に入信しますか?</p>
  <button class="button cancel">キャンセル</button>
  <button class="button ok">OK</button>
</dialog>

<button id="showButton">ダイアログを開く</button>

<script>
  //各要素を変数に代入
  const dialog = document.querySelector('#myDialog');
  const cancelButton = document.querySelector('#myDialog .button.cancel');
  const okButton = document.querySelector('#myDialog .button.ok');
  const showButton = document.querySelector('#showButton');

  //「ダイアログを開く」ボタンがクリックされたらダイアログを開く
  showButton.addEventListener('click', function () {
    dialog.showModal();
  });
  //キャンセルがクリックされたらダイアログを閉じてcancelを返す
  cancelButton.addEventListener('click', function () {
    dialog.close('cancel');
  });
  //OKがクリックされたらダイアログを閉じてokを返す
  okButton.addEventListener('click', function () {
    dialog.close('ok');
  });

  //closeイベントが発生したらalertで戻り値を表示
  dialog.addEventListener('close', function () {
    alert('returnValue: ' + dialog.returnValue);
  });
</script>

22行目でclose()メソッドに引数'cancel'を、26行目では引数'ok'を与えています。close()メソッドが実行されるとそれぞれの引数が戻り値として返されます。戻り値はreturnValueプロパティに格納されます。

31行目のようにdialog.returnValueで参照することができます。

ダイアログボックスの外側をクリックして閉じる

ここまで、ダイアログボックスを閉じるにはボタンのクリックまたはescキーを使いました。もし、ダイアログボックスの外側をクリックして閉じることができたら嬉しくないですか?私は嬉しいです。

<dialog id="myDialog">
  <div class="inner">
    <p>一度入信したら、もう後戻りはできません。</p>
    <button class="button ok">OK</button>
  </div>
</dialog>

<button id="showButton">ダイアログを開く</button>

<style>
  #myDialog {
    padding: 0;
  }
  #myDialog .inner {
    padding: 1em;
  }
</style>

<script>
  //各要素を変数に代入
  const dialog = document.querySelector('#myDialog');
  const okButton = document.querySelector('#myDialog .button.ok');
  const showButton = document.querySelector('#showButton');

  //「ダイアログを開く」ボタンがクリックされたらダイアログを開く
  showButton.addEventListener('click', function () {
    dialog.showModal();
  });
  //「OK」ボタンがクリックされたらダイアログを閉じる
  okButton.addEventListener('click', function () {
    dialog.close();
  });
  //ダイアログの外側がクリックされたらダイアログを閉じる
  dialog.addEventListener('click', function (event) {
    if (!event.target.closest('#myDialog .inner')) {
      dialog.close();
    }
  });
</script>

2, 5行目、<dialog>要素の内側に<div class="inner">を記述しておきます。この<div class="inner">の親要素(外側)がクリックされたときにダイアログが閉じるようにJavaScriptで制御します。

11〜16行目、#myDialogpadding0にして、#myDialog .innerがダイアログボックス内に目一杯広がるようにします。そして#myDialog .innerの内側に適度なpaddingを設定します。

34〜38行目、#myDialog .innerの外側がクリックされたときにダイアログを閉じるための記述です。closest()は、その要素と祖先要素を指定したセレクタで探索するメソッドです。この場合、クリックした位置(event.target)の祖先要素を取得し#myDialog .innerでなければダイアログを閉じます。

説明してて、難しいよなぁ伝わってるかなぁと思ってます。わからなかったらコピペすればいいぢゃない。

ダイアログの背景がスクロールしないようにする

デフォルトでは、ダイアログを開いているときでもその後ろの親ウインドウはスクロールできてしまいます。もし、親ウインドウを固定できたら嬉しくないですか?私は嬉しいです。

<dialog id="myDialog">
  <p>一度入信したら、もう後戻りはできません。</p>
  <button class="button ok">OK</button>
</dialog>

<button id="showButton">ダイアログを開く</button>

<style>
  body.inactive {
    overflow: hidden;
  }
</style>

<script>
  //各要素を変数に代入
  const body = document.body;
  const dialog = document.querySelector('#myDialog');
  const okButton = document.querySelector('#myDialog .button.ok');
  const showButton = document.querySelector('#showButton');

  //「ダイアログを開く」ボタンがクリックされたらinactiveクラスを追加してモーダルダイアログを開く
  showButton.addEventListener('click', function () {
    body.classList.add('inactive');
    dialog.showModal();
  });
  //「OK」ボタンがクリックされたらinactiveクラスを削除してダイアログを閉じる
  okButton.addEventListener('click', function () {
    body.classList.remove('inactive');
    dialog.close();
  });
  //escキーが押されたらinactiveクラスを削除
  dialog.addEventListener('cancel', function () {
    body.classList.remove('inactive');
  });
</script>

9〜11行目、<body>要素にinactiveクラスがついていたらスクロールできないようにするための設定です。

16行目、<body>要素を変数に入れておきます。

23行目、ダイアログを開いたら<body>要素にinactiveクラスを追加します。これで<body>がスクロールできなくなります。

28行目、ダイアログを閉じたら、<body>要素からinactiveクラスを削除します。これで<body>がスクロールできるようになります。

32〜34行目、escキーでダイアログを閉じた場合にもinactiveクラスを削除します。

プログラミング学習、お疲れさまです

プログラミングの独学に行き詰まっていませんか?誰かに相談したい、もっと効率よく学びたいなら、プログラミングスクールを検討してみてください。

ダイアログをCSSでスタイリングする

ずっと気になっていたとは思いますが、デフォルトの<dialog>のデザインはとてもダサいです。CSSで外観をカスタマイズしましょう。

ダイアログボックスの外観は一般的なブロック要素と同じようにスタイリングできます。縦横のサイズとか色とかボーダーとか影とか位置とか。ここでは詳しく解説しません(冷たい)。

そして、ダイアログ特有の要素は::backdrop擬似要素です。ダイアログをshowModal()で開いたときの背景をスタイリングすることができます。デフォルトでは、モーダルダイアログを開くと背景にうっすらと影がかかります。この影をもっと濃くしたいならば次のようにします。

<style>
#myDialog::backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}
</style>

いろいろなダイアログのスタイリング例は下記の記事でどうぞ。

さいごに

というわけで、HTMLの<dialog>要素とJavaScriptとCSSでダイアログを簡単に自作できることがおわかりいただけたかと思います。

ウェブサイトの価値はダイアログのオシャレ度で決まると言われています(どこで)。ぜひ、かっこいいダイアログの作成にチャレンジしてみてください。

でわでわ

JavaScriptでダイアログを作る方法

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次