ブラウザウィンドウのクローズイベントをキャプチャする方法は?


149

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

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

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

回答:


212

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イベントでは機能しないため、新しいフォームを追加する場合は、ハンドラーもフォームにバインドする必要があります。

別のイベントハンドラーが送信またはナビゲーションをキャンセルした場合、後でウィンドウが実際に閉じられると、確認プロンプトが失われることに注意してください。submitclickイベントの時間を記録しbeforeunload、数秒後にそれが発生するかどうかを確認することで、これを修正できます。


8
うん、すごい!jqueryの新しいバージョンは$( 'form')。live( 'submit、function(){})をサポートしています。
Venkat D.2011

4
あなたの解決策は良いですが、更新の場合にイベントをキャンセルするにはどうすればよいですか?ブラウザが閉じている場合にのみイベントが必要です。更新のケースはありません
Refael

ブラウザはbeforeunloadの戻り値を確認ダイアログとして表示しているようです。だから私はこの答えがより正確だと思います:リンク
tahagh

2
ページのこのハンドルのリフレッシュが使用しCtrl + rF5Ctrl + Shift + rおよびブラウザのURLを変更しますか?
Arti

1
@ジョニー:それは今だけ.on()です。
SLaks

45

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

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

3
これは、フォームタグ定義でjQueryを指定してjQueryを使用しないのと同じくらい簡単ではありませんか?: `<フォームをonSubmit = "window.onbeforeunload = NULL;">
AWE

4
@aweしかし、それonsubmit=...を各フォームに含める必要があります。(私は特定のwebappでページごとに多くのフォームを持っています)
KajMagnus

16

クロスブラウザーソリューション(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のメモを参照してください


3
これはブラウザ間で一貫して機能します。簡単なメモです。私は両方の更新livebindの声明をonjQueryの最新レベルで素晴らしい作品これは、。ありがとう!
Sablefoste 2013年


4

さまざまな理由でアンカータグを使用する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;
});

1
この回答は正しいですが、ブラウザを更新するときにこのイベントが発生する問題が発生した場合は、ifを次のコードに変更してください:if(inFormOrLink!== undefined &&!inFormOrLink)
LeonPierre

4

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

方法

@SLaksの回答を参照してください。

$(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:∞(またはダブルクリック、または強制終了)
Edge:∞(またはダブルクリック)
Explorer 11:0秒。
サファリTODO

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

  • リクエストログを含む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.

3

Slaksの回答を使用しましたが、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;
})

1

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


1
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

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

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

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


0

フォーム送信がそれらを別のページに移動する場合(私はそうするため、のトリガーとなるbeforeunload)、フォーム送信をajax呼び出しに変更しようとすることができます。この方法では、フォームを送信するときにページから離れることはなく、beforeunloadバインディングコードを自由に使用できます。


0

私の問題:「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

jQuery 1.7以降、.live()メソッドは非推奨になりました。.on()を使用して、イベントハンドラーをアタッチします。古いバージョンのjQueryのユーザーは、.live()よりも.delegate()を使用する必要があります。

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

完了時またはリンク時

$(window).unbind();

0

これも試してみてください

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
    }
};

-1

確認してください...

function wopen_close(){
  var w = window.open($url, '_blank', 'width=600, height=400, scrollbars=no, status=no, resizable=no, screenx=0, screeny=0');
  w.onunload = function(){
    if (window.closed) {
       alert("window closed");
    }else{ 
       alert("just refreshed");
    }
  }
}

動作しません。アンロードイベントが発生した瞬間に(ドキュメントから発生します)、window.closed === false;
Sergey P. aka azure 2016年

-1
var validNavigation = false;
            jQuery(document).ready(function () {

                wireUpEvents();
            });

            function endSession() {
                // Browser or broswer tab is closed
                // Do sth here ...
                alert("bye");
            }

            function wireUpEvents() {
                /*
                * For a list of events that triggers onbeforeunload on IE
                * check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
                */
                window.onbeforeunload = function () {
                    debugger
                    if (!validNavigation) {
                        endSession();
                    }
                }

                // Attach the event keypress to exclude the F5 refresh
                $(document).bind('keypress', function (e) {
                    debugger
                    if (e.keyCode == 116) {
                        validNavigation = true;
                    }
                });

                // Attach the event click for all links in the page
                $("a").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event submit for all forms in the page
                $("form").bind("submit", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event click for all inputs in the page
                $("input[type=submit]").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

            }`enter code here`

-7

以下は私のために働いた。

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });

これはjquery関数です。
maxisam 2012年

7
event.clientYあなたは、ブラウザのクローズボタンやタブを閉じる]ボタンをクリックすると、負です。ただし、キーボードショートカット(F5、Ctrl-R)を使用してページをリロードしたり、キーボードのショートカーソル(Alt-F4など)を使用してブラウザを閉じたりすると、この値は正になります。したがって、ページのリロードイベントとブラウザの閉じるイベントを区別するために、イベントの位置に依存することはできません。
Julien Kronegg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.