web-dev-qa-db-ja.com

ブラウザウィンドウを閉じるイベントをキャプチャする方法

ブラウザウィンドウ/タブクローズイベントをキャプチャしたいです。私はjQueryで次のことを試しました:

jQuery(window).bind(
    "beforeunload", 
    function() { 
        return confirm("Do you really want to close?") 
    }
)

しかし、それはフォームの送信にも作用します。これは私が望んでいることではありません。ユーザーがウィンドウを閉じたときにだけトリガーされるイベントが欲しいのですが。

139
khelll

beforeunloadイベントは、何らかの理由でユーザーがページを離れたときに発生します。

たとえば、ユーザーがフォームを送信したり、リンクをクリックしたり、ウィンドウ(またはタブ)を閉じたり、アドレスバー、検索ボックス、またはブックマークを使用して新しいページに移動したりすると発生します。

次のコードを使用して、フォームの送信とハイパーリンクを(他のフレームからのものを除く)除外することができます。

var inFormOrLink;
$('a').on('click', function() { inFormOrLink = true; });
$('form').on('submit', function() { inFormOrLink = true; });

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

1.7より古いjQueryバージョンの場合は、これを試してください。

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

liveメソッドはsubmitイベントでは機能しないため、新しいフォームを追加する場合は、それにハンドラをバインドする必要があります。

別のイベントハンドラが送信またはナビゲーションをキャンセルした場合、後でウィンドウが実際に閉じられると、確認のプロンプトが表示されなくなります。 submitイベントとclickイベントに時間を記録し、beforeunloadが数秒以上後に発生するかどうかを確認することでこれを修正できます。

195
SLaks

フォームのbeforeunloadイベントハンドラ内でsubmitイベントハンドラをアンバインドするだけです。

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});
44
karim79

クロスブラウザソリューション(Chrome 21、IE9、FF15でテスト済み)の場合は、次のコードを使用することを検討してください。これは、Slaksのコードを少し調整したものです。

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

Firefox 4以降、「本当に閉じますか?」というメッセージが表示されます。表示されません。 FFは一般的なメッセージを表示するだけです。 https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload の注を参照してください。

15
desm
window.onbeforeunload = function () {
    return "Do you really want to close?";
};
10

さまざまな理由でAnchorタグを使用するTelerik(例:RadComboBox)やDevExpressのようなサードパーティ製のコントロールでうまく機能する解決策については、以下のコードを使用することを検討してください。アンカータグのターゲティング:

var inFormOrLink;
$('a[href]:not([target]), a[href][target=_self]').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
});
4
PLT

私の答えは簡単なベンチマークを提供することを目的としています。

の仕方

@ SLaks answer を参照してください。

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

ブラウザが最終的にページを閉じるまでにどのくらいかかりますか。

ユーザーがページを閉じるたびに(x ボタンまたは CTRL + W)、ブラウザは与えられたbeforeunloadコードを実行しますが、無期限ではありません。唯一の例外は確認ボックス(return 'Do you really want to close?)です。これはユーザーの応答を待つまで待機します。

Chrome:2秒.
Firefox:∞(またはダブルクリック、または強制終了)
エッジ:∞(またはダブルクリック)
Explorer 11:0秒。
SafariTODO

これをテストするために使用したもの

  • 要求ログを持つNode.js Expressサーバー
  • 次の短いHTMLファイル

ブラウザがそのページをシャットダウンする前に(同期的に)できるだけ多くのリクエストを送信することです。

<html>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
    function request() {
        return $.ajax({
            type: "GET",
            url: "http://localhost:3030/" + Date.now(),
            async: true
        }).responseText;
    }
    window.onbeforeunload = () => {
        while (true) {
            request();
        }
        return null;
    }
    </script>
</body>
</html>

Chromeの出力:

GET /1480451321041 404 0.389 ms - 32  
GET /1480451321052 404 0.219 ms - 32  
...  
GET /hello/1480451322998 404 0.328 ms - 32

1957ms ≈ 2 seconds // we assume it's 2 seconds since requests can take few milliseconds to be sent.
4
zurfyx

Slaks answerを使用しましたが、onbeforeunloadのreturnValueが文字列として解析されてブラウザの確認ボックスに表示されるため、これはそのままでは機能しませんでした。そのため、 "true"のように、trueという値が表示されました。

リターンを使うだけでうまくいきました。これが私のコードです

var preventUnloadPrompt;
var messageBeforeUnload = "my message here - Are you sure you want to leave this page?";
//var redirectAfterPrompt = "http://www.google.co.in";
$('a').live('click', function() { preventUnloadPrompt = true; });
$('form').live('submit', function() { preventUnloadPrompt = true; });
$(window).bind("beforeunload", function(e) { 
    var rval;
    if(preventUnloadPrompt) {
        return;
    } else {
        //location.replace(redirectAfterPrompt);
        return messageBeforeUnload;
    }
    return rval;
})
3
kapad

残念ながら、それがリロードか、新しいページのリダイレクトか、ブラウザのクローズかに関わらず、イベントがトリガーされます。別の方法としては、イベントをトリガーするIDをキャッチし、それがフォームであれば関数をトリガーしないで、それがフォームのIDでなければ、ページを閉じるときにしたいことを実行します。それが直接可能かどうかもわかりませんし、面倒です。

顧客がタブを閉じる前に、いくつか小さなことをすることができます。 javascriptがブラウザのタブを閉じる/ブラウザを閉じる しかし、アクションのリストが大きく、タブが終了する前に閉じると無力です。あなたはそれを試すことができますが、私の経験でdonotはそれに依存しません。

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  /* Do you small action code here */
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/beforeunload?redirectlocale=en-US&redirectslug=DOM/Mozilla_event_reference/beforeunload

1
Gary
jQuery(window).bind(
                    "beforeunload",
                      function (e) {
                          var activeElementTagName = e.target.activeElement.tagName;
                          if (activeElementTagName != "A" && activeElementTagName != "INPUT") {
                              return "Do you really want to close?";
                          }
                      })
1
Coding man

おそらく、OnSubmitを処理して、後でOnBeforeUnloadハンドラにチェックインするフラグを設定できます。

1
i_am_jorf

あなたのフォーム送信がそれらを別のページに持っていくのであれば(それがbeforeunloadの引き金となるように)、あなたはあなたのフォーム送信をajax呼び出しに変更しようと試みることができます。こうすれば、フォームを送信したときにページから離れずに、必要に応じてbeforeunloadバインディングコードを使用できます。

0
idrumgood

私の問題: 'onbeforeunload'イベントは、送信数(クリック数)が奇数の場合にのみ発生します。私は自分の解決策を働かせるためにSOの中の同じようなスレッドからの解決策の組み合わせを持っていました。よく私のコードは話すでしょう。

<!--The definition of event and initializing the trigger flag--->


$(document).ready(function() {
updatefgallowPrompt(true);
window.onbeforeunload = WarnUser;   
}

function WarnUser() {
var allowPrompt = getfgallowPrompt();
    if(allowPrompt) {
    saveIndexedDataAlert();
    return null;
    } else {
        updatefgallowPrompt(true);
        event.stopPropagation
    }
}

<!--The method responsible for deciding weather the unload event is triggered from submit or not--->
function saveIndexedDataAlert() {
    var allowPrompt = getfgallowPrompt();
    var lenIndexedDocs = parseInt($('#sortable3 > li').size()) + parseInt($('#sortable3 > ul').size());

    if(allowPrompt && $.trim(lenIndexedDocs) > 0) {
        event.returnValue = "Your message";
    } else {
        event.returnValue = "   ";
        updatefgallowPrompt(true);
    }
}

<!---Function responsible to reset the trigger flag---->
$(document).click(function(event) {  
$('a').live('click', function() { updatefgallowPrompt(false); });
 });

<!--getter and setter for the flag---->
function updatefgallowPrompt (allowPrompt){ //exit msg dfds
    $('body').data('allowPrompt', allowPrompt); 
}   

function getfgallowPrompt(){        
    return $('body').data('allowPrompt');   
}
0
Yoosaf Abdulla

これも試してください

window.onbeforeunload = function ()
{       
    if (pasteEditorChange) {
        var btn = confirm('Do You Want to Save the Changess?');
           if(btn === true ){
               SavetoEdit();//your function call
           }
           else{
                windowClose();//your function call
           }
    }  else { 
        windowClose();//your function call
    }
};
0
Bhaskara Arani

JQuery 1.7以降、.live()メソッドは推奨されなくなりました。イベントハンドラを添付するには.on()を使用します。古いバージョンのjQueryのユーザーは、.live()よりも.delegate()を使用してください。

$(window).bind("beforeunload", function() {
    return true || confirm("Do you really want to close?"); 
}); 

完了時またはリンク時

$(window).unbind();
0
Tom