IE9 onbeforeunload called twice when window.location changed in button event... minimal reproduction

user505765 picture user505765 · Apr 1, 2012 · Viewed 7.5k times · Source

I've been hammering and hammering at this and just can't get anywhere.

I have a cancel button that does a "window.location = '404.htm';" when clicked. The onbeforeunload handler fires twice, but only if the user clicks "Stay on this page" to the first dialog. A normal navigation (page refresh, going to home page) the onbeforeunload handler only fires once.

I've managed to repro the behavior with a minimal amount of HTML and script:

<!DOCTYPE html>
<html>
<head>
    <title>Test page</title>
</head>
<body onbeforeunload="return 'Unsaved changes';">
    <form name="form1" id="form1">
        <input id='cmdCancel' type="button" value="Cancel" onclick="window.location = '404.htm';" />
    </form>
    <script type="text/javascript">
        /*
         * Connecting the events via code makes no difference
         *
        document.forms[0].cmdCancel.onclick =
            function () {
                alert('Clicked cancel. About to navigate...');
                window.location = '404.htm';
            };

        window.onbeforeunload = function () {
            return "Unsaved changes";
        }; 

        */   
    </script>
</body>
</html>

There are lots of hits for "onbeforeunload called twice" but no minimal reproduction and no actual solutions.

Any suggestions?

Thanks!

Answer

James Poulose picture James Poulose · Oct 11, 2012

Try this, this worked for me. This solution was originally posted by Amit at http://social.msdn.microsoft.com/Forums/eu/sharepointinfopath/thread/13000cd8-5c50-4260-a0d2-bc404764966d?prof=required

Remember, disabling the onbeforeunload temporarily and enabling it back after a short while is the key.

var checkChangesEnabled = true;

window.onbeforeunload = confirmExit;

function confirmExit()
{
  if(checkChangesEnabled)
  {
    event.returnValue = "You have not saved your document yet.";
    disableCheck();
  }
}

function disableCheck()
{
  checkChangesEnabled = false;
  setTimeout("enableCheck()", "100");
}

function enableCheck()
{
   checkChangesEnabled = true;
}