◆ 今後に期待

いつまにかこんなタグがありました

今まではbodyタグの子要素にこんなの
<div style="position:fixed;width:100%;height:100%;background-color:rgba(0,0,0,0.35)" onclick="this.style.display='none'">     <div style="position:absolute;left:25%;right:25%;top:35%;bottom:35%;background-color:#f0f0f0;" onclick="event.stopPropagation();">          ここがダイアログ     </div> </div>
を書いてたのが楽になるのかなと期待しながら使ってみます


ですが その前に一応上のサンプルを簡単に説明しておきます
外側divでposition:fixed;width:100%;height:100%で全画面に要素を表示します
fixedなのでスクロールしてもずっと同じ位置に固定されます
この要素が上にあるせいで(おかげで)inputやaなどをクリックしても反応しなくなります
このままだと分かりづらいので背景色をrgba(0,0,0,0.35)にして半透明で暗くします
クリックされたらこの要素を非表示にします

内側divは真ん中にダイアログメッセージを表示する場所を作っているだけです
分かりやすいように背景を白色にしてます
メッセージ表示部分をクリックしてダイアログが消えないようにonclickではstopPropagationを行います

ダイアログを表示させたいときには外側divのdisplayをblockにします



では dialogタグに移ります

dialogタグでは3つ
・show
・showModal
・close
のメソッドが使えます
document.querySelector("dialog").show();
のような使い方をします

最初closeというのを見つけたのでopenと試したらそんなメソッドないとエラーが出ました
少し分かりづらいメソッド名です

show

showはダイアログを表示しますが 場所はHTML的に要素が書かれた場所で 背景も変わらないのでダイアログが出たのかどうかがわかりにくいです
dialog-sample-01
これだとdialogタグを下の方に書いてるのですごく下に出てきました

さらに 背景のaタグやinputタグにアクセス可能です

alertを表示するボタンを押してみると↓
dialog-sample-02
ダイアログが出てalertダイアログまで出てます


この状態でshowModalを実行するボタンを押してみると
Uncaught InvalidStateError: Failed to execute 'showModal' on 'HTMLDialogElement': The element already has an 'open' attribute, and therefore cannot be opened modally.
というエラー出ました
すでにダイアログが開いてるって内容です

ダイアログを出すなら他の要素にさわれなくして欲しいし 表示されたことをわかりやすくして欲しいのでshowメソッドは使いドコロがわからない いらない子です

showModal

こっちはよくある 背景が暗くなって 画面の真ん中に出てくるタイプです
ダイアログオープン中は他のinputなどを押せない良い仕様です
dialog-sample-03

ですが position:fixed というわけではなく スクロールするとdialogタグがずれます

dialog-sample-04

dialogタグにcssを使えるので position:fixedを自分で設定すれば直せます
他にも真ん中が嫌だから左の方にってこともできます

showModalはできる子!


+追記+
showModalはescapeキーでダイアログを閉じてくれます
やっぱりshowModalはできる子!

close

closeはshowやshowModalで出したdialogを閉じるものです
これを実行しないと閉じてくれません

暗いところをクリックしたら閉じたいときは自分でプログラムを書かないとダメです
方法ですが dialogタグは表示されるとこんなサイズになります
dialog-sample-05

要素が文字を表示する部分(緑色と青色)になっています
じゃあ外側はどうやって取るのということですが dialogタグに対してonclickをつけて確認すると 画面のどこをクリックしてもdialogタグをクリックしたイベントが起きています
じゃあ文字を表示する部分はどうやって取れるの??

少し調べてみたのですが 外と内を分けてクリックイベントを受け取れるon○○○はなさそうでした

なら しょうがない 無理矢理やってやる!
ということでこうなりました
window.onclick = function(eve){ var dialog = document.querySelector("dialog"); var rect = dialog.getClientRects()[0]; if(rect && (eve.clientX < rect.left || eve.clientX > rect.left + rect.width || eve.clientY < rect.top || eve.clientY > rect.top + rect.height) ){ dialog.close(); } };

getClientRects()でdialogの内側(文字を表示する部分)の場所と大きさをもってきます
クリックしたところとdialogの位置を比較して外側にあったらdialog.close();を実行しています

「rect &&」 となっているのはdialogタグが非表示のときはdialogタグのgetClientRects()の返り値の[0]がundefinedになるからです

open

メソッドにはopenはないですが 属性にopenがあります
<dialog open></dialog>
と 属性にopenがあるのがダイアログが開いている状態です

直接open属性を削除してもcloseと同じくダイアログが消えます
ですが openを直接つけるのはshowと同じ動きになり showModalにはならないです



Chromodo36だと動かない と思って調べてみると実装されたのがChrome37からなんですね
機能少ないのも納得です

メソッドやイベント増えて使いやすくなっていってほしいですね

サンプル