web-dev-qa-db-ja.com

window.onbeforeunload-フォームを送信しない場合にのみ警告を表示

Window.onbeforeunloadを使用して、フォーム上の値を変更した後にユーザーが移動できないようにします。これは正常に機能していますが、ユーザーがフォームを送信したときに警告が表示されることを除きます(望ましくありません)。

フォームの送信時に警告を表示せずにこれを行うにはどうすればよいですか?

現在のコード:

var formHasChanged = false;

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) {
    formHasChanged = true;
});

$(document).ready(function () {
    window.onbeforeunload = function (e) {
        if (formHasChanged) {
            var message = "You have not saved your changes.", e = e || window.event;
            if (e) {
                e.returnValue = message;
            }
            return message;
        }
    }
});
31
mtmurdock

フォームの送信イベントを使用してフラグを設定するとうまくいく場合があります。

 var formHasChanged = false;
 var submitted = false;

$(document).on('change', 'form.confirm-navigation-form input, form.confirm-navigation-form select, form.confirm-navigation-form textarea', function (e) {
    formHasChanged = true;
});

$(document).ready(function () {
    window.onbeforeunload = function (e) {
        if (formHasChanged && !submitted) {
            var message = "You have not saved your changes.", e = e || window.event;
            if (e) {
                e.returnValue = message;
            }
            return message;
        }
    }
 $("form").submit(function() {
     submitted = true;
     });
});
34
Jay Tomten

.on()を使用してonbeforeunloadをバインドし、次に.off()を使用してフォーム送信でアンバインドできます。

$(document).ready(function () {
    // Warning
    $(window).on('beforeunload', function(){
        return "Any changes will be lost";
    });

    // Form Submit
    $(document).on("submit", "form", function(event){
        // disable warning
        $(window).off('beforeunload');
    });
}
15
Brent White

submit() イベントを処理できます。これはフォームの送信時にのみ発生します。

そのイベント内で、フラグ変数formHasChangedをfalseに設定して、アンロードを続行できるようにします。また、単なる提案ですが、そのフラグ変数の目的が変更されるため、「warnBeforeUnload」のような名前に変更することができます

$(document).submit(function(){
    warnBeforeUnload = false;
});
10
Derek Hunziker

これに対するより良い解決策を探していました。必要なのは、1つまたは複数のトリガーを「本当によろしいですか」の作成から除外することです。ダイアログボックス。そのため、ますます多くの副作用に対する回避策を作成するべきではありません。送信ボタンのclickイベントなしでフォームが送信された場合はどうなりますか?クリックハンドラーがisDirtyステータスを削除しても、その後フォーム送信がブロックされるとどうなりますか?トリガーの動作を変更できますが、適切な場所はダイアログを処理するロジックです。送信ボタンのsubmitイベントにバインドするのではなく、フォームのclickイベントにバインドすることは、このスレッドの答えが以前見た他のいくつかのものより優れている点ですが、このIMHOは間違ったアプローチを修正します。

onbeforeunloadイベントのイベントオブジェクトを掘り下げた後、.target.activeElementプロパティ。元のイベントをトリガーした要素を保持します。だから、いや、それはボタンやリンク、または私たちがクリックしたもの(またはブラウザ自体が離れて移動した場合は何もありません)です。 「よろしいですか?」ダイアログロジックは、次の2つのコンポーネントに縮小します。

  1. フォームのisDirty処理:

    $('form.pleaseSave').on('change', function() {
      $(this).addClass('isDirty');
    });
    
  2. 「よろしいですか?」ダイアログロジック:

    $(window).on('beforeunload', function(event) {
      // if form is dirty and trigger doesn't have a ignorePleaseSave class
      if ($('form.pleaseSave').hasClass('isDirty')
          && !$(event.target.activeElement).hasClass('ignorePleaseSave')) {
        return "Are you sure?"
      }
      // special hint: returning nothing doesn't summon a dialog box
    });
    

それは単純です。回避策は必要ありません。トリガー(送信および他のアクションボタン)にignorePleaseSaveクラスと、ダイアログをpleaseSaveクラスに適用したいフォームを与えるだけです。ページをアンロードする他のすべての理由は、「よろしいですか?」を呼び出します。ダイアログ。

追伸ここではjQueryを使用していますが、.target.activeElementプロパティは、プレーンJavaScriptでも使用できます。

2
spackmat