ウィンドウを閉じるときに任意のメッセージを設定したダイアログを表示する事ができなかった記録

注意:このページで「ウィンドウを閉じるときに任意のメッセージを設定したダイアログを表示する」方法はわかりません。

- 動作確認した環境
    - MacOS Mojave 10.14.6
    - Google Chrome 78.0
    - Fire Fox 70.0
    - Safari 13.0

# やりたいこと
ブラウザにおいてユーザが[x]ボタンや`Ctrl + W`でウィンドウを閉じる時に任意のメッセージを表示した[OK][キャンセル]ボタンがあるダイアログを表示したい。

## ボタンのイベントでは似たようなことがよくあるので難しいと思っていなかった・・・。
サイト側でウィンドウを閉じられなくするなんてセキュリティ的に問題になるよね、ってことに気がつくのが遅かったのです。
MacのChrome
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/7b8efa23-ef18-7eb1-db95-2f9f2abe8cd1.gif)

```js:sample.js
/** [閉じる]ボタン押下処理. */
function onClickClose() {
    let result = confirm('本当に閉じていいの？');
    if (result) {
        window.close();
    }
}
```
```html
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" charset="utf-8">
    <title>ウィンドウを閉じるときにメッセージダイアログを表示したい</title>
    <script src="https://code.jquery.com/jquery-1.11.0.min.js" integrity="sha256-spTpc4lvj4dOkKjrGokIrHkJgNA0xMS98Pw9N7ir9oI=" crossorigin="anonymous"></script>
    <script src="sample.js"></script>
</head>
<body>
    <table>
        <tr><td>入力欄</td><td><input id="pasteArea" type="text"></td></tr>
        <tr><td colspan="2"><input type="button" id="close" value="閉じる" onclick="onClickClose();"></td></tr>
    </table>
</body>
</html>
```

# ウィンドウを閉じるのは、`beforeunload`イベントでキャッチできる
[Window: beforeunload イベント - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/beforeunload_event)

## `beforeunload`イベントでは`confirm()`が使えなかった
> HTML 仕様書は window.alert(), window.confirm(), window.prompt() などのメソッドが、このイベントの実行中には無視されることがあることを示しています。
> [Window: beforeunload イベント - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/beforeunload_event)

MacのFireFox
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/0333e344-be18-3f44-0fcf-e2aa9fe90ce6.gif)

```js:sample.js
$(window).on('beforeunload', function(e) {
    // ウィンドウを閉じる時にメッセージを表示する.
    let result = confirm('本当に閉じていいの？');
    return result;
});
```

## イベントの返却値に任意のメッセージを設定してもダイアログには表示されない
MacのSafari
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/28ed3572-8811-c132-7b33-63132a9cb723.gif)

```js
$(window).on('beforeunload', function(e) {
    // ウィンドウを閉じる時にメッセージを表示する.
    return '本当に閉じていいの？';
});
```

## `preventDefault()`を呼び出したけれどダイアログには表示されない
> 仕様書によれば、確認ダイアログを表示するためにはイベントハンドラーでイベントの preventDefault() を呼び出すことになっています。
> [Window: beforeunload イベント - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/beforeunload_event)

MacのChrome
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/68d3dc60-840b-dcc3-21f2-a23a4d1340d3.gif)

```js:sample.js
$(window).on('beforeunload', function(e) {
    e.preventDefault();
    // ウィンドウを閉じる時にメッセージを表示する.
    return '本当に閉じていいの？';
});
```

## `returnValue`に任意のメッセージを設定してもダイアログには表示されない
MacのFireFox
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/9c00e966-5f36-8edf-e90d-e0579bfe8680.gif)

```js:sample.js
$(window).on('beforeunload', function(e) {
    e.preventDefault();
    // ウィンドウを閉じる時にメッセージを表示する.
    e.returnValue = '本当に閉じていいの？';
    return '';
});
```

# そもそも、IE以外のいろんなブラウザがカスタムメッセージへの対応をやめている
- [Chrome](https://www.chromestatus.com/feature/5349061406228480)
- [Safari](https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_9_1.html)

画像参照元 : [Window: beforeunload イベント - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Window/beforeunload_event)
![スクリーンショット 2019-11-24 16.38.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/9a28b5b7-b468-d114-8db2-09278e21c3c9.png)

# 自作のダイアログが使えるか試してみる
カスタムメッセージが表示できないのなら、自作のダイアログを表示できないかを試してみます。

## jQuery UIでダイアログをとりあえず自作してみる
[Dialog | jQuery UI 1.10 日本語リファレンス | js STUDIO](http://js.studio-kingdom.com/jqueryui/widgets/dialog)
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/b9d0fbcb-2ffc-b0ba-c3fe-172111dff989.gif)

```js:sample.js
...省略...
$(window).on('load', function() {
    createDialog();
});

/** 自作ダイアログを設定する. */
function createDialog() {
    $('#mydialog').dialog({
        title: '本当に閉じていいの？',
        autoOpen: false,
        modal: true,
        height: 0,
        width: 200,
        closeText: 'x',
        buttons: [
            {text: '閉じない', click: function() {
                $(this).dialog('close');
            }}
        ]
    });
}

/** 自作ダイアログ押下処理. */
function onClickMyClose() {
    $('#mydialog').dialog('open');
}
```
```html
...省略...
        <tr><td colspan="2"><input type="button" id="close" value="閉じる" onclick="onClickClose();"></td></tr>
        <!-- ↓ここを追加 -->
        <tr><td colspan="2"><input type="button" id="myClose" value="自作ダイアログ" onclick="onClickMyClose();"></td></tr>
    </table>
...省略...
```

## ウィンドウを閉じるときに自作ダイアログを表示したがうまくいかなかった
### ブラウザのダイアログが出てしまう
MacのFireFox
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/350e6ce6-cd1a-75fb-484b-7147b51d2f7a.gif)

```js:sample.js
$(window).on('beforeunload', function(e) {
    e.preventDefault();
    // ウィンドウを閉じる時にメッセージを表示する.
    $('#mydialog').dialog('open');
});
```

### ブラウザのダイアログを出さないとウィンドウが閉じてしまう
MacのFireFox
![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/08fb7420-6338-a391-d341-f975cb6a923e.gif)

```js:sample.js
$(window).on('beforeunload', function(e) {
    // ウィンドウを閉じる時にメッセージを表示する.
    $('#mydialog').dialog('open');
});
```

## そもそも、ウィンドウを閉じるイベントをキャンセルする方法がわからない
たとえ、タイマーかななんかで自作ダイアログを表示できたとしても「ウィンドウを閉じるイベントをキャンセルする方法がわからない」という根本的な事に気がついた:sob:

# 参考情報
- [onbeforeunload が変わってた](http://var.blog.jp/archives/70707876.html)
- [離脱時に確認メッセージを表示する方法 │ Web備忘録](https://webbibouroku.com/Blog/Article/js-unload-confirm)
(https://developer.mozilla.org/ja/docs/Web/Events/beforeunload)
- [jQuery UI を用いてオリジナルのダイアログを実装する方法！](https://webllica.com/jquery-ui-dialog/)
- [Dialog | jQuery UI 1.10 日本語リファレンス | js STUDIO](http://js.studio-kingdom.com/jqueryui/widgets/dialog)