代码之家  ›  专栏  ›  技术社区  ›  khelll

如何捕获浏览器窗口关闭事件?

  •  135
  • khelll  · 技术社区  · 15 年前

    我想捕获浏览器窗口/选项卡关闭事件。 我用jquery尝试了以下方法:

    jQuery(window).bind(
        "beforeunload", 
        function() { 
            return confirm("Do you really want to close?") 
        }
    )
    

    但它也适用于表单提交,这不是我想要的。我想要一个只在用户关闭窗口时触发的事件。

    17 回复  |  直到 15 年前
        1
  •  192
  •   theRonny    10 年前

    这个 beforeunload 无论用户出于何种原因离开页面,都会激发事件。

    例如,如果用户提交表单、单击链接、关闭窗口(或选项卡),或使用地址栏、搜索框或书签转到新页面,则会激发此消息。

    可以使用以下代码排除表单提交和超链接(其他框架除外):

    var inFormOrLink;
    $('a').on('click', function() { inFormOrLink = true; });
    $('form').on('submit', function() { inFormOrLink = true; });
    
    $(window).on("beforeunload", function() { 
        return inFormOrLink ? "Do you really want to close?" : null; 
    })
    

    对于早于1.7的jquery版本,请尝试以下操作:

    var inFormOrLink;
    $('a').live('click', function() { inFormOrLink = true; });
    $('form').bind('submit', function() { inFormOrLink = true; });
    
    $(window).bind("beforeunload", function() { 
        return inFormOrLink ? "Do you really want to close?" : null; 
    })
    

    这个 live 方法不适用于 submit 事件,因此如果您添加一个新表单,您还需要将处理程序绑定到它。

    请注意,如果另一个事件处理程序取消了提交或导航,则在稍后实际关闭窗口时,您将丢失确认提示。你可以把时间记录在 提交 click 事件,并检查 预先卸载 几秒钟后发生。

        2
  •  44
  •   karim79    15 年前

    也许只是解开 beforeunload 窗体中的事件处理程序 submit 事件处理程序:

    jQuery('form').submit(function() {
        jQuery(window).unbind("beforeunload");
        ...
    });
    
        3
  •  15
  •   desm    12 年前

    对于跨浏览器解决方案(在chrome 21、ie9、ff15中测试),请考虑使用以下代码,这是Slaks代码的稍微调整版本:

    var inFormOrLink;
    $('a').live('click', function() { inFormOrLink = true; });
    $('form').bind('submit', function() { inFormOrLink = true; });
    
    $(window).bind('beforeunload', function(eventObject) {
        var returnValue = undefined;
        if (! inFormOrLink) {
            returnValue = "Do you really want to close?";
        }
        eventObject.returnValue = returnValue;
        return returnValue;
    }); 
    

    请注意,自从火狐4以来,“你真的想关闭吗?”不显示。FF只显示一般消息。见注释 https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload

        4
  •  9
  •   Behnam    11 年前
    window.onbeforeunload = function () {
        return "Do you really want to close?";
    };
    
        5
  •  4
  •   PLT    11 年前

    对于与Telerik(例如RadcomboBox)和DevExpress等因各种原因使用锚标记的第三方控件一起工作良好的解决方案,请考虑使用以下代码,这是一个稍作调整的DESM代码版本,具有更好的自定位锚标记选择器:

    var inFormOrLink;
    $('a[href]:not([target]), a[href][target=_self]').live('click', function() { inFormOrLink = true; });
    $('form').bind('submit', function() { inFormOrLink = true; });
    
    $(window).bind('beforeunload', function(eventObject) {
        var returnValue = undefined;
        if (! inFormOrLink) {
            returnValue = "Do you really want to close?";
        }
        eventObject.returnValue = returnValue;
        return returnValue;
    });
    
        6
  •  3
  •   kapad    11 年前

    我使用了slaks answer,但没有按原样工作,因为onbeforeunload返回值被解析为字符串,然后显示在浏览器的确认框中。所以显示值“真”,就像“真”。

    只是用退货工作。 这是我的密码

    var preventUnloadPrompt;
    var messageBeforeUnload = "my message here - Are you sure you want to leave this page?";
    //var redirectAfterPrompt = "http://www.google.co.in";
    $('a').live('click', function() { preventUnloadPrompt = true; });
    $('form').live('submit', function() { preventUnloadPrompt = true; });
    $(window).bind("beforeunload", function(e) { 
        var rval;
        if(preventUnloadPrompt) {
            return;
        } else {
            //location.replace(redirectAfterPrompt);
            return messageBeforeUnload;
        }
        return rval;
    })
    
        7
  •  2
  •   Community CDub    7 年前

    我的回答旨在提供简单的基准。

    如何

    @SLaks answer .

    $(window).on("beforeunload", function() { 
        return inFormOrLink ? "Do you really want to close?" : null; 
    })
    

    浏览器最终关闭页面需要多长时间?

    每当用户关闭页面时( X 按钮或 控制 + W )浏览器执行给定的 beforeunload 代码,但不能无限期地。唯一的例外是确认框( return 'Do you really want to close? )等待用户的响应。

    :2秒。
    火狐 :_(或双击,或强制关闭)
    :_(或双击)
    资源管理器11 0秒。
    游猎 : 托多

    我们用来测试的是:

    • 带有请求日志的node.js Express服务器
    • 下面的短HTML文件

    它所做的就是在浏览器关闭页面(同步)之前发送尽可能多的请求。

    <html>
    <body>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
        <script>
        function request() {
            return $.ajax({
                type: "GET",
                url: "http://localhost:3030/" + Date.now(),
                async: true
            }).responseText;
        }
        window.onbeforeunload = () => {
            while (true) {
                request();
            }
            return null;
        }
        </script>
    </body>
    </html>
    

    铬输出:

    GET /1480451321041 404 0.389 ms - 32  
    GET /1480451321052 404 0.219 ms - 32  
    ...  
    GET /hello/1480451322998 404 0.328 ms - 32
    
    1957ms ≈ 2 seconds // we assume it's 2 seconds since requests can take few milliseconds to be sent.
    
        8
  •  1
  •   i_am_jorf    15 年前

    也许您可以处理onsubmit并设置一个标志,稍后您可以签入onbeforeunload处理程序。

        9
  •  1
  •   Coding man    9 年前
    jQuery(window).bind(
                        "beforeunload",
                          function (e) {
                              var activeElementTagName = e.target.activeElement.tagName;
                              if (activeElementTagName != "A" && activeElementTagName != "INPUT") {
                                  return "Do you really want to close?";
                              }
                          })
    
        10
  •  1
  •   Community CDub    7 年前

    不幸的是,无论是重新加载、新页面重定向还是浏览器关闭,都会触发事件。另一种方法是捕获触发事件的ID,如果它是表单,则不触发任何函数;如果它不是表单的ID,则在页面关闭时执行您希望执行的操作。我不确定这是否也可能是直接的,是乏味的。

    你可以在客户关闭标签前做一些小事情。 javascript detect browser close tab/close browser 但是,如果你的行动清单很大,而且在完成之前标签就关闭了,你就束手无策了。你可以试一下,但根据我的经验,不一定要依靠它。

    window.addEventListener("beforeunload", function (e) {
      var confirmationMessage = "\o/";
      /* Do you small action code here */
      (e || window.event).returnValue = confirmationMessage; //Gecko + IE
      return confirmationMessage;                            //Webkit, Safari, Chrome
    });
    

    https://developer.mozilla.org/en-US/docs/Web/Reference/Events/beforeunload?redirectlocale=en-US&redirectslug=DOM/Mozilla_event_reference/beforeunload

        11
  •  0
  •   idrumgood    15 年前

    如果您提交的表单将它们带到另一页(我认为是这样的,因此触发了 beforeunload ,您可以尝试将表单提交更改为Ajax调用。这样,他们提交表单时不会离开您的页面,您可以使用 预先卸载 根据需要绑定代码。

        12
  •  0
  •   Yoosaf Abdulla    12 年前

    我的问题:只有提交(单击)次数为奇数时才会触发“onbeforeunload”事件。我有来自类似线程的解决方案组合,以便使我的解决方案工作。好吧,我的密码会说出来的。

    <!--The definition of event and initializing the trigger flag--->
    
    
    $(document).ready(function() {
    updatefgallowPrompt(true);
    window.onbeforeunload = WarnUser;   
    }
    
    function WarnUser() {
    var allowPrompt = getfgallowPrompt();
        if(allowPrompt) {
        saveIndexedDataAlert();
        return null;
        } else {
            updatefgallowPrompt(true);
            event.stopPropagation
        }
    }
    
    <!--The method responsible for deciding weather the unload event is triggered from submit or not--->
    function saveIndexedDataAlert() {
        var allowPrompt = getfgallowPrompt();
        var lenIndexedDocs = parseInt($('#sortable3 > li').size()) + parseInt($('#sortable3 > ul').size());
    
        if(allowPrompt && $.trim(lenIndexedDocs) > 0) {
            event.returnValue = "Your message";
        } else {
            event.returnValue = "   ";
            updatefgallowPrompt(true);
        }
    }
    
    <!---Function responsible to reset the trigger flag---->
    $(document).click(function(event) {  
    $('a').live('click', function() { updatefgallowPrompt(false); });
     });
    
    <!--getter and setter for the flag---->
    function updatefgallowPrompt (allowPrompt){ //exit msg dfds
        $('body').data('allowPrompt', allowPrompt); 
    }   
    
    function getfgallowPrompt(){        
        return $('body').data('allowPrompt');   
    }
    
        13
  •  0
  •   Tom    11 年前

    从jquery 1.7开始,不推荐使用.live()方法。使用.on()附加事件处理程序。旧版本jquery的用户应优先使用.delegate(),而不是.live()。

    $(window).bind("beforeunload", function() {
        return true || confirm("Do you really want to close?"); 
    }); 
    

    完成或链接时

    $(window).unbind();
    
        14
  •  0
  •   Bhaskara Arani    8 年前

    试试这个

    window.onbeforeunload = function ()
    {       
        if (pasteEditorChange) {
            var btn = confirm('Do You Want to Save the Changess?');
               if(btn === true ){
                   SavetoEdit();//your function call
               }
               else{
                    windowClose();//your function call
               }
        }  else { 
            windowClose();//your function call
        }
    };
    
        15
  •  -1
  •   animuson    10 年前

    只要核实…

    function wopen_close(){
      var w = window.open($url, '_blank', 'width=600, height=400, scrollbars=no, status=no, resizable=no, screenx=0, screeny=0');
      w.onunload = function(){
        if (window.closed) {
           alert("window closed");
        }else{ 
           alert("just refreshed");
        }
      }
    }
    
        16
  •  -1
  •   arslan khan    7 年前
    var validNavigation = false;
                jQuery(document).ready(function () {
    
                    wireUpEvents();
                });
    
                function endSession() {
                    // Browser or broswer tab is closed
                    // Do sth here ...
                    alert("bye");
                }
    
                function wireUpEvents() {
                    /*
                    * For a list of events that triggers onbeforeunload on IE
                    * check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
                    */
                    window.onbeforeunload = function () {
                        debugger
                        if (!validNavigation) {
                            endSession();
                        }
                    }
    
                    // Attach the event keypress to exclude the F5 refresh
                    $(document).bind('keypress', function (e) {
                        debugger
                        if (e.keyCode == 116) {
                            validNavigation = true;
                        }
                    });
    
                    // Attach the event click for all links in the page
                    $("a").bind("click", function () {
                        debugger
                        validNavigation = true;
                    });
    
                    // Attach the event submit for all forms in the page
                    $("form").bind("submit", function () {
                        debugger
                        validNavigation = true;
                    });
    
                    // Attach the event click for all inputs in the page
                    $("input[type=submit]").bind("click", function () {
                        debugger
                        validNavigation = true;
                    });
    
                }`enter code here`
    
        17
  •  -7
  •   bfontaine cat-walk    10 年前

    跟随者为我工作;

     $(window).unload(function(event) {
        if(event.clientY < 0) {
            //do whatever you want when closing the window..
        }
     });