1. ホーム
  2. ジャバスクリプト

[解決済み】未保存の変更を含むウェブページを離れる前にユーザーに警告を表示する

2022-03-24 13:41:07

質問

私のアプリケーションには、フォームがあるページがいくつかあります。

誰かがナビゲートしたり、ブラウザのタブを閉じたりした場合、未保存のデータを残して本当にフォームを残してよいか確認するよう促すには、どうしたらよいでしょうか?

どのように解決するのですか?

短く、間違った答え。

によって行うことができます。 を処理します。 beforeunload イベントを発生させ、NULLでない文字列を返します。 :

window.addEventListener("beforeunload", function (e) {
    var confirmationMessage = 'It looks like you have been editing something. '
                            + 'If you leave before saving, your changes will be lost.';

    (e || window.event).returnValue = confirmationMessage; //Gecko + IE
    return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});

この方法の問題点は フォームを送信すると、unload イベントも発生します。 . これは、フォームを送信していることを示すフラグを追加することで簡単に修正できます。

var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';
        
        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

そして、送信時にセッターを呼び出します。

<form method="post" onsubmit="setFormSubmitting()">     
    <input type="submit" />
</form>

でも、読んでみてください...

長文、正解です。

また、次のようなメッセージも表示させないようにします。 ユーザーがフォーム上で何も変更していない場合 . 一つの解決策は beforeunload イベントを "dirty" フラグと組み合わせて使用すると、本当に関連性のある場合のみプロンプトが表示されるようになります。

var isDirty = function() { return false; }

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting || !isDirty()) {
            return undefined;
        }
        
        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};
    

さて、次に実装するのは isDirty メソッドには、さまざまなアプローチがあります。

を使用することができます。 jQueryとフォームのシリアライズ しかし、この方法にはいくつかの欠点があります。まず、どんなフォームでも動作するようにコードを変更する必要があります ( $("form").each() で済むのだが、最大の問題は、jQueryの serialize() は、名前がついていて無効になっていない要素にのみ作用するので、無効になっている要素や名前のついていない要素を変更しても、dirty フラグは発動しません。 そのための回避策があります 例えば、コントロールを有効にする代わりに、コントロールを読み取り専用にし、シリアライズしてから再び無効にすることができます。

だから、イベントがいいみたいです。試してみてください。 キー入力をリスニングする . このイベントには、いくつかの問題があります。

  • チェックボックス、ラジオボタンなど、マウス入力で変更される要素ではトリガーされません。
  • のような無関係なキー入力に対してもトリガーされます。 Ctrl キーを使用します。
  • JavaScriptのコードで設定した値ではトリガーしないようにしました。
  • コンテキストメニューからテキストをカットまたはペーストしてもトリガーされません。
  • JavaScriptでhidden inputに値を保存するdatepickersやcheckbox/radiobutton beautifiersのような仮想入力では動作しません。

change イベント また は、JavaScriptのコードから設定された値にはトリガーしません。 そのため、バーチャルインプットには使えません。

バインディング input イベントをすべての input の(そして textareaselect s) をあなたのページで は古いブラウザでは動作しません また、上記のすべてのイベント処理ソリューションと同様に、アンドゥをサポートしていません。ユーザーがテキストボックスを変更した後にそれを取り消したり、チェックボックスをチェックしたり外したりすると、フォームはまだ汚れているとみなされます。

また、特定の要素を無視するなど、より多くの動作を実装したい場合は、さらに多くの作業が必要になります。

車輪の再発明をしないでください。

そのため、これらのソリューションや必要な回避策を実行しようと考える前に、車輪の再発明をすることになり、他の人がすでに解決している問題にぶつかる可能性があることを認識しておいてください。

もしあなたのアプリケーションがすでにjQueryを使用しているなら、自分でローリングするのではなく、テストされメンテナンスされたコードを使用し、これら全てにサードパーティライブラリを使用した方がよいでしょう。

jquery.dirty (@troseman がコメントで提案してくれた) は、フォームが変更されたかどうかを適切に検出し、プロンプトを表示中にユーザーがページから離脱するのを防ぐ機能を提供します。また、フォームをリセットしたり、現在のフォームの状態を "clean" とするなどの便利な機能も備えています。使用例です。

$("#myForm").dirty({preventLeaving: true});

古いもので、現在放棄されているプロジェクトは、次のとおりです。 jQueryのAre You Sure?プラグイン も素晴らしい出来栄えです。 デモページ . 使用例です。

<script src="jquery.are-you-sure.js"></script>

<script>
  $(function() {
    $('#myForm').areYouSure(
      {
        message: 'It looks like you have been editing something. '
               + 'If you leave before saving, your changes will be lost.'
      }
    );
  });
  
</script>

カスタムメッセージはどこでもサポートされているわけではありません

以下の点に注意してください。 はすでに2011年以降、Firefox 4 は、このダイアログでのカスタムメッセージに対応していませんでした。2016年4月現在、Chrome 51がロールアウトされています。 カスタムメッセージも削除される .

このサイトの他の場所にも代替案がありますが、このようなダイアログで十分わかりやすいと思います。

このサイトを離れたいですか?

変更した内容が保存されない場合があります。

去る 滞在