[英]Detect browser or tab closing
是否有任何跨瀏覽器 JavaScript/jQuery 代碼來檢測瀏覽器或瀏覽器選項卡是否正在關閉,但不是由於單擊了鏈接?
如果我理解正確,您想知道選項卡/窗口何時有效關閉。 好吧,AFAIK 在 JavaScript 中檢測到這一點的唯一方法是使用onunload
或onbeforeunload
事件。
不幸的是(或幸運的是?),當您通過鏈接或瀏覽器的后退按鈕離開站點時,也會觸發這些事件。 所以這是我能給出的最好的答案,我認為你不能在 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代碼來檢測瀏覽器或瀏覽器選項卡是否已關閉,但不是由於單擊鏈接而導致的?
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());
}
});
大家好,我能夠通過使用瀏覽器本地存儲和時間戳來實現“檢測瀏覽器和選項卡關閉事件”點擊。 希望大家都可以通過使用此解決方案來解決您的問題。
經過我的初步研究,我發現當我們關閉瀏覽器時,瀏覽器會一一關閉所有選項卡以完全關閉瀏覽器。 因此,我觀察到關閉標簽之間的時間延遲非常小。 所以我把這個時間延遲作為我的主要驗證點,並能夠實現瀏覽器和標簽關閉事件檢測。
我在 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>
我的方法將遵循以下原則:
這仍然是一個迂回的路要走,但對我來說很有意義
正如@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.