繁体   English   中英

检测浏览器或标签页关闭

[英]Detect browser or tab closing

是否有任何跨浏览器 JavaScript/jQuery 代码来检测浏览器或浏览器选项卡是否正在关闭,但不是由于单击了链接?

如果我理解正确,您想知道选项卡/窗口何时有效关闭。 好吧,AFAIK 在 JavaScript 中检测到这一点的唯一方法是使用onunloadonbeforeunload事件。

不幸的是(或幸运的是?),当您通过链接或浏览器的后退按钮离开站点时,也会触发这些事件。 所以这是我能给出的最好的答案,我认为你不能在 JavaScript 中检测到纯close 如果我在这里错了,请纠正我。

来自MDN 文档

由于某些原因,基于 Webkit 的浏览器不遵循对话框的规范。 一个几乎交叉工作的示例将与以下示例接近。

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";

  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

此示例用于处理所有浏览器。

简单的解决方案

window.onbeforeunload = function () {
    return "Do you really want to close?";
};
<body onbeforeunload="ConfirmClose()" onunload="HandleOnClose()">

var myclose = false;

function ConfirmClose()
{
    if (event.clientY < 0)
    {
        event.returnValue = 'You have closed the browser. Do you want to logout from your application?';
        setTimeout('myclose=false',10);
        myclose=true;
    }
}

function HandleOnClose()
{
    if (myclose==true) 
    {
        //the url of your logout page which invalidate session on logout 
        location.replace('/contextpath/j_spring_security_logout') ;
    }   
}

//这在 IE7 中工作,如果你正在关闭选项卡或只有一个选项卡的浏览器

对于类似的任务,您可以使用sessionStorage在本地存储数据,直到关闭浏览器选项卡。

sessionStorage对象仅存储一个会话的数据(关闭浏览器选项卡时数据被删除)。( W3Schools

这是我的笔

<div id="Notice">
    <span title="remove this until browser tab is closed"><u>dismiss</u>.</span>
</div>
<script>
    $("#Notice").click(function() {
     //set sessionStorage on click
        sessionStorage.setItem("dismissNotice", "Hello");
        $("#Notice").remove();
    });
    if (sessionStorage.getItem("dismissNotice"))
    //When sessionStorage is set Do stuff...
        $("#Notice").remove();
</script>

我需要在浏览器或选项卡关闭时自动注销用户,但在用户导航到其他链接时不需要。 我也不希望在发生这种情况时显示确认提示。 在为此苦苦挣扎了一段时间之后,尤其是在使用 IE 和 Edge 时,这是我在基于此答案的方法后结束的工作(检查了使用 IE 11、Edge、Chrome 和 Firefox)。

首先,在 JS 的beforeunload事件处理程序中在服务器上启动一个倒计时。 ajax 调用需要同步,IE 和 Edge 才能正常工作。 你还需要使用return; 防止确认对话框显示如下:

    window.addEventListener("beforeunload", function (e) {        
      $.ajax({
          type: "POST",
          url: startTimerUrl,
          async: false           
      });
      return;
    });

启动计时器cancelLogout标志设置为false 如果用户刷新页面或导航到另一个内部链接,则服务器上的cancelLogout标志设置为true 一旦计时器事件过去,它会检查cancelLogout标志以查看注销事件是否已被取消。 如果计时器已被取消,则它将停止计时器。 如果浏览器或选项卡已关闭,则cancelLogout标志将保持为false ,并且事件处理程序会将用户注销。

实施说明:我正在使用 ASP.NET MVC 5,并且我在重写的Controller.OnActionExecuted()方法中取消注销。

我找到了一种适用于我所有浏览器的方法。

在以下版本上测试:Firefox 57、Internet Explorer 11、Edge 41、最新的 Chrome 之一(它不会显示我的版本)

注意:如果您以任何可能的方式离开页面(刷新、关闭浏览器、重定向、链接、提交..),onbeforeunload 就会触发。 如果您只希望它在浏览器关闭时发生,只需绑定事件处理程序。

  $(document).ready(function(){         

        var validNavigation = false;

        // Attach the event keypress to exclude the F5 refresh (includes normal refresh)
        $(document).bind('keypress', function(e) {
            if (e.keyCode == 116){
                validNavigation = true;
            }
        });

        // Attach the event click for all links in the page
        $("a").bind("click", function() {
            validNavigation = true;
        });

        // Attach the event submit for all forms in the page
        $("form").bind("submit", function() {
          validNavigation = true;
        });

        // Attach the event click for all inputs in the page
        $("input[type=submit]").bind("click", function() {
          validNavigation = true;
        }); 

        window.onbeforeunload = function() {                
            if (!validNavigation) {     
                // ------->  code comes here
            }
        };

  });

没有事件,但是在撰写本文时,所有主要浏览器都支持window.closed属性。 因此,如果您真的需要知道,您可以轮询窗口以检查该属性。

if(myWindow.closed){do things}

注意:轮询任何东西通常不是最好的解决方案。 如果可能,应该使用window.onbeforeunload事件,唯一需要注意的是,如果您离开,它也会触发。

抱歉,我无法对现有答案之一添加评论,但如果您想实现一种警告对话框,我只想提一下,任何事件处理函数都有一个参数 - event。 在您的情况下,您可以调用 event.preventDefault() 来禁止自动离开页面,然后发出您自己的对话框。 我认为这是比使用标准的丑陋和不安全的警报()更好的选择。 我个人基于 kendoWindow 对象(Telerik 的 Kendo UI,它几乎完全开源,除了 kendoGrid 和 kendoEditor)实现了我自己的一组对话框。 您还可以使用 jQuery UI 中的对话框。 但请注意,这些事情是异步的,您需要将处理程序绑定到每个按钮的 onclick 事件,但这一切都很容易实现。

但是,我确实同意缺少真正的关闭事件是可怕的:例如,如果您只想在真正关闭的情况下在后端重置会话状态,那么这是一个问题。

$(window).unload( function () { alert("Bye now!"); } );

由于还没有人提到它(8 年多之后):WebSocket 可以是另一种检测关闭选项卡的有效方法。 只要选项卡打开并指向主机,客户端就能够保持与主机的活动 WebSocket 连接。

警告:请注意,如果 WebSocket 不需要您已经在做的任何额外的重大开销,则此解决方案实际上仅适用于项目。

在合理的超时期限内(例如 2 分钟),服务器端可以确定客户端在 WebSocket 断开连接后已经离开,并执行所需的任何操作,例如删除上传的临时文件。 (在我极其专业的用例中,我的目标是在 WebSocket 连接断开并且所有 CGI/FastCGI 活动终止后三秒终止本地主机应用程序服务器- 任何其他保持活动连接都不会影响我。)

我在让 onunload 事件处理程序与信标正常工作时遇到问题(如this answer所建议的那样)。 关闭选项卡似乎不会触发信标,而打开的选项卡会以可能导致问题的方式触发它。 WebSocket 更干净地解决了我遇到的问题,因为连接关闭的时间大约与选项卡关闭的同时关闭,并且在应用程序中切换页面只是在延迟窗口内打开一个新的 WebSocket 连接。

是否有跨浏览器的JavaScript / jQuery代码来检测浏览器或浏览器选项卡是否已关闭,但不是由于单击链接而导致的?

onunloadChrome的答案。 根据caniuse其跨浏览器。 但并非所有浏览器的反应都一样。

window.onunload = function(){
    alert("The window is closing now!");
}

developer.mozilla.org

这些事件在窗口卸载其内容和资源时触发。

对于

onunload页面关闭时执行。 即使在页面刷新和导航到不同的页面时,它也不会执行。

对于Firefox v86.0

它根本不会执行。 页面刷新,导航,关闭浏览器选项卡,关闭浏览器,什么都没有。

window.onbeforeunload = function() {
  console.log('event');
  return false; //here also can be string, that will be shown to the user
}
window.addEventListener("beforeunload", function (e) {
 var confirmationMessage = "tab close";

 (e || window.event).returnValue = confirmationMessage;     //Gecko + IE
 sendkeylog(confirmationMessage);
 return confirmationMessage;                                //Webkit, Safari, Chrome etc.
}); 
//Detect Browser or Tab Close Events
$(window).on('beforeunload',function(e) {
  e = e || window.event;
  var localStorageTime = localStorage.getItem('storagetime')
  if(localStorageTime!=null && localStorageTime!=undefined){
    var currentTime = new Date().getTime(),
        timeDifference = currentTime - localStorageTime;

    if(timeDifference<25){//Browser Closed
       localStorage.removeItem('storagetime');
    }else{//Browser Tab Closed
       localStorage.setItem('storagetime',new Date().getTime());
    }

  }else{
    localStorage.setItem('storagetime',new Date().getTime());
  }
});

JSFiddle 链接

大家好,我能够通过使用浏览器本地存储和时间戳来实现“检测浏览器和选项卡关闭事件”点击。 希望大家都可以通过使用此解决方案来解决您的问题。

经过我的初步研究,我发现当我们关闭浏览器时,浏览器会一一关闭所有选项卡以完全关闭浏览器。 因此,我观察到关闭标签之间的时间延迟非常小。 所以我把这个时间延迟作为我的主要验证点,并能够实现浏览器和标签关闭事件检测。

我在 Chrome 浏览器版本 76.0.3809.132 上对其进行了测试,发现工作正常

:) 如果您发现我的回答有帮助,请投票。

我已经尝试了上述所有解决方案,但没有一个真正适合我,特别是因为我的项目中有一些 Telerik 组件具有弹出窗口的“关闭”按钮,并且它调用“beforeunload”事件。 此外,当您的页面中有 Telerik 网格时,按钮选择器无法正常工作(我的意思是网格内的按钮)所以,我无法使用上述任何建议。 最后,这是对我有用的解决方案。 我在 _Layout.cshtml 的 body 标签上添加了一个 onUnload 事件。 像这样的东西:

<body onUnload="LogOff()">

然后添加 LogOff 函数以重定向到 Asp.Net MVC 中的内置方法 Account/LogOff。 现在,当我关闭浏览器或选项卡时,它会重定向到 LogOff 方法,并且用户必须在返回时登录。 我已经在 Chrome 和 Firefox 中测试过了。 它有效!

  function LogOff() {
        $.ajax({
            url: "/Account/LogOff",
            success: function (result) {

                                        }
               });
       }
window.onbeforeunload = function ()
{       

    if (isProcess > 0) 
    {
        return true;       
    }   

    else
    { 
        //do something      
    }
}; 

如果您在浏览器的任何进程中关闭窗口或刷新页面,此功能会显示一个确认对话框。此功能适用于所有浏览器。您必须在您的 ajax 进程中设置 isProcess var。

可以在这样的“卸载”事件的事件处理程序中借助 window.close 进行检查,但需要使用超时(因此如果延迟或阻止窗口关闭,则无法保证结果):

JSFiddle 示例(在最新的 Safari、FF、Chrome、Edge 和 IE11 上测试)

var win = window.open('', '', 'width=200,height=50,left=200,top=50');
win.document.write(`<html>
   <head><title>CHILD WINDOW/TAB</title></head>
   <body><h2>CHILD WINDOW/TAB</h2></body>
</html>`);
win.addEventListener('load',() => {
    document.querySelector('.status').innerHTML += '<p>Child was loaded!</p>';
});
win.addEventListener('unload',() => {
    document.querySelector('.status').innerHTML += '<p>Child was unloaded!</p>';
    setTimeout(()=>{
        document.querySelector('.status').innerHTML +=  getChildWindowStatus();
    },1000);
});
win.document.close()
document.querySelector('.check-child-window').onclick = ()=> {
    alert(getChildWindowStatus());
}
function getChildWindowStatus() {
  if (win.closed) { 
      return 'Child window has been closed!';
  } else {
      return 'Child window has not been closed!';
  }
}

浏览器进行了更新,以便在离开应用程序时更好地吸引用户。 事件 'visibilitychange' 可让您在页面从另一个选项卡中隐藏或关闭时进行跟踪。 您可以跟踪文档可见性状态。 属性 document.visibilityState 将返回当前状态。 您将需要跟踪登录和退出,但它更接近目标。

更新的浏览器支持这一点,但 safari(我们知道)从不符合标准。 您可以使用 'pageshow' 和 'pagehide' 在 safari 中工作。

您甚至可以使用诸如 sendBeacon 之类的新 API 在选项卡关闭且不应期待响应时向服务器发送单向请求。

我构建了一个用于跟踪它的类的快速端口。 我不得不删除框架中的一些调用,所以它可能是错误的,但这应该让你开始。

export class UserLoginStatus
{
    /**
     * This will add the events and sign the user in.
     */
    constructor()
    {
        this.addEvents();
        this.signIn();
    }

    /**
     * This will check if the browser is safari. 
     * 
     * @returns {bool}
     */
    isSafari()
    {
        if(navigator && /Safari/.test(navigator.userAgent) && /Chrome/.test(navigator.userAgent))
        {
            return (/Google Inc/.test(navigator.vendor) === false);
        }
        return false;
    }

    /**
     * This will setup the events array by browser.
     * 
     * @returns {array}
     */
    setupEvents()
    {
        let events = [
            ['visibilitychange', document, () =>
            {
                if (document.visibilityState === 'visible')
                {
                    this.signIn();
                    return;
                }

                this.signOut();
            }]
        ];

        // we need to setup events for safari
        if(this.isSafari())
        {
            events.push(['pageshow', window, (e) =>
            {
                if(e.persisted === false)
                {
                    this.signIn();
                }
            }]);

            events.push(['pagehide', window, (e) =>
            {
                if(e.persisted === false)
                {
                    this.signOut();
                }
            }]);
        }

        return events;
    }

    /**
     * This will add the events.
     */
    addEvents()
    {
        let events = this.setupEvents();
        if(!events || events.length < 1)
        {
            return;
        }

        for(var i = 0, length = events.length; i < length; i++)
        {
            var event = events[i];
            if(!event)
            {
                continue;
            }

            event[1].addEventListener(event[0], event[3]);
        }
    }

    /**
     * 
     * @param {string} url 
     * @param {string} params 
     */
    async fetch(url, params)
    {
        await fetch(url, 
        {
            method: 'POST',
            body: JSON.stringify(params)
        });
    }

    /**
     * This will sign in the user.
     */
    signIn()
    {
        // user is the app
        const url = '/auth/login';
        let params = 'userId=' + data.userId;

        this.fetch(url, params);
    }

    /**
     * This will sign out the user.
     */
    signOut()
    {
        // user is leaving the app

        const url = '/auth/logout';
        let params = 'userId=' + data.userId;

        if(!('sendBeacon' in window.navigator))
        {
            // normal ajax request here
            this.fetch(url, params);
            return;
        }

        // use a beacon for a more modern request the does not return a response
        navigator.sendBeacon(url, new URLSearchParams(params));
    }
}

如果某些数据未保存或类似情况,它可用于提醒用户。 此方法在选项卡关闭或浏览器关闭或网页刷新时有效。

除非用户不与网页交互,否则谷歌浏览器不会交互,这是由于恶​​意网站造成的......这种情况下,如果您不点击进入文本区域,则不会弹出。

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <form>
        <textarea placeholder = "Write...."></textarea>
    </form>
    <script type="text/javascript">
        window.addEventListener('beforeunload', function (e) {
            e.returnValue = '';
        });
    </script>
</body>
</html>

我的方法将遵循以下原则:

  1. 使用onpopstate监听 url 的变化,并将 sessionStorage 变量设置为 1
  2. 监听页面加载并将 sessionStorage 变量设置为 0
  3. beforeunload 上,检查变量是否为 0。如果是,则表示用户正在关闭并且没有更改 url。

这仍然是一个迂回的路要走,但对我来说很有意义

正如@jAndy 提到的,没有正确的javascript 代码来检测正在关闭的窗口。 我从@Syno 的提议开始。

我曾经遇到过这样的情况,只要您按照这些步骤操作,您就可以检测到它。
我在 Chrome 67+ 和 Firefox 61+ 上对其进行了测试。

var wrapper = function () { //ignore this

var closing_window = false;
$(window).on('focus', function () {
    closing_window = false; 
   //if the user interacts with the window, then the window is not being 
   //closed
});

$(window).on('blur', function () {

    closing_window = true;
    if (!document.hidden) { //when the window is being minimized
        closing_window = false;
    }
    $(window).on('resize', function (e) { //when the window is being maximized
        closing_window = false;
    });
    $(window).off('resize'); //avoid multiple listening
});

$('html').on('mouseleave', function () {
    closing_window = true; 
    //if the user is leaving html, we have more reasons to believe that he's 
    //leaving or thinking about closing the window
});

$('html').on('mouseenter', function () {
    closing_window = false; 
    //if the user's mouse its on the page, it means you don't need to logout 
    //them, didn't it?
});

$(document).on('keydown', function (e) {

    if (e.keyCode == 91 || e.keyCode == 18) {
        closing_window = false; //shortcuts for ALT+TAB and Window key
    }

    if (e.keyCode == 116 || (e.ctrlKey && e.keyCode == 82)) {
        closing_window = false; //shortcuts for F5 and CTRL+F5 and CTRL+R
    }
});

// Prevent logout when clicking in a hiperlink
$(document).on("click", "a", function () {
    closing_window = false;
});

// Prevent logout when clicking in a button (if these buttons rediret to some page)
$(document).on("click", "button", function () {
    closing_window = false;

});
// Prevent logout when submiting
$(document).on("submit", "form", function () {
    closing_window = false;
});
// Prevent logout when submiting
$(document).on("click", "input[type=submit]", function () {
    closing_window = false;
});

var toDoWhenClosing = function() {

    //write a code here likes a user logout, example: 
    //$.ajax({
    //    url: '/MyController/MyLogOutAction',
    //    async: false,
    //    data: {

    //    },
    //    error: function () {
    //    },
    //    success: function (data) {
    //    },
    //});
};


window.onbeforeunload = function () {
    if (closing_window) {
        toDoWhenClosing();
    }
};

};

试试这个,我相信这对你有用。

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type='text/javascript'>
    $(function() {

        try{
            opera.setOverrideHistoryNavigationMode('compatible');
            history.navigationMode = 'compatible';
        }catch(e){}

        function ReturnMessage()
        {
            return "wait";
        }

        function UnBindWindow()
        {
            $(window).unbind('beforeunload', ReturnMessage);
        }

        $(window).bind('beforeunload',ReturnMessage );
    });
</script>
<script type="text/javascript" language="Javascript">

function DetectBrowserExit()
{
   alert('Execute task which do you want before exit');
}

window.onbeforeunload = function(){ DetectBrowserExit(); }

</script>

我已经在以下Web浏览器中测试了此脚本:目前,Opera Web浏览器不支持onBeforeUnload事件。 Internet Explorer Mozilla Firefox谷歌浏览器Safari

尝试这个。 它会起作用的。 jquery 卸载方法已弃用。

window.onbeforeunload = function(event) {
    event.returnValue = "Write something clever here..";
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM