👌

簡単なダイアログ表示機能 | HTML, CSS, JS

2024/04/29に公開

ダイアログ表示機能

表示イメージ

ソースコード

ディレクトリ構成

    /
    ├ index.html
    ├ dialog.css
    └ dialog.js

HTML / index.html

index.html
<!-- dialog.js インポート -->
<script src="./dialog.js" inline></script>

<!-- dialog テンプレート -->
<div class="dialog hide" id="dialog">
    <div class="dialog dialog__header">
        <h1 class="dialog dialog__header__title" id="dialog_title">
            <!-- ここにタイトルが入る -->
        </h1>
    </div>
    <div class="dialog dialog__body">
        <p id="dialog_message">
            <!-- ここに本文が入る -->
        </p>
    </div>
    <div class="dialog dialog__footer">
        <button class="dialog dialog__btn__sub" id="dialog_subbtn">
            キャンセル</button>
        <button class="dialog dialog__btn__main" id="dialog_mainbtn">
            OK</button>
    </div>
</div>

<!-- dialog 初期化 -->
<script>
    document.addEventListener('DOMContentLoaded', (e) => {
        dialog.init('#dialog'); // dialog テンプレートの Element ID を指定する
    });
</script>

CSS / dialog.css

dialog.css
.dialog {
  --blue: #003dea;
  --white: #fff;
  --black: #777;
  --shadow-black: rgba(0, 0, 0, .5);
}

/* ダイアログ外枠 */
#dialog {
  width: 30vw;
  min-width: 380px;
  background-color: var(--white);
  border: 1px solid var(--black);
  border-radius: .2rem;
  box-shadow: 0 10px 25px 0 var(--shadow-black);
  z-index: 200;

  position: fixed;
  margin: auto;  
  left: 50%;
  top: 50%;
  transform: translateX(-50%)
             translateY(-50%);
  padding: 1rem 2rem;

  display: flex;
  flex-direction: column;
  gap: 1rem;
}
#dialog.hide {
  display: none;
}

/* ダイアログ内要素リセット */
.dialog * {
  margin: 0;
  padding: 0;
}

/* Header */
.dialog__header__title {
  font-size: 1.8rem;
  line-height: 1.8rem;
}

/* Body */
.dialog.dialog__body p {
  margin: 0;
  line-height: 1.4rem;
}

/* Footer */
.dialog.dialog__footer {
  display: flex;
  justify-content: space-between;
}

/* キャンセルボタン */
.dialog.dialog__btn__sub {
  background-color: white;
  color: var(--blue);
  border: 0;
}
.dialog.dialog__btn__sub:hover {
  text-shadow: 1px 2px 3px var(--shadow-black);
  text-decoration: underline;
  cursor: pointer;
}

/* OK ボタン */
.dialog.dialog__btn__main {
  background-color: var(--blue);
  color: var(--white);
  border: 0;
  border-radius: .2rem;
  padding: 0 2rem;
}
.dialog.dialog__btn__main:hover {
  box-shadow: 0 10px 25px 0 var(--shadow-black);
  text-decoration: underline;
  cursor: pointer;
}

JavaScript / dialog.js

dialog.js
const dialog = {
  status: false,
  element: null,
  mainHandler: null, /** @type {function|null} OK ボタンのクリックイベント関数 */
  subHandler: null, /** @type {function|null} キャンセルボタンのクリックイベント関数 */
};

(function() {
  /**
   * ダイアログ要素をメモリに保存する
   * @param {string} elementId ダイアログの要素 ID
   */
  dialog.init = (elementId) => {
    dialog.element = document.querySelector(elementId);
    if (!dialog.element) {
      console.error('[dialog.js] ERROR: dialog.element is undefined');
    } else {
      console.log('[dialog.js] dialog.init', dialog.element);
      dialog.hide();
    }
  }

  /**
   * ダイアログを非表示にする
   */
  dialog.hide = () => {
    if (!dialog.status) return;
    dialog.element.classList.add('hide');
    dialog.element.querySelector('#dialog_mainbtn')
      .removeEventListener('click', dialog.mainHandler);
    dialog.element.querySelector('#dialog_subbtn')
      .removeEventListener('click', dialog.subHandler);
    dialog.status = !dialog.status;
  }

  /**
   * ダイアログを表示する
   * @param {{title: string, message: string,
   *  mainHandler: function, subHandler: function}}
   * mainHandler: OK ボタンのクリックイベント関数, デフォルトは dialog.hide.
   * subHandler: キャンセルボタンのクリックイベント関数, デフォルトは dialog.hide.
   */
  dialog.show = ({
    title,
    message,
    mainHandler = dialog.hide,
    subHandler = dialog.hide,
  }) => {
    if (dialog.status) return;
    dialog.mainHandler = mainHandler;
    dialog.subHandler = subHandler;
    dialog.element.querySelector('#dialog_title')
      .innerText = title;
    dialog.element.querySelector('#dialog_message')
      .innerText = message;
    dialog.element.querySelector('#dialog_mainbtn')
      .addEventListener('click', mainHandler);
    dialog.element.querySelector('#dialog_subbtn')
      .addEventListener('click', subHandler);
    dialog.element.classList.remove('hide');
    dialog.status = !dialog.status;
  }

})();

使い方

表示には dialog.show(<options>), 非表示には dialog.hide() を実行するだけ.

dialog.show({
    title: 'ダイアログ',
    message: 'ダイアログを表示しています.',
    mainHandler: function() {
        alert('okが押されました!');
        dialog.hide();
    },
    subHandler: function() {
        alert('キャンセルが押されました!');
        dialog.hide();
    }
});

mainHandler, subHandler は省略できて、その場合、dialog.hide() が割り当てられる.

dialog.show({
    title: 'ダイアログ',
    message: 'ダイアログを表示しています.',
});

初期化 dialog.init(<Element ID>) は忘れずに.

Discussion