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