How to show the "Are you sure you want to navigate away from this page?" when changes committed?

Viewed 262187

Here in stackoverflow, if you started to make changes then you attempt to navigate away from the page, a javascript confirm button shows up and asks: "Are you sure you want to navigate away from this page?" blee blah bloo...

Has anyone implemented this before, how do I track that changes were committed? I believe I could do this myself, I am trying to learn the good practices from you the experts.

I tried the following but still doesn't work:

<html>
<body>
    <p>Close the page to trigger the onunload event.</p>
    <script type="text/javascript">
        var changes = false;        
        window.onbeforeunload = function() {
            if (changes)
            {
                var message = "Are you sure you want to navigate away from this page?\n\nYou have started writing or editing a post.\n\nPress OK to continue or Cancel to stay on the current page.";
                if (confirm(message)) return true;
                else return false;
            }
        }
    </script>

    <input type='text' onchange='changes=true;'> </input>
</body>
</html>

Can anyone post an example?

18 Answers

Update (2017)

Modern browsers now consider displaying a custom message to be a security hazard and it has therefore been removed from all of them. Browsers now only display generic messages. Since we no longer have to worry about setting the message, it is as simple as:

// Enable navigation prompt
window.onbeforeunload = function() {
    return true;
};
// Remove navigation prompt
window.onbeforeunload = null;

Read below for legacy browser support.

Update (2013)

The orginal answer is suitable for IE6-8 and FX1-3.5 (which is what we were targeting back in 2009 when it was written), but is rather out of date now and won't work in most current browsers - I've left it below for reference.

The window.onbeforeunload is not treated consistently by all browsers. It should be a function reference and not a string (as the original answer stated) but that will work in older browsers because the check for most of them appears to be whether anything is assigned to onbeforeunload (including a function that returns null).

You set window.onbeforeunload to a function reference, but in older browsers you have to set the returnValue of the event instead of just returning a string:

var confirmOnPageExit = function (e) 
{
    // If we haven't been passed the event get the window.event
    e = e || window.event;

    var message = 'Any text will block the navigation and display a prompt';

    // For IE6-8 and Firefox prior to version 4
    if (e) 
    {
        e.returnValue = message;
    }

    // For Chrome, Safari, IE8+ and Opera 12+
    return message;
};

You can't have that confirmOnPageExit do the check and return null if you want the user to continue without the message. You still need to remove the event to reliably turn it on and off:

// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;

// Turn it off - remove the function entirely
window.onbeforeunload = null;

Original answer (worked in 2009)

To turn it on:

window.onbeforeunload = "Are you sure you want to leave?";

To turn it off:

window.onbeforeunload = null;

Bear in mind that this isn't a normal event - you can't bind to it in the standard way.

To check for values? That depends on your validation framework.

In jQuery this could be something like (very basic example):

$('input').change(function() {
    if( $(this).val() != "" )
        window.onbeforeunload = "Are you sure you want to leave?";
});

The onbeforeunload Microsoft-ism is the closest thing we have to a standard solution, but be aware that browser support is uneven; e.g. for Opera it only works in version 12 and later (still in beta as of this writing).

Also, for maximum compatibility, you need to do more than simply return a string, as explained on the Mozilla Developer Network.

Example: Define the following two functions for enabling/disabling the navigation prompt (cf. the MDN example):

function enableBeforeUnload() {
    window.onbeforeunload = function (e) {
        return "Discard changes?";
    };
}
function disableBeforeUnload() {
    window.onbeforeunload = null;
}

Then define a form like this:

<form method="POST" action="" onsubmit="disableBeforeUnload();">
    <textarea name="text"
              onchange="enableBeforeUnload();"
              onkeyup="enableBeforeUnload();">
    </textarea>
    <button type="submit">Save</button>
</form>

This way, the user will only be warned about navigating away if he has changed the text area, and will not be prompted when he's actually submitting the form.

With JQuery this stuff is pretty easy to do. Since you can bind to sets.

Its NOT enough to do the onbeforeunload, you want to only trigger the navigate away if someone started editing stuff.

The standard states that prompting can be controlled by canceling the beforeunload event or setting the return value to a non-null value. It also states that authors should use Event.preventDefault() instead of returnValue, and the message shown to the user is not customizable.

As of 69.0.3497.92, Chrome has not met the standard. However, there is a bug report filed, and a review is in progress. Chrome requires returnValue to be set by reference to the event object, not the value returned by the handler.

It is the author's responsibility to track whether changes have been made; it can be done with a variable or by ensuring the event is only handled when necessary.

window.addEventListener('beforeunload', function (e) {
    // Cancel the event as stated by the standard.
    e.preventDefault();
    // Chrome requires returnValue to be set.
    e.returnValue = '';
});
    
window.location = 'about:blank';

When the user starts making changes to the form, a boolean flag will be set. If the user then tries to navigate away from the page, you check that flag in the window.onunload event. If the flag is set, you show the message by returning it as a string. Returning the message as a string will popup a confirmation dialog containing your message.

If you are using ajax to commit the changes, you can set the flag to false after the changes have been committed (i.e. in the ajax success event).

You can add an onchange event on the textarea (or any other fields) that set a variable in JS. When the user attempts to close the page (window.onunload) you check the value of that variable and show the alert accordingly.

From the WebAPIs->WindowEventHandler->onbeforeunload, it recommends use window.addEventListener() and the beforeunload event, instead of onbeforeunload.

Syntax example

window.addEventListener("beforeunload", function(event) { ... });
window.onbeforeunload = function(event) { ... };

Note: The HTML specification states that authors should use the Event.preventDefault() method instead of using Event.returnValue to prompt the user.

So, in terms of your case, the code should look like this:

//javascript
window..addEventListener("beforeunload", function(event) { 
    //your code

    // If you prevent default behaviour in Mozilla Firefox prompt will always be shown
    e.preventDefault();

    // Chrome requires returnValue to be set
    e.returnValue = '';
})

It can be easily done by setting a ChangeFlag to true, on onChange event of TextArea. Use javascript to show confirm dialog box based on the ChangeFlag value. Discard the form and navigate to requested page if confirm returns true, else do-nothing.

There is an "onunload" parameter for the body tag you can call javascript functions from there. If it returns false it prevents navigating away.

Related