【问题标题】:window.beforeunload called twice in Firefox - how to get around this?window.beforeunload 在 Firefox 中调用了两次 - 如何解决这个问题?
【发布时间】:2009-11-26 00:50:45
【问题描述】:

我正在创建一个安装了 beforeunload 处理程序的弹出窗口。当使用“Close”文件菜单项关闭弹窗时,调用了两次 beforeunload 处理程序,产生了两个“Are you sure you want to close this window?”。出现消息。

这是 Firefox 的一个错误,我有 reported it here,但我仍然想要一种方法来防止这种情况发生。你能想出一种明智的方法来检测双重 beforeunload 以防止双重消息问题吗?问题是 Firefox 没有告诉我用户选择单击对话框中的哪个按钮 - 确定或取消。

【问题讨论】:

标签: javascript firefox onbeforeunload


【解决方案1】:
<script type="text/javascript">
var onBeforeUnloadFired = false;

window.onbeforeunload = function ()
{
    if (!onBeforeUnloadFired) {
        onBeforeUnloadFired = true;
        event.returnValue = "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
   }

   window.setTimeout("ResetOnBeforeUnloadFired()", 10);
}

function ResetOnBeforeUnloadFired() {
   onBeforeUnloadFired = false;
}    
</script>

【讨论】:

    【解决方案2】:

    在处理程序中设置一个变量以防止对话框第二次出现。之后使用 setTimeout 重置它。

    【讨论】:

    • 什么是合理的超时值?将其设置得太短,速度慢的用户最终会看到两次对话框。将其设置得太长,用户将根本看不到对话框 - 这是不应该发生的事情,因为它可能会导致他们丢失数据。
    • 你可以把它写得很短。我假设对 beforeunload 的两次调用相隔几毫秒。将超时设置为 100 毫秒左右,Boone 就会知道它的存在。
    • 不过,只要用户按下第一个对话框上的“确定”按钮,就会进行第二次调用。
    【解决方案3】:

    这绝对是一个 FF 错误。我已经在https://bugzilla.mozilla.org/show_bug.cgi?id=531199报告了它

    【讨论】:

      【解决方案4】:

      我找到的最佳解决方案是使用一个标志全局变量,该变量会在这么多毫秒后重置,比如 500(这确保可以再次调用该函数,但不能在其出现后立即调用)。

      查看最后的代码:

      http://social.msdn.microsoft.com/Forums/en/sharepointinfopath/thread/13000cd8-5c50-4260-a0d2-bc404764966d

      【讨论】:

        【解决方案5】:

        我在 Chrome 21、Firefox 14、IE 7-9、Safari 5(PC 上)中发现了这个问题。

        以下内容适用于所有这些浏览器。如果在事件期间删​​除了 window.onbeforeunload 函数,这将阻止第二次调用。如果用户决定留在页面上,诀窍是重置 window.onbeforeunload 函数。

        var window_on_before_unload = function(e) {
            var msg;
            // Do here what you ever you need to do
            msg = "Message for user";
        
            // Prevent next "window.onbeforeunload" from re-running this code.
            // Ensure that if the user decides to stay on the page that
            // this code is run the next time the user tries to leave the page.
            window.onbeforeunload = set_on_before_unload;
        
            // Prepare message for user
            if (msg) {
                if (/irefox\/([4-9]|1\d+)/.test(navigator.userAgent))
                    alert(msg
                            + '\n\nThe next dialog will allow you to stay here or continue\nSee Firefox bug #588292');
        
                (e = e || window.event).returnValue = msg;
                return msg;
            }
        };
        
        // Set window.onbeforeunload to the above handler.
        // @uses window_on_before_unload
        // @param {Event} e
        var set_on_before_unload = function(e) {
            // Initialize the handler for window.onbeforeunload.
            window.onbeforeunload = window_on_before_unload;
        }
        
        // Initialize the handler for window.onbeforeunload.
        set_on_before_unload();
        

        【讨论】:

          【解决方案6】:

          在处理程序中创建一个设置为 true 的全局变量。仅当此变量为 false 时才显示警报/弹出窗口。

          【讨论】:

          • 但是如果用户取消了关闭呢?然后,下次他们尝试关闭窗口时,对话框根本不会弹出。
          • 如果您使用confirm() 作为警告消息,您可以检测用户是否取消关闭并相应地设置全局变量。
          • 背景:如果您从 beforeunload 处理程序返回任何内容,则浏览器会显示“您确定要关闭”的对话框,并将返回值合并到文本中。我不知道有什么方法可以了解用户是单击确定还是取消。
          • 啊,我误解了问题的范围。这是FF中的一个错误。我在 Vista 上没有遇到 FF3.0.15 的问题
          【解决方案7】:

          我使用下面的sn-p来跟踪exitcount

          当页面加载时,下面的变量exitCount被初始化

          if (typeof(MTG) == 'undefined') MTG = {};
          MTG.exitCount=0; 
          

          在窗口卸载事件中

          $(window).bind("beforeunload", function(){
          
          
                      if (MTG.exitCount<=0) 
                      {
          
                                       //do your thing, save etc
                      }   
                      MTG.exitCount++;
          
          
          
          
          });
          

          【讨论】:

            【解决方案8】:

            我发现,与其自己调用 confirm(),不如执行 even.preventDefault();在 beforeunload 事件中。 Firefox 会弹出自己的确认对话框。 我不确定这是否是正确/标准的做法,但他们就是这样做的。

            【讨论】:

              【解决方案9】:

              我有一个使用 window.open 打开另一个弹出窗口的文档。在原始窗口中,我已经(使用 jquery)注册了一个“卸载”事件的侦听器,如下所示:

              var popup_window = window.open(...) 
              $(popup_window).on('unload', function(event) ...
              

              我遇到此页面是因为该事件有效地触发了两次。我发现它不是一个错误,它会触发两次,因为它会触发一次“about:blank”页面被您的页面替换,另一个触发您的页面被卸载。

              我所要做的就是通过查询原始事件来过滤我感兴趣的事件:

              function (event) {
                 var original_url = e.originalEvent.originalTarget.URL;
                 if (original_url != 'about:blank')
                 {
                     ... do cool things ...
                 }
              }
              

              我不知道这是否适用于原始问题,因为它是一个窗口打开另一个窗口的特殊情况,但我希望它有所帮助。

              【讨论】:

                猜你喜欢
                • 2017-05-07
                • 2015-07-28
                • 2022-01-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-10-07
                • 1970-01-01
                相关资源
                最近更新 更多