最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - IE9 onbeforeunload called twice when window.location changed in button event... minimal reproduction - Stack Overfl

programmeradmin3浏览0评论

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!

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!

Share Improve this question edited Apr 2, 2012 at 17:19 user505765 asked Apr 1, 2012 at 20:15 user505765user505765 5191 gold badge8 silver badges15 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 5

Try this, this worked for me. This solution was originally posted by Amit at http://social.msdn.microsoft./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;
}

As anyways your onbeforeunload is interpreted through JS, you probably can use a boolean flag in a global variable to know whether it's the first time the process started by the event runs. Like:

<head>
  ...
  <script ...>
  var flag=true;
  var ret="";
  function getoff() {
    if(flag) {
      //do your things and save your return value to the global variable "ret"
      //ret="Unsaved changes";
      flag=false; //with this, the code above will be executed only once
    }
    return ret; //the second call will return the same thing as the first call, as first call's return value is stored in a global variable, and is not modified during the second call
  }
  </script>
</head>
<body onbeforeunload="return getoff();">
...

Another possibility perhaps, as according to this post the problem seems to e from changing the page using JS, you can use a hidden hyperlink to change the page using HTML, something like:

<a href="404.htm" id="myButton" style="display:none;visibility:hidden;"></a>

Then your button could do:

<input type="button" ... onclick="document.getElementById('myButton').click();">

Assuming any of this works, a hidden link like that is an ugly hack (the first possibility isn't much prettier anyway), but what doesn't require some ugly hacks when it's about having MSIE behave like if it was a web browser...

With the next code, you can fix this for any case:

window.location = 'javascript:window.location = "http://www.google."';

I found that it is called twice when using postback and non-asp tagged controls. Change controls from <button> to <asp:Button>, etc. to solve this.

I think I found a cleaner solution to the problem. I set the onbeforeunload to null inside the callback, and reset it prior to exit:

...
window.onbeforeunload=confirmExit;

function confirmExit(){
    window.onbeforeunload=null;
    event.returnValue="You have not saved your document yet.";
    window.onbeforeunload=confirmExit;
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论