beforeunloadイベントと確認ダイアログ
Changes you made may not be saved.
フォームの入力中とかにページを離脱しようと出るアレのこと。
昔から微妙に使われてるくせに、いまいち挙動が不定でブラウザ差異もあって釈然としない。
最近はどうなってるのか知る必要が出たので、改めて調べた。
基本のかたち
コードとしてはこう書けばよい。
window.addEventListener("beforeunload", (ev) => { // unloadをキャンセル = 本当に離れるのかを確認する ev.preventDefault(); });
イベントハンドラ内で、`preventDefault()`すれば、非同期でダイアログが出せる。
と、Specにも書いてある。
ただし、ブラウザによってはそれだけではダメなやつがある。
Chrome
それがまさかのChrome!
Chromeの場合はこう。
window.addEventListener("beforeunload", (ev) => { // なくてもいい // ev.preventDefault(); ev.returnValue = ""; });
という具合に、イベントオブジェクトの`returnValue`に文字列を代入する必要がある。
空文字列でもいいし、何かしらの文字列でもいいけど、指定したとしても、確認ダイアログにそれが出るわけではない。
まとめ
window.addEventListener("beforeunload", (ev) => { if (shouldUnload) return; ev.preventDefault(); ev.returnValue = ""; });
特定の条件でだけ引き止めたい時は、こんな風に変数を見るようにして、`shouldUnload`を`false`にすればよい。
あと、独自のUIでの引き止めは、現状どうやってもできない。
確認ダイアログの文言はいじれないし、ダイアログ出さずに遷移をキャンセルする方法もなさそう。
あとは、単にリロードしただけのような場合(ユーザーアクションがなにもない場合)は、確認ダイアログが表示されないようになってる。(ブラウザの粋な計らいっぽい)
あとあと、遠い記憶でモバイルでは`beforeunload`が発火しないとかあった気がする。