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

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

firefoxでは使えないみたい。

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

```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解説

```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);
	
```

#終わり

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