Wie erfasse ich das Ereignis zum Schließen des Browserfensters?

149

Ich möchte das Ereignis zum Schließen des Browserfensters / Tabs erfassen. Ich habe Folgendes mit jQuery versucht:

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

Aber es funktioniert auch beim Einreichen von Formularen, was ich nicht will. Ich möchte ein Ereignis, das nur ausgelöst wird, wenn der Benutzer das Fenster schließt.

khelll
quelle

Antworten:

211

Das beforeunloadEreignis wird ausgelöst, wenn der Benutzer Ihre Seite aus irgendeinem Grund verlässt.

Es wird beispielsweise ausgelöst, wenn der Benutzer ein Formular sendet, auf einen Link klickt, das Fenster (oder die Registerkarte) schließt oder über die Adressleiste, das Suchfeld oder ein Lesezeichen zu einer neuen Seite wechselt.

Sie können Formularübermittlungen und Hyperlinks (außer von anderen Frames) mit dem folgenden Code ausschließen:

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

Versuchen Sie Folgendes für jQuery-Versionen, die älter als 1.7 sind:

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

Die liveMethode funktioniert nicht mit dem submitEreignis. Wenn Sie also ein neues Formular hinzufügen, müssen Sie den Handler ebenfalls daran binden.

Beachten Sie, dass Sie die Bestätigungsaufforderung verlieren, wenn ein anderer Ereignishandler die Übermittlung oder Navigation abbricht, wenn das Fenster später tatsächlich geschlossen wird. Sie können dies beheben, indem Sie die Zeit in den submitund clickEreignissen aufzeichnen und überprüfen, ob beforeunloaddies mehr als ein paar Sekunden später geschieht.

SLaks
quelle
8
yup, funktioniert super! Die neueren Versionen von jquery unterstützen $ ('form'). Live ('submit, function () {}).
Venkat D.
4
Ihre Lösung ist gut, aber wie kann ich das Ereignis im Falle einer Aktualisierung abbrechen? Ich möchte das Ereignis nur, wenn der Browser geschlossen ist, kein Fall von Aktualisierung
Refael
Es scheint, dass der Browser den Rückgabewert von beforeunload als Bestätigungsdialog anzeigt. Ich denke, diese Antwort ist genauer: link
tahagh
2
tut dies Griff Aktualisierung einer Seite mit Ctrl + r, F5, Ctrl + Shift + rund die Browser - URL zu ändern?
Arti
1
@ Jonny: Es ist jetzt nur .on().
SLaks
45

Binden Sie den beforeunloadEreignishandler möglicherweise einfach im Ereignishandler des Formulars auf submit:

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});
karim79
quelle
3
Ist es nicht genauso einfach, jQuery nicht zu verwenden, indem Sie dies in der Formular-Tag-Definition angeben? : `<form onsubmit =" window.onbeforeunload = null; ">
Ehrfurcht
4
@awe Aber das müsstest du onsubmit=...in jedes Formular aufnehmen. (Ich habe viele Formulare pro Seite in einer bestimmten Webanwendung)
KajMagnus
16

Verwenden Sie für eine browserübergreifende Lösung (getestet in Chrome 21, IE9, FF15) den folgenden Code, bei dem es sich um eine leicht optimierte Version des Slaks-Codes handelt:

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

Beachten Sie, dass seit Firefox 4 die Meldung "Möchten Sie wirklich schließen?" wird nicht angezeigt. FF zeigt nur eine generische Nachricht an. Siehe Hinweis unter https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload

desm
quelle
3
Dieser funktioniert konsistent über alle Browser hinweg. Nur eine schnelle Anmerkung; Ich habe sowohl die liveals auch die bindAnweisungen aktualisiert on, was mit der neuesten Version von jQuery hervorragend funktioniert. Vielen Dank!
Sablefoste
16
window.onbeforeunload = function () {
    return "Do you really want to close?";
};
Behnam Mohammadi
quelle
4

Für eine Lösung, die mit Steuerelementen von Drittanbietern wie Telerik (z. B. RadComboBox) und DevExpress, die die Anchor-Tags aus verschiedenen Gründen verwenden, gut funktioniert, sollten Sie den folgenden Code verwenden, bei dem es sich um eine leicht optimierte Version des Desm-Codes mit einer besseren Auswahl für sich selbst handelt Targeting von Ankertags:

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;
});
PLT
quelle
1
Diese Antwort ist richtig, aber für diejenigen, die Probleme mit diesem Ereignis hatten, wenn Sie den Browser aktualisieren, ändern Sie Ihr if in den folgenden Code: if (inFormOrLink! == undefined &&! InFormOrLink)
LeonPierre
4

Meine Antwort zielt darauf ab, einfache Benchmarks bereitzustellen.

WIE MAN

Siehe @ Slaks Antwort .

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

Wie lange dauert es, bis der Browser Ihre Seite endgültig herunterfährt?

Immer wenn ein Benutzer die Seite schließt ( xSchaltfläche oder CTRL+ W), führt der Browser den angegebenen beforeunloadCode aus, jedoch nicht auf unbestimmte Zeit. Die einzige Ausnahme ist das Bestätigungsfeld ( return 'Do you really want to close?), das auf die Antwort des Benutzers wartet.

Chrome : 2 Sekunden.
Firefox : ∞ (oder Doppelklick oder Erzwingen beim Schließen)
Kante : ∞ (oder Doppelklick)
Explorer 11 : 0 Sekunden.
Safari : TODO

Was wir verwendet haben, um dies zu testen:

  • Ein Node.js Express-Server mit Anforderungsprotokoll
  • Die folgende kurze HTML-Datei

Es sendet so viele Anfragen wie möglich, bevor der Browser seine Seite herunterfährt (synchron).

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

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.
zurfyx
quelle
3

Ich habe die Antwort von Slaks verwendet, aber das hat nicht so funktioniert, da der Rückgabewert onbeforeunload als Zeichenfolge analysiert und dann im Bestätigungsfeld des Browsers angezeigt wird. Daher wurde der Wert true wie "true" angezeigt.

Nur mit Return hat funktioniert. Hier ist mein Code

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;
})
Kapad
quelle
1

Vielleicht könnten Sie OnSubmit verarbeiten und ein Flag setzen, das Sie später in Ihrem OnBeforeUnload-Handler einchecken.

i_am_jorf
quelle
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?";
                          }
                      })
Codierender Mann
quelle
1

Leider wird das Ereignis ausgelöst, unabhängig davon, ob es sich um ein erneutes Laden, eine Umleitung neuer Seiten oder ein Schließen des Browsers handelt. Eine Alternative besteht darin, die ID abzufangen, die das Ereignis auslöst. Wenn es sich um ein Formular handelt, wird keine Funktion ausgelöst. Wenn es sich nicht um die ID des Formulars handelt, tun Sie, was Sie tun möchten, wenn die Seite geschlossen wird. Ich bin mir nicht sicher, ob das auch direkt möglich und langweilig ist.

Sie können einige kleine Dinge tun, bevor der Kunde die Registerkarte schließt. Javascript erkennt Browser schließen Tab / Browser schließen, aber wenn Ihre Liste von Aktionen groß ist und der Tab geschlossen wird, bevor es beendet ist, sind Sie hilflos. Sie können es versuchen, aber meiner Erfahrung nach hängen Sie nicht davon ab.

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=de-US&redirectslug=DOM/Mozilla_event_reference/beforeunload

Gary
quelle
0

Wenn Ihre Formularübermittlung sie auf eine andere Seite weiterleitet (wie ich annehme, daher das Auslösen von beforeunload), können Sie versuchen, Ihre Formularübermittlung in einen Ajax-Aufruf zu ändern. Auf diese Weise verlassen sie Ihre Seite nicht, wenn sie das Formular senden, und Sie können Ihren beforeunloadBindungscode nach Ihren Wünschen verwenden.

idrumgood
quelle
0

Mein Problem: Das Ereignis "onbeforeunload" wird nur ausgelöst, wenn eine ungerade Anzahl von Übermittlungen (Klicks) vorliegt. Ich hatte eine Kombination von Lösungen aus ähnlichen Threads in SO, damit meine Lösung funktioniert. Nun, mein Code wird sprechen.

<!--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');   
}
Yoosaf Abdulla
quelle
0

Ab jQuery 1.7 ist die .live () -Methode veraltet. Verwenden Sie .on (), um Ereignishandler anzuhängen. Benutzer älterer Versionen von jQuery sollten .delegate () anstelle von .live () verwenden.

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

auf vollständig oder Link

$(window).unbind();
Tom
quelle
0

Versuchen Sie dies auch

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
    }
};
Bhaskara Arani
quelle
-1

Überprüfen Sie einfach ...

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");
    }
  }
}
Brunno
quelle
Es funktioniert nicht. In dem Moment, in dem das Entladeereignis ausgelöst wird (übrigens wird es aus dem Dokument ausgelöst), wird das Fenster geschlossen === false;
Sergey P. aka 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`
Arslan Khan
quelle
-7

Das Folgende hat für mich funktioniert;

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });
Dilhan Jayathilaka
quelle
Es ist eine Abfragefunktion.
Maxisam
7
Das event.clientYist negativ, wenn Sie auf die Schaltfläche zum Schließen des Browsers oder zum Schließen der Registerkarte klicken. Dieser Wert ist jedoch positiv, wenn Sie die Seite mithilfe von Tastaturkürzeln (F5, Strg-R) neu laden oder den Browser mithilfe von Tastaturkürzeln (z. B. Alt-F4) schließen. Daher können Sie sich nicht auf die Ereignisposition verlassen, um das Ereignis zum Schließen des Browsers vom Ereignis zum erneuten Laden der Seite zu unterscheiden.
Julien Kronegg