LoginSignup
0
0

More than 1 year has passed since last update.

dialogタグを使ってモーダルウィンドウ

Last updated at Posted at 2021-09-10

html5のdialogタグを使ってモーダルウィンドウ実装するとどうなるのか試してみたかった。

firefoxでは使えないみたい。

HTML

クラス構文使って以下の通りに。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
</head>

<body>

<dialog id="dialog">
    <p class="message"></p>
    <button>OK</button>
    <button>CANCEL</button>
</dialog>

<button id="btn1">btn1</button>
<button id="btn2">btn2</button>

<script>

    class Modal {
        constructor(dialog){
            if (dialog.tagName!=='DIALOG') throw 'target is not DIALOG'
            if (dialog.classList.contains('modal-instance')) throw 'target is used'
            dialog.classList.add('modal-instance')

            this.dialog = dialog

            this._close = e => e.target.tagName==='BUTTON' && dialog.close(e.target.textContent)
            this._after = e => this.fn(e.target.returnValue, ...this.args)

            dialog.addEventListener('click', this._close, false)
            dialog.addEventListener('close', this._after)
        }
        open(msg='', fn, ...args){
            if (typeof fn!=='function') return

            this.dialog.querySelector('.message').textContent = msg
            this.dialog.showModal()

            this.fn = fn
            this.args = args
        }
    }

    const modal = new Modal(document.getElementById('dialog'));

    const afterModal = (rv, btnId, a, b) => {
        if (rv==='CANCEL') return console.log(rv)
        switch (btnId) {
            case 'btn1':
                console.log(btnId, a+b)
                break
            case 'btn2':
                console.log(btnId, a*b)
                break
        }
    }
    document.getElementById('btn1').addEventListener('click', e => {
        modal.open('btn1 question', afterModal, 'btn1', 5, 5)
    }, false);
    document.getElementById('btn2').addEventListener('click', e => {
        modal.open('btn2 question', afterModal, 'btn2', 5, 5)
    }, false);

</script>
</body>
</html>

javascript解説

    class Modal {
        constructor(dialog){    //利用したいDIALOGを指定
            if (dialog.tagName!=='DIALOG') throw 'target is not DIALOG'
            //既に利用されているか確認
            if (dialog.classList.contains('modal-instance')) throw 'target is used'
            dialog.classList.add('modal-instance')

            this.dialog = dialog

            //ダイアログ内のボタンを押した時の処理
            //ボタンの文字列を取得
            this._close = e => e.target.tagName==='BUTTON' && dialog.close(e.target.textContent)
            //閉じた後の処理。指定の関数を実行
            this._after = e => this.fn(e.target.returnValue, ...this.args)

            dialog.addEventListener('click', this._close, false)
            dialog.addEventListener('close', this._after)
        }
        open(msg='', fn, ...args){
        //引数1: ダイアログ内で表示するメッセージ
        //引数2: 閉じた後に実行する関数。引数=(押したボタンの文字列, ...引数3)
        //引数3以降: 引数2の関数で利用する引数
            if (typeof fn!=='function') return

            this.dialog.querySelector('.message').textContent = msg
            this.dialog.showModal()

            this.fn = fn
            this.args = args
        }
    }


    //以降、使用例
    const modal = new Modal(document.getElementById('dialog'));

    const afterModal = (rv, btnId, a, b) => {
        if (rv==='CANCEL') return console.log(rv)
        switch (btnId) {
            case 'btn1':
                console.log(btnId, a+b)
                break
            case 'btn2':
                console.log(btnId, a*b)
                break
        }
    }
    document.getElementById('btn1').addEventListener('click', e => {
        modal.open('btn1 question', afterModal, 'btn1', 5, 5)
    }, false);
    document.getElementById('btn2').addEventListener('click', e => {
        modal.open('btn2 question', afterModal, 'btn2', 5, 5)
    }, false);

終わり

もっと上手いやり方ありそう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0