Bagaimana cara menangkap acara tutup jendela browser?


149

Saya ingin menangkap acara tutup jendela / tab browser. Saya telah mencoba yang berikut ini dengan jQuery:

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

Tapi itu berfungsi pada pengajuan formulir juga, yang bukan itu yang saya inginkan. Saya ingin acara yang memicu hanya ketika pengguna menutup jendela.

Jawaban:


212

The beforeunloadevent kebakaran setiap kali pengguna meninggalkan halaman Anda untuk alasan apapun.

Misalnya, itu akan dipecat jika pengguna mengirimkan formulir, mengklik tautan, menutup jendela (atau tab), atau pergi ke halaman baru menggunakan bilah alamat, kotak pencarian, atau bookmark.

Anda bisa mengecualikan pengiriman formulir dan hyperlink (kecuali dari frame lain) dengan kode berikut:

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

Untuk versi jQuery yang lebih tua dari 1,7, coba ini:

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

The liveMetode tidak bekerja dengan submitacara, jadi jika Anda menambahkan bentuk baru, Anda akan perlu untuk mengikat pawang untuk itu juga.

Perhatikan bahwa jika pengendali acara yang berbeda membatalkan pengiriman atau navigasi, Anda akan kehilangan konfirmasi jika jendela benar-benar ditutup nanti. Anda dapat memperbaikinya dengan merekam waktu di submitdan clickacara, dan memeriksa jika itu beforeunloadterjadi lebih dari beberapa detik kemudian.


8
ya, bekerja dengan baik! Versi terbaru dari dukungan jquery $ ('form'). Live ('submit, function () {}).
Venkat D.

4
Solusi Anda baik tetapi bagaimana cara membatalkan acara jika terjadi penyegaran? Saya ingin acara hanya jika browser ditutup, tidak ada kasus refresh
Refael

Tampaknya browser menampilkan nilai kembali dari sebelumunload sebagai dialog konfirmasi. Jadi saya pikir jawaban ini lebih akurat: tautan
tahagh

2
tidak menangani ini refresh halaman menggunakan Ctrl + r, F5, Ctrl + Shift + rdan mengubah URL peramban?
Arti

1
@ Jonny: Sekarang saja .on().
SLaks

45

Mungkin cukup lepaskan ikatan beforeunloadpenangan acara di dalam penangan acara formulir submit:

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

3
Bukankah ini semudah tidak menggunakan jQuery dengan menetapkan ini dalam definisi tag form? : `<form onsubmit =" window.onbeforeunload = null; ">
awe

4
@awe Tapi Anda harus memasukkan itu onsubmit=...di setiap formulir. (Saya punya banyak formulir per halaman, di webapp tertentu)
KajMagnus

16

Untuk solusi lintas-browser (diuji di Chrome 21, IE9, FF15), pertimbangkan untuk menggunakan kode berikut, yang merupakan versi kode Slaks yang sedikit dimodifikasi:

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

Perhatikan bahwa sejak Firefox 4, pesan "Apakah Anda benar-benar ingin menutup?" tidak ditampilkan. FF hanya menampilkan pesan umum. Lihat catatan di https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload


3
Yang ini bekerja secara konsisten di seluruh browser. Hanya catatan singkat; Aku diperbaharui baik livedan bindpernyataan untuk on, yang bekerja besar dengan tingkat terbaru dari jQuery. Terima kasih!
Sablefoste


4

Untuk solusi yang bekerja dengan baik dengan kontrol pihak ketiga seperti Telerik (mis .: RadComboBox) dan DevExpress yang menggunakan tag Anchor karena berbagai alasan, pertimbangkan untuk menggunakan kode berikut, yang merupakan versi sedikit dimodifikasi dari kode desm dengan pemilih yang lebih baik untuk diri sendiri menargetkan tag jangkar:

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
Jawaban ini benar tetapi bagi mereka yang memiliki masalah dengan peristiwa ini terjadi ketika Anda menyegarkan peramban, ubah if ke kode berikut: if (inFormOrLink! == undefined &&! InFormOrLink)
LeonPierre

4

Jawaban saya ditujukan untuk memberikan tolok ukur sederhana.

BAGAIMANA CARA

Lihat jawaban @SLaks .

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

Berapa lama browser akhirnya menutup halaman Anda?

Setiap kali pengguna menutup halaman ( xtombol atau CTRL+ W), browser mengeksekusi beforeunloadkode yang diberikan , tetapi tidak tanpa batas waktu. Satu-satunya pengecualian adalah kotak konfirmasi ( return 'Do you really want to close?) yang akan menunggu hingga respons pengguna.

Chrome : 2 detik.
Firefox : ∞ (atau klik dua kali, atau paksa tutup)
Tepi : ∞ (atau klik dua kali)
Explorer 11 : 0 detik.
Safari : TODO

Apa yang kami gunakan untuk menguji ini:

  • Server Node.js Express dengan log permintaan
  • Berikut file HTML singkatnya

Apa yang dilakukannya adalah mengirim sebanyak mungkin permintaan sebelum browser mematikan halamannya (secara serempak).

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

Output 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

Saya menggunakan jawaban Slaks tetapi itu tidak berfungsi sebagaimana mestinya, karena returnValue onbeforeunload diuraikan sebagai string dan kemudian ditampilkan di kotak konfirmasi browser. Jadi nilai true ditampilkan, seperti "true".

Hanya menggunakan pengembalian bekerja. Ini kode saya

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

Mungkin Anda bisa menangani OnSubmit dan menetapkan bendera yang nanti Anda periksa di handler OnBeforeUnload Anda.


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

Sayangnya, apakah itu memuat ulang, pengalihan halaman baru, atau browser menutup acara akan dipicu. Alternatifnya adalah menangkap id yang memicu acara dan jika itu bentuk, jangan memicu fungsi apa pun dan jika itu bukan id dari formulir tersebut, lakukan apa yang ingin Anda lakukan ketika halaman ditutup. Saya tidak yakin apakah itu juga mungkin secara langsung dan membosankan.

Anda dapat melakukan beberapa hal kecil sebelum pelanggan menutup tab. javascript mendeteksi peramban tutup tab / peramban tutup tetapi jika daftar tindakan Anda besar dan tab ditutup sebelum selesai, Anda tidak berdaya. Anda dapat mencobanya tetapi dengan pengalaman saya, jangan bergantung padanya.

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

Jika pengiriman formulir Anda membawa mereka ke halaman lain (seperti yang saya asumsikan demikian, maka memicu beforeunload), Anda bisa mencoba mengubah pengiriman formulir Anda ke panggilan ajax. Dengan cara ini, mereka tidak akan meninggalkan halaman Anda ketika mereka mengirimkan formulir dan Anda dapat menggunakan beforeunloadkode mengikat Anda seperti yang Anda inginkan.


0

Masalah Saya: Acara 'onbeforeunload' hanya akan dipicu jika ada jumlah ganjil pengiriman (klik). Saya memiliki kombinasi solusi dari utas serupa di SO agar solusi saya berfungsi. baik kode saya akan berbicara.

<!--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

Pada jQuery 1.7, metode .live () sudah tidak digunakan lagi. Gunakan .on () untuk melampirkan penangan acara. Pengguna versi jQuery yang lebih lama harus menggunakan .delegate () untuk preferensi .live ()

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

pada lengkap atau tautan

$(window).unbind();

0

Coba ini juga

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

Cukup verifikasi ...

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

Itu tidak bekerja. Pada saat acara bongkar diaktifkan (btw, itu muncul dari dokumen), window.closed === false;
Sergey P. alias azure

-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

Mengikuti bekerja untuk saya;

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

itu adalah fungsi jquery.
Maks

7
Ini event.clientYnegatif jika Anda mengklik tombol tutup browser atau tombol tutup tab. Namun, nilai ini positif ketika Anda memuat ulang halaman menggunakan pintasan keyboard (F5, Ctrl-R) atau menutup browser menggunakan pintasan keyboard (mis. Alt-F4). Dengan demikian, Anda tidak dapat mengandalkan posisi acara untuk membedakan acara tutup browser dari acara memuat ulang halaman.
Julien Kronegg
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.