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

评论

请参阅我对这个问题的回答:stackoverflow.com/questions/3735198/…

您可以! stackoverflow.com/questions/42706209/…

使用sessionStorage属性,它将在浏览器关闭后过期。 w3schools.com/jsref/prop_win_sessionstorage.asp

检查这个答案!我发现它非常有用,并且涵盖了大多数情况。 stackoverflow.com/a/26275621/7192927

#1 楼

如果我正确地理解了您,您想知道何时有效关闭标签页/窗口。好吧,AFAIK在Javascript中检测这种东西的唯一方法是onunloadonbeforeunload事件。

(不幸的是,或者幸运的是,当您离开某个站点通过link或浏览器的后退按钮。因此,这是我能给出的最佳答案,我认为您无法在Javascript中原生检测到纯close。如果我错了,请纠正我。

评论


正确。您只能检测何时卸载页面,而不是何时关闭窗口。另外,onbeforeunload是非标准的,因此并非所有浏览器都支持。

–古法
10-10-8在8:45

我也想使用“关闭”功能,但是注意到我的用户偶尔会按F5刷新屏幕。由于我的“关闭”处理程序是在此类刷新时调用的,因此这意味着我无法按需要的方式使用它(这是真正的“关闭选项卡或窗口”)...该死,我们需要一个新的事件模型对于所有这一切!

–each
13年4月25日在17:06

不再适用于chrome / opera ... chromestatus.com/feature/5349061406228480

– Samir Seetal
17年6月15日在10:10

当然,这仍然会起作用,他们只是从onbeforeunload中删除了自定义String返回值。因此,现在您将不再能够在卸载之前显示自定义消息。

– jAndy
17年6月16日在15:37

@jAndy @Guffa我如何找出哪个窗口被卸载了?

– Egor Dudyak
2月27日18:01



#2 楼

来自MDN文档
由于某些原因,基于Webkit的浏览器不遵循该对话框的规范。一个几乎可以相互工作的示例与下面的示例非常接近。
window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";

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

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

评论


这是适用于我的Chrome浏览器的唯一解决方案。我没有尝试任何其他人。

–Chase Roberts
2014年1月7日,0:10

是的,我尝试了许多解决方案,最后附带了此解决方案,结合使用可获得最佳答案,并在所有浏览器上进行了测试。

–mohamed-ibrahim
2014年1月8日在11:08

在仅打开选项卡的情况下使用firefox(> = ver。44)时,此方法在选项卡关闭时效果不理想。

–Rajkishore
16年5月24日在15:04



从今天开始,使用所有最新版本的浏览器,在关闭选项卡,导航或关闭Chrome,Firefox,Opera,IE11和Edge的浏览器时,提示均有效,并且当您打开多个选项卡(Chrome会关闭所有选项卡的Chrome)时,提示也适用至少在我的机器上没有提示。

–蒂埃里(Thierry)
18-09-27在15:24

没有按照问题的定义进行适当的分配。这还会触发页面离开事件,不仅浏览器关闭或标签页关闭

– Sunil Acharya
18/12/25在8:20

#3 楼

简单解决方案

window.onbeforeunload = function () {
    return "Do you really want to close?";
};


评论


这是什么魔法? (y)可以在所有浏览器上使用吗?在chrome上效果很好

– Ziv Weissman
16/09/14在14:20



刷新页面时触发。那是我唯一的问题。

– Leo Leoncio
17年9月25日在14:05

Firefox和Chrome不再支持该解决方案

– Mehdi Dehghani
18年1月20日在9:05



这还会触发页面离开事件,不仅浏览器关闭或标签页关闭

– Sunil Acharya
18/12/25在8:20

#4 楼

<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中有效

评论


嗯但是对于多个标签浏览器,例如ie8,firefox。使用这个有问题吗?

– cometta
2011年4月9日在5:03

事实证明,当用户使用鼠标单击后退,前进或刷新按钮时,在IE9中使用此代码将导致此消息弹出。

–史蒂夫·沃瑟姆(Steve Wortham)
2012年3月13日在16:20

请注意,我们早在2007年就实施了类似的解决方案。大约一周前,该解决方案在IE9中不再起作用。很久以前,它在选项卡式浏览器中停止运行(或可能从未运行过)。

– tjfo
13年7月17日在16:17

我使用Chromium / Ubuntu中的控制台注入了window.onunload =“ alert('wait')”和window.onbeforeunload =“ alert('wait ... chrome!')”,但在关闭标签页时均未触发。

–冰水
2014年4月15日下午3:34

window.onunload =“ alert('wait')”之类的东西应该不会真正起作用。 “该函数应该为事件对象的returnValue属性分配一个字符串值,并返回相同的字符串”。请看一下MDN文章

– Dmytro Vyprichenko
2014年5月21日在9:33



#5 楼

我需要在浏览器或选项卡关闭时自动注销用户,但在用户导航到其他链接时不需要注销。我也不想在出现这种情况时显示确认提示。经过一段时间的努力之后,尤其是在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()方法注销。

评论


这很棒。您是否有理由设置“异步:错误”?这将生成警告,已弃用同步AJAX调用。谢谢!

– cat_in_hat
18年7月16日在13:49

如答案中所述,@ FoundWaldoException我发现需要将async设置为false才能使其在IE和Edge中工作。

–爱奥尼亚人316
18年7月23日在14:38

如何取消注销OnActionExecuted?

– Kiquenet
18/12/11在14:25

@Kiquenet只需停止在代码中启动的计时器即可。

–爱奥尼亚人316
18/12/12在16:09

#6 楼

对于类似的任务,可以使用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>


评论


卓见。用于在多个页面上有效工作的在线计时器。到目前为止,我只知道localStorage。

–AndréR. Kohl
9月2日13:39

#7 楼

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

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

#8 楼

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

if(myWindow.closed){do things}

注意:
轮询通常不是最佳解决方案。如果可能的话,应该使用window.onbeforeunload事件,唯一的警告是,如果您离开,也会触发该事件。

#9 楼

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


评论


这不适用于Firefox或Chrome。如果要显示警报,请尝试beforeunload。像这样:$(window).on('beforeunload',function(){alert('Bye now')});;

– AdrianoRR
2013年3月12日21:51



按照jQuery docs“大多数浏览器都会忽略对alert(),confirm()和提示符()的调用” api.jquery.com/unload

– katzmopolitan
15年11月23日在18:15

#10 楼

我找到了一种方法,可以在所有浏览器上使用。

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


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


  $(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
            }
        };

  });


评论


如何为浏览器关闭添加单独的处理程序。.我认为我们没有为此单独的事件。

–blazehub
18年8月15日在3:37

这非常有帮助。我需要将A锚点调整为仅对实际的超链接触发。否则,单击引导程序选项卡会将其弄乱:$(“ a [href!='']”)。not('[href ^ =“#”]')。bind(“ click”,函数()

–肯·弗斯伦德
19-10-11在21:27



#11 楼

尝试使用它:

window.onbeforeunload = function (event) {
    var message = 'Important: Please click on \'Save\' button to leave this page.';
    if (typeof event == 'undefined') {
        event = window.event;
    }
    if (event) {
        event.returnValue = message;
    }
    return message;
};

$(function () {
    $("a").not('#lnkLogOut').click(function () {
        window.onbeforeunload = null;
    });
    $(".btn").click(function () {
        window.onbeforeunload = null;
});
});


#12 楼

window.addEventListener("beforeunload", function (e) {
 var confirmationMessage = "tab close";

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


评论


实际上,我只想在用户关闭选项卡时显示确认消息。这对我有用。但是我面临一个问题,如果我单击同一页面上的任何链接,还会显示确认消息.moe的参考信息为:w3schools.com/code/tryit.asp?filename=FEK2KWUN9R8Z @Tunaki

–穆罕默德
17年4月12日在9:50



什么是sendkeylog?

– Kiquenet
18/12/11在13:32

#13 楼

由于尚无人提及它(8年后):WebSocket可以是检测关闭的选项卡的另一种有效方法。只要该选项卡处于打开状态并指向主机,客户端就可以维持与主机的活动WebSocket连接。

注意:请注意,该解决方案仅对以下情况才可行: WebSocket不需要您已经在做的任何额外的额外开销。

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

我在使onunload事件处理程序与信标一起正常工作时遇到了问题(按照此答案的建议)。关闭选项卡似乎没有触发信标,而打开选项卡则以可能导致问题的方式触发了它。 WebSocket解决了我碰到的问题,因为连接大致在选项卡关闭的同时关闭,并且在应用程序内切换页面只是在延迟窗口内很好地打开了一个新的WebSocket连接。

评论


没关系。但是,您不能共享任何代码或过程来处理它吗?没有那个,对于像我这样的菜鸟无法理解

–P Satish Patro
19年3月1日在12:00

实际上,我的第一句话不清楚。我不知道网络套接字。所以,我只想看看如何处理

–P Satish Patro
19-3-4在5:39



我上面的评论中的链接转到一些示例WebSocket JS代码。客户端JS部分是简单的部分。该代码是针对我非常特定的用例的,尽管我需要及时终止整个应用程序服务器。如何编写WebSocket服务器取决于您,并且需要服务器端配置来连接所有内容(很多人更喜欢带有Nginx前端的NodeJS后端)。编写启用TCP / IP的服务器是一个复杂的主题,不适合在评论中进行讨论,而仅设置一个服务器来检测此特定问题就太过分了。

– CubicleSoft
19 Mar 4 '19 at 7:12

#14 楼

window.onbeforeunload = function() {
  console.log('event');
  return false; //here also can be string, that will be shown to the user
}


评论


这里也可以是字符串,在Firefox上不会显示给用户,但是在chrome上却可以显示给用户...

– TrySpace
2014年2月13日14:38在

任何返回值(字符串)仅在MSIE <= 11中显示。因此,对于所有其他浏览器基本上没有用。

– OSWorX
19 Mar 17 '19在8:33

#15 楼

//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 Link

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

经过初步研究,我发现当我们关闭浏览器时,浏览器将逐个关闭所有选项卡以完全关闭浏览器。 。因此,我观察到在关闭标签之间几乎没有时间延迟。因此,我将此时间延迟作为主要验证点,并能够实现浏览器和选项卡关闭事件检测。

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

:)如果您认为我的回答有帮助,请投票。...

评论


好吧,这给了我一个主意。我设置了一个时间戳,并在登录后以及在事件卸载前设置了10秒的本地存储时间。在加载时,我验证时间是否过去,然后重定向到登录页面。谢谢 :)

– G4BB3R
2月20日18:33

#16 楼

我已经尝试了所有上述解决方案,但没有一个真正适合我,特别是因为项目中有一些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) {

                                        }
               });
       }


#17 楼

window.onbeforeunload = function ()
{       

    if (isProcess > 0) 
    {
        return true;       
    }   

    else
    { 
        //do something      
    }
}; 


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

评论


设置isProcess的完整样本?

– Kiquenet
18/12/11在14:18

#18 楼

可以在像这样的'unload'事件中在事件处理程序中借助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!';
  }
}


#19 楼

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

onunload仅在页面关闭时执行:

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

我测试了它在chrome上,即使在页面刷新和导航到其他页面时也不会执行。
由于javascript执行代码的方式,警报可能不会显示..但是肯定会击中代码。

#20 楼

正如@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();
    }
};


};

评论


您的JavaScript代码中有一些问题。我注意到的第一件事是,当窗口模糊时,您将不断绑定以调整大小。如果模糊100倍,那么您将有100个侦听器,这最终会降低浏览器的速度。

–凯尔
18年7月27日在20:59

我放了一个$(window).off('resize'),够了吗?

–布鲁诺·亨里克(Bruno Henrique)
18年7月27日在21:11



从技术上讲,但它还会删除通过jQuery在其他位置添加的所有其他处理程序。

–凯尔
18年7月28日在0:51

#21 楼

试试吧,
我确定这对您有用。

<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>


#22 楼

尝试这个。会的。不建议使用jquery卸载方法。

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