Search code examples
javascripthtmlonbeforeunload

Javascript, controlling an onbeforeunload tag


I'm trying to set up a onbeforeunload tag to stop a user from leaving specific pages if and only if they have unsaved content, and only on specific pages (we're using a single master page). I quickly discovered that having a return ##anything## in the onbeforeunload tag would always trigger a javascript confirm, and puts ##anything## inside the pop-up. Obviously, this is now expected behavior, but it does take away my idea of using my own confirm box that could be controlled with an if statement.

I tried this, and it didn't work:

<body class="yui-skin-sam" onbeforeunload="document.onFormClose();">

<script>
document.onFormClose = function () {
    if (document.getElementById('DirtyFlag').value == "true") {
        document.getElementById('DirtyFlag').value == "false";
        return 'You will lose all changes made since your last save';
    }
}
</script>

where DirtyFlag is a hidden field that turns true if any unsaved changes exist. I'd hoped that putting the return inside the function would do the trick, but no such luck.

So my question is, is there a way to use the onbeforeunload tag with a return built in that will bypass it pending the value of that field? Alternatively, (though this would be less ideal) I suppose I could add or remove the onbeforeunload tag dynamically, in all the places I set or reset the getElementById tag. Unfortunately, I don't know how to do that either. Oh, and I'm restricted completely from using jQuery or any other javascript library.


Solution

  • Not sure if this is as designed, but if you return null from the event handler, you might get the results you want:

    window.onbeforeunload = function() {
        var el = document.getElementById("dirtyFlag");
        if (el.value === "true") {
            return 'You will lose all changes made since your last save';
    
        }
        else {
            return null;
        }
    };
    

    The following works in FF: http://jsfiddle.net/andrewwhitaker/chZJ8/. Try changing the hidden inputs value to "true" and you should start getting the confirmation dialog. However, I cannot get it to work in Chrome and I'm unable to test in IE. It would be great if someone could confirm this works in either of those browsers.

    Edit: Adding another example that's easier to use and works in Chrome (the iFrame in JSFiddle was causing issues). Check out the example here: http://andrewawhitaker.com/examples/onbeforeunload_test.html. Type 'true' in the input to see a confirmation. If 'true' is not the value of the input, no dialog is displayed. Works in FF and Chrome, still can't vouch for IE.

    Update 2: A more reliable way of doing this is probably to add and remove the event listener when you set the value for dirtyFlag programmatically, just remove or add the event handler appropriately:

    var isDirty = function() { ... };
    if (/* form is dirty*/) {
        window.onbeforeunload = isDirty;
    }
    else {
        window.onbeforeunload = null;
    }