How to capture the browser window close event?
Asked Answered
E

17

171

I want to capture the browser window/tab close event. I have tried the following with jQuery:

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

But it works on form submission as well, which is not what I want. I want an event that triggers only when the user closes the window.

Excellency answered 27/10, 2009 at 16:15 Comment(1)
If you want to be extremely precise, please check this solution: #76140470Bellows
E
231

The beforeunload event fires whenever the user leaves your page for any reason.

For example, it will be fired if the user submits a form, clicks a link, closes the window (or tab), or goes to a new page using the address bar, search box, or a bookmark.

You could exclude form submissions and hyperlinks (except from other frames) with the following code:

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

For jQuery versions older than 1.7, try this:

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 live method doesn't work with the submit event, so if you add a new form, you'll need to bind the handler to it as well.

Note that if a different event handler cancels the submit or navigation, you will lose the confirmation prompt if the window is actually closed later. You could fix that by recording the time in the submit and click events, and checking if the beforeunload happens more than a couple of seconds later.

Excrescency answered 27/10, 2009 at 16:22 Comment(13)
yup, working great! The newer versions of jquery support $('form').live('submit, function() { }).Mel
Your solution is good but how do I cancel the event in case of refresh ? I want the event only if the browser is closed, no case of refreshCopycat
It seems that the browser displays the return value of beforeunload as a confirm dialog. So I think this answer is more accurate: linkTranslatable
@Excrescency code is fine. I want to run logout() function if user clicks on "Leave this Page" pop button. But how can I detect whether user have clicked on "Leave this Page" or not?Marble
does this handle refresh of a page using Ctrl + r, F5, Ctrl + Shift + r and changing the browser URL?Region
The browser does still show a confirm box with message null?Christogram
Got an error in every browser (Safari, FF, Chrome): TypeError: $('a').live is not a function. (In '$('a').live('click', function() { inFormOrLink = true; })', '$('a').live' is undefined) (using JQuery 3.2.1)Blackboard
@Jonny: It's now just .on().Excrescency
That was it, tnx! $(window).on('beforeunload', function(){ // do something });Blackboard
This is great logic, but isnt that a race condition?? Could you analyze the event when it is triggered by beforeunload and determine the type of the source? Or worst case use a timeout . . but those tend to snowball!Fritzsche
@HimanshuBansal - that browser does not support this event, true statement that - so it is not this code but that browser specific lacks support for this event.Euphonic
@MarkSchultheiss is there any way to track if the user terminate the browser on mobile..android/ios which we normally do rather than closing tab then closing browserValerianaceous
@Excrescency How can we filter other events like clicking a back button, doing a refresh, or opening a bookmark? In the code provided by you, you have applied 2 filters which are working fine. How can we implement other filters as well? Please suggest.Spicule
B
46

Maybe just unbind the beforeunload event handler within the form's submit event handler:

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});
Boggle answered 27/10, 2009 at 16:20 Comment(2)
Isn't this just as easy not using jQuery by specifying this in the form tag definition? : `<form onsubmit="window.onbeforeunload=null;">Westering
@Westering But you'd need to include that onsubmit=... in each form. (I have many forms per page, in a certain webapp)Deerskin
E
19
window.onbeforeunload = function () {
    return "Do you really want to close?";
};
Emeldaemelen answered 9/3, 2014 at 8:24 Comment(0)
P
17

For a cross-browser solution (tested in Chrome 21, IE9, FF15), consider using the following code, which is a slightly tweaked version of Slaks' code:

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

Note that since Firefox 4, the message "Do you really want to close?" is not displayed. FF just displays a generic message. See note in https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload

Palaeo answered 25/9, 2012 at 15:7 Comment(1)
This one works consistently across browsers. Just a quick note; I updated both the live and the bind statements to on, which works great with the latest level of jQuery. Thanks!Persuade
T
10

My answer is aimed at providing simple benchmarks.

HOW TO

See @SLaks answer.

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

How long does the browser take to finally shut your page down?

Whenever an user closes the page (x button or CTRL + W), the browser executes the given beforeunload code, but not indefinitely. The only exception is the confirmation box (return 'Do you really want to close?) which will wait until for the user's response.

Chrome: 2 seconds.
Firefox: ∞ (or double click, or force on close)
Edge: ∞ (or double click)
Explorer 11: 0 seconds.
Safari: TODO

What we used to test this out:

  • A Node.js Express server with requests log
  • The following short HTML file

What it does is to send as many requests as it can before the browser shut downs its page (synchronously).

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

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.
Tuppence answered 29/11, 2016 at 22:56 Comment(0)
I
4

For a solution that worked well with third party controls like Telerik (ex.: RadComboBox) and DevExpress that use the Anchor tags for various reasons, consider using the following code, which is a slightly tweaked version of desm's code with a better selector for self targeting anchor tags:

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;
});
Intractable answered 14/5, 2013 at 14:51 Comment(1)
This answer is correct but for those who have had issues with this event happening when you refresh the browser change your if to the following code: if (inFormOrLink !== undefined && !inFormOrLink)Estop
A
3

I used Slaks answer but that wasn't working as is, since the onbeforeunload returnValue is parsed as a string and then displayed in the confirmations box of the browser. So the value true was displayed, like "true".

Just using return worked. Here is my 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;
})
Anxiety answered 30/4, 2012 at 13:51 Comment(0)
N
1

Perhaps you could handle OnSubmit and set a flag that you later check in your OnBeforeUnload handler.

Nerveless answered 27/10, 2009 at 16:17 Comment(0)
H
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?";
    }
})
Heehaw answered 30/6, 2015 at 6:21 Comment(0)
L
1

Unfortunately, whether it is a reload, new page redirect, or browser close the event will be triggered. An alternative is catch the id triggering the event and if it is form dont trigger any function and if it is not the id of the form then do what you want to do when the page closes. I am not sure if that is also possible directly and is tedious.

You can do some small things before the customer closes the tab. javascript detect browser close tab/close browser but if your list of actions are big and the tab closes before it is finished you are helpless. You can try it but with my experience donot depend on it.

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

Lucan answered 10/12, 2015 at 14:33 Comment(0)
W
0

If your form submission takes them to another page (as I assume it does, hence the triggering of beforeunload), you could try to change your form submission to an ajax call. This way, they won't leave your page when they submit the form and you can use your beforeunload binding code as you wish.

Wrongful answered 27/10, 2009 at 16:24 Comment(0)
A
0

My Issue: The 'onbeforeunload' event would only be triggered if there were odd number of submits(clicks). I had a combination of solutions from similar threads in SO to have my solution work. well my code will speak.

<!--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'); 
}
Althorn answered 14/4, 2012 at 7:43 Comment(0)
T
0

As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live()

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

on complete or link

$(window).unbind();
Tother answered 11/7, 2013 at 13:12 Comment(0)
M
-1

Just verify...

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");
    }
  }
}
Malversation answered 27/12, 2013 at 0:46 Comment(1)
It doesn't work. At the moment the unload event fires (btw, it fires from document), the window.closed === false;Tingly
S
-1

Try this also

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
    }
};
Shakeup answered 6/12, 2016 at 11:22 Comment(0)
C
-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`
Campbellite answered 18/4, 2017 at 14:11 Comment(0)
J
-7

Following worked for me;

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });
Jonson answered 17/11, 2011 at 0:26 Comment(1)
The event.clientY is negative if you click on the browser close button or tab close button. However, this value is positive when you reload the page using keyboard shortcuts (F5, Ctrl-R) or close the browser using keyboard shortcurts (e.g. Alt-F4). Thus, you cannot rely the event position to differenciate browser close event from page reload event.Riojas

© 2022 - 2024 — McMap. All rights reserved.