Tarayıcı penceresi kapatma olayını nasıl yakalayabilirim?


152

Tarayıcı penceresi / sekme kapatma olayını yakalamak istiyorum. Aşağıdakileri jQuery ile denedim:

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

Ama form gönderme üzerinde de çalışıyor, ki istediğim bu değil. Yalnızca kullanıcı pencereyi kapattığında tetiklenen bir olay istiyorum.

Yanıtlar:


215

beforeunloadKullanıcı herhangi bir nedenle sayfanızı bıraktığı zaman olay ateşler.

Örneğin, kullanıcı bir form gönderirse, bir bağlantıya tıklarsa, pencereyi (veya sekmeyi) kapatırsa veya adres çubuğunu, arama kutusunu veya bir yer imini kullanarak yeni bir sayfaya giderse tetiklenecektir.

Aşağıdaki kodla form gönderimlerini ve köprüleri (diğer çerçeveler dışında) hariç tutabilirsiniz:

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'den daha eski jQuery sürümleri için şunu deneyin:

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

liveYöntem ile değil çalışır submitEğer yeni bir form eklemek eğer öyleyse, siz de ona işleyicisi bağlamak gerekir, olay.

Farklı bir olay işleyicisi göndermeyi veya navigasyonu iptal ederse, pencere daha sonra gerçekten kapatılırsa onay istemini kaybedeceğinizi unutmayın. Zamanı submitve clickolaylarına kaydederek ve beforeunloadbirkaç saniyeden daha uzun bir süre sonra olup olmadığını kontrol ederek bunu düzeltebilirsiniz .


8
evet, harika çalışıyor! Daha yeni jquery sürümleri $ ['form']. Live ('submit, function () {}) destekler.
Venkat D.

5
Çözümünüz iyi ama yenileme durumunda olayı nasıl iptal edebilirim? Etkinliği yalnızca tarayıcı kapalıysa istiyorum, yenileme
Refael

Görünüşe göre tarayıcı, bir onaylama iletişim kutusu olarak önyükleme öncesi dönüş değerini görüntülüyor. Bu yüzden bu cevabın daha doğru olduğunu düşünüyorum: link
tahagh

2
Bir sayfanın bu sap yenileme kullanarak yapar Ctrl + r, F5, Ctrl + Shift + rve tarayıcı URL'sini değiştirme?
Arti

1
@Jonny: Şimdi sadece .on().
SLaks

45

Belki sadece beforeunloadformun submitolay işleyicisindeki olay işleyicisinin bağlantısını kaldırın:

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

3
Bunu form etiketi tanımında belirterek jQuery'yi kullanmamak bu kadar kolay değil mi? : '<Form onsubmit = "window.onbeforeunload = null;">
korku

4
@awe Ancak bunu onsubmit=...her forma eklemeniz gerekir . (Belirli bir web uygulamasında sayfa başına birçok
formum var

16

Tarayıcılar arası bir çözüm için (Chrome 21, IE9, FF15'te test edilmiştir), Slaks kodunun biraz değiştirilmiş bir versiyonu olan aşağıdaki kodu kullanmayı düşünün:

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'ten beri "Gerçekten kapatmak istiyor musunuz?" görüntülenmez. FF yalnızca genel bir mesaj görüntüler. Https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload adresindeki nota bakın


3
Bu, tarayıcılar arasında tutarlı bir şekilde çalışır. Sadece hızlı bir not; Ben hem güncellenen liveve bindaçıklamalarda onJQuery'nin son seviyesi ile harika çalışıyor, hangi. Teşekkürler!
Sablefoste


4

Çeşitli nedenlerle Anchor etiketlerini kullanan Telerik (ör .: RadComboBox) ve DevExpress gibi üçüncü taraf denetimlerle iyi çalışan bir çözüm için, desm kodunun kendi kendine daha iyi bir seçiciye sahip biraz ince ayarlı bir sürümü olan aşağıdaki kodu kullanmayı düşünün. bağlantı etiketlerini hedefleme:

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
Bu cevap doğrudur, ancak tarayıcıyı yenilediğinizde bu olayla ilgili sorunlar yaşayanlar için aşağıdaki kodu değiştirin: if (inFormOrLink! == undefined &&! İnFormOrLink)
LeonPierre

4

Cevabım basit ölçütler sağlamayı amaçlıyor.

NASIL

@SLaks cevabına bakın .

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

Tarayıcının nihayet sayfanızı kapatması ne kadar sürer?

Bir kullanıcı sayfayı her kapattığında ( xdüğme veya CTRL+ W), tarayıcı verilen beforeunloadkodu çalıştırır , ancak süresiz olarak çalıştırmaz. Bunun tek istisnası, return 'Do you really want to close?kullanıcının yanıtını bekleyecek olan onay kutusudur ( ).

Chrome : 2 saniye.
Firefox : ∞ (veya çift tıklayın veya kapatmaya zorlayın)
Kenar : ∞ (veya çift tıklayın)
Explorer 11 : 0 saniye.
Safari : YAPILACAK

Bunu test etmek için kullandığımız şey:

  • İstek günlüğüne sahip bir Node.js Express sunucusu
  • Aşağıdaki kısa HTML dosyası

Yaptığı şey, tarayıcı sayfasını kapatmadan önce (eşzamanlı olarak) olabildiğince çok istek göndermektir.

<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 çıkışı:

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 cevabını kullandım, ancak onbeforeunload returnValue bir dizge olarak ayrıştırılıp ardından tarayıcının onaylar kutusunda görüntülendiğinden olduğu gibi çalışmıyordu. Böylece "true" gibi true değeri görüntülendi.

Sadece dönüşü kullanmak işe yaradı. İşte kodum

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

Belki OnSubmit'i işleyebilir ve daha sonra OnBeforeUnload işleyicinize kontrol edeceğiniz bir bayrak ayarlayabilirsiniz.


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

Maalesef, ister yeniden yükleme, ister yeni sayfa yönlendirme veya tarayıcı kapatma olayı tetiklenecektir. Bir alternatif, olayı tetikleyen kimliği yakalamaktır ve eğer biçim ise herhangi bir işlevi tetiklemeyin ve formun kimliği değilse, sayfa kapandığında yapmak istediğinizi yapın. Bunun doğrudan mümkün olup olmadığından ve sıkıcı olup olmadığından emin değilim.

Müşteri sekmeyi kapatmadan önce bazı küçük şeyler yapabilirsiniz. javascript, tarayıcı sekmeyi kapat / tarayıcıyı kapatır, ancak eylemler listeniz büyükse ve sekme tamamlanmadan kapanırsa, çaresizsiniz demektir. Deneyebilirsiniz ama benim deneyimlerime bağlı kalmayın.

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

Form gönderiminiz onları başka bir sayfaya götürürse (varsaydığım gibi, dolayısıyla tetikleniyor beforeunload), form gönderiminizi bir ajax çağrısı olarak değiştirmeyi deneyebilirsiniz. Bu şekilde formu gönderdiklerinde sayfanızdan ayrılmazlar ve beforeunloadbağlayıcı kodunuzu dilediğiniz gibi kullanabilirsiniz.


0

Sorunum: 'onbeforeunload' olayı yalnızca tek sayıda gönderim (tıklama) varsa tetiklenecekti. Çözümümün işe yaraması için SO'daki benzer iş parçacıklarıyla bir çözüm kombinasyonu aldım. benim kodum konuşacak.

<!--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'den itibaren, .live () yöntemi kullanımdan kaldırılmıştır. Olay işleyicileri eklemek için .on () kullanın. JQuery'nin eski sürümlerinin kullanıcıları .live () yerine .delegate () kullanmalıdır.

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

tamamlandığında veya bağlandığında

$(window).unbind();

0

Bunu da dene

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

Doğrula ...

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

Çalışmıyor. Unload olayı tetiklendiği anda (btw, belgeden tetiklenir), window.closed === false;
Sergey P. aka azure

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

Aşağıdakiler benim için çalıştı;

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

bir jquery işlevidir.
maxisam

8
event.clientYEğer tarayıcı kapat düğmesi veya sekme kapatma düğmesi tıklarsanız negatiftir. Ancak, klavye kısayollarını (F5, Ctrl-R) kullanarak sayfayı yeniden yüklediğinizde veya klavye kısayollarını (örneğin Alt-F4) kullanarak tarayıcıyı kapattığınızda bu değer pozitiftir. Bu nedenle, tarayıcı kapatma olayını sayfa yeniden yükleme olayından ayırmak için olay konumuna güvenemezsiniz.
Julien Kronegg
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.