ブラウザまたはタブのクローズを検出する


306

リンクがクリックされたためではなく、ブラウザーまたはブラウザーのタブが閉じられているかどうかを検出するクロスブラウザーJavaScript / jQueryコードはありますか?


1
:この質問に対する私の答えを参照してくださいstackoverflow.com/questions/3735198/...
ニヴァス


sessionStorage プロパティを使用します。ブラウザを閉じると期限切れになります。w3schools.com/jsref/prop_win_sessionstorage.asp
csandreas1

この答えをチェックしてください!私はそれが非常に便利であるとわかり、ほとんどの場合をカバーしています。stackoverflow.com/a/26275621/7192927
SukanyaPai

回答:


273

私が正しく理解できたら、いつタブ/ウィンドウが効果的に閉じられるかを知りたいと思います。そうですね、AFAIKはJavascriptその種のものを検出する唯一の方法ですonunloadonbeforeunloadイベント。

残念なことに(または幸いなことに?)、これらのイベントは、サイトlinkまたはブラウザの戻るボタンを離したときにも発生します。だから、これが私ができる最良の答えです。JavaScriptで純粋に純粋に検出できるとは思いませんclose。私がここで間違っている場合は修正してください。


39
正しい。ページがアンロードされたときのみ検出でき、ウィンドウが閉じられたときは検出できません。また、onbeforeunloadは非標準であるため、すべてのブラウザーでサポートされているわけではありません。
Guffa

7
「閉じる」機能も使用したかったのですが、ユーザーがF5キーを押して画面を更新する場合があることに気付きました。私の「閉じる」ハンドラはそのような更新時に呼び出されるため、これは私が必要とする方法でそれを使用できないことを意味します(これは真の「閉じるタブまたはウィンドウ」でした)...いまいましい、新しいイベントモデルが必要ですこのすべてのために!
ジーク2013

1
chrome / operaでは動作しなくなりました... chromestatus.com/feature/5349061406228480
Samir Seetal

2
もちろん、これはまだ機能Stringonbeforeunloadます。カスタム戻り値をから削除しただけです。したがって、アンロードする前にカスタムメッセージを表示することはできなくなりました。
jAndy

@jAndy @Guffaどのウィンドウが起動したunloadかを知るにはどうすればよいですか?
Egor Dudyak

125

Firefoxドキュメントから

何らかの理由で、Webkitベースのブラウザはダイアログボックスの仕様に準拠していません。ほぼクロスワーキングの例は、以下の例に近いものになります。

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

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

すべてのブラウザを処理するためのこの例。


2
これが私のChromeブラウザで機能する唯一のソリューションです。他の人は試しませんでした。
チェイスロバーツ

4
ええ、私は多くのソリューションを試してみましたが、最後にこれを組み合わせてベストアンサーを組み合わせて、すべてのブラウザーでテストしています。
mohamed-ibrahim 2014年

1
このメソッドは、タブのみが開かれているFirefox(> = ver。44)を使用している場合、タブを閉じると完全に機能しません。
Rajkishore 2016年

現在、すべての最新バージョンのブラウザーを使用して、Chrome、Firefox、Opera、IE11、およびEdgeのタブを閉じる、ナビゲートまたは閉じるときにプロンプ​​トが機能し、Chromeがすべてのタブを閉じる以外の複数のタブを開いている場合にも機能しますプロンプトなしで、少なくとも私のマシンでは。
ティエリー

問題の定義どおりに適切な配布を行わない。これは、ブラウザのクローズまたはタブのクローズだけでなく、ページ離脱イベントでもトリガーされました
Sunil Acharya

48

シンプルなソリューション

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

7
これはどんな魔術ですか?(y)すべてのブラウザで動作しますか?クロームでうまく機能する
Ziv Weissman

5
ページを更新すると発生します。それが私の唯一の問題です。
Leo Leoncio 2017

6
このソリューションは、FirefoxとChromeでは機能しません
Mehdi Dehghani

これは、ブラウザのクローズまたはタブのクローズだけでなく、ページ離脱イベントでもトリガーされました
Sunil Acharya

20
<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で機能します。タブを閉じている場合、または1つのタブのみでブラウザーを閉じている場合


2
y A。しかし、ie8、firefoxなどの複数のタブブラウザーの場合 これを使用して問題がありますか?
コメッタ

IE9でこのコードを使用すると、ユーザーがマウスで戻る、進む、または更新ボタンをクリックしたときに、このメッセージがポップアップ表示されることがわかりました。
スティーブウォーサム

2007年に同様のソリューションを実装したことをお知らせします。このソリューションは、約1週間前からIE9で動作しなくなりました。それはずっと前にタブ付きブラウザで機能しなくなった(またはおそらく機能しなかった)。
tjfo 2013

Chromium / Ubuntuでコンソールを挿入window.onunload = "alert('wait')"してwindow.onbeforeunload = "alert('wait... chrome!')"使用しましたが、タブを閉じてもどちらも起動しませんでした。
アイスウォーター2014

window.onunload = "alert('wait')"そして、そのようなものは実際には機能しないはずです。「関数は、EventオブジェクトのreturnValueプロパティに文字列値を割り当て、同じ文字列を返す必要があります」。MDNの記事を
Dmitry Vyprichenko 2014年

8

ブラウザまたはタブが閉じたときにユーザーを自動的にログアウトする必要がありましたが、ユーザーが他のリンクに移動したときはログアウトしませんでした。また、それが発生したときに確認プロンプトを表示したくありませんでした。これにしばらく、特にIEとEdgeで苦労した後、この回答によるアプローチを基にした後、私がやったこと(IE 11、Edge、Chrome、Firefoxでの作業を確認)

まず、beforeunloadJSのイベントハンドラーでサーバーのカウントダウンタイマーを開始します。IEとEdgeが正しく動作するには、ajax呼び出しが同期している必要があります。を使用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()メソッドでログアウトをキャンセルしています。


これはうまくいきました。「async:false」にする理由はありますか?これにより、同期AJAX呼び出しが廃止されたという警告が生成されます。ありがとう!
cat_in_hat 2018

1
回答で述べたように、@ FoundWaldoExceptionは、これがIEおよびEdgeで機能するために、非同期をfalseに設定する必要があることを発見しました。
Ionian316 2018

ログアウトをキャンセルするにはどうすればよいOnActionExecutedですか?
Kiquenet 2018

@Kiquenetコードで開始されたタイマーを停止するだけです。
Ionian316

6

申し訳ありませんが、既存の回答の1つにコメントを追加することはできませんでしたが、一種の警告ダイアログを実装したい場合に備えて、イベントハンドラー関数には引数-イベントがあることをお伝えしたいと思います。あなたのケースでは、event.preventDefault()を呼び出してページを自動的に離れることを禁止し、独自のダイアログを発行できます。私はこれを、標準の醜くて安全でないalert()を使用するよりも優れたオプションと考えています。私は、kendoWindowオブジェクト(TelerikのKendo UI、kendoGridとkendoEditorを除いて、ほぼ完全にオープンソースです)に基づいて、独自のダイアログボックスセットを個人的に実装しました。jQuery UIからダイアログボックスを使用することもできます。ただし、そのようなことは非同期であり、ハンドラーをすべてのボタンのonclickイベントにバインドする必要がありますが、これはすべて実装するのが非常に簡単です。

ただし、実際のクローズイベントの欠如はひどいことに同意します。たとえば、実際のクローズの場合にのみバックエンドでセッション状態をリセットしたい場合、それは問題です。


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>

5

イベントはありませんがwindow.closed、この記事の執筆時点ですべての主要なブラウザーでサポートされているプロパティがあります。したがって、本当に知る必要がある場合は、ウィンドウをポーリングしてそのプロパティを確認できます。

if(myWindow.closed){do things}

注:何でもポーリングすることは、通常、最善の解決策ではありません。window.onbeforeunload可能であればイベントは唯一の注意点は、あなたが離れて移動する場合、それはまた、発火するということで、使用すべきです。


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

9
これはFirefoxまたはChromeでは機能しません。beforeunloadアラートを表示したい場合は試してください。このように:$(window).on('beforeunload', function(){ alert ('Bye now')});
AdrianoRR 2013年

5
jQueryのドキュメントのとおり
katzmopolitan

4

それを使ってみてください:

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;
});
});

3

はすべてのブラウザで動作する方法を見つけました。

次のバージョンでテスト済み:Firefox 57、Internet Explorer 11、Edge 41、最新のChromeの1つ(私のバージョンは表示されません)

: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
            }
        };

  });

ブラウザを閉じるための別のハンドラがどのように追加されるか。これには別のイベントがあるとは思わない。
blazehub 2018

これはとても役に立ちました。実際のハイパーリンクに対してのみ発火するようにAアンカーを調整する必要がありました。それ以外の場合、ブートストラップタブをクリックするとめちゃくちゃになりました:$( "a [href!= '']")。not( '[href ^ = "#"]')。bind( "click"、function()
Ken Forslund

3

まだ誰も言及していないため(8年以上後):WebSocketは、閉じたタブを検出するもう1つの効果的な方法です。タブが開いていてホストを指している限り、クライアントはホストへのアクティブなWebSocket接続を維持できます。

警告:このソリューションは、WebSocketがすでに行っていることからの追加の大きなオーバーヘッドを必要としない場合にのみ、プロジェクトでのみ実行可能であることに注意してください。

適切なタイムアウト期間内(たとえば2分)に、サーバー側はWebSocketが切断された後にクライアントが去ったと判断し、アップロードされた一時ファイルの削除など、必要なアクションを実行できます。(私の非常に特殊なユースケースでは、私の目標はlocalhostアプリサーバーを終了することでした、WebSocket接続がドロップしてすべてのCGI / FastCGIアクティビティが終了してから3秒後にことでした。他のキープアライブ接続は影響しません。)

この回答で推奨されているように)onunloadイベントハンドラーがビーコンで適切に機能するようにするのに問題がありました。タブを閉じるとビーコンはトリガーされないように見え、タブを開くと問題を引き起こす可能性のある方法でビーコンがトリガーされました。WebSocketは、タブが閉じられ、アプリケーション内のページを切り替えると遅延ウィンドウ内で新しいWebSocket接続が開かれるのとほぼ同時に接続が閉じられるため、実行中に発生した問題をより明確に解決しました。


2
それは大丈夫です。しかし、それを処理するためのコードや手順を共有することはできませんか?それなしでは私のような初心者には理解できません
P Satish Patro

実際、最初のコメントでははっきりしていませんでした。Webソケットがわかりません。だから、私はただ処理する方法を見たかっただけです
Pサティシュパトロ

1
上記の私のコメントのリンクは、いくつかのWebSocket JSコードの例を示しています。クライアントのJS部分は簡単な部分です。このコードは、アプリケーションサーバー全体を適切なタイミングで終了する必要がある、非常に具体的な使用例です。WebSocketサーバーの作成方法は自由であり、すべてを接続するにはサーバー側の設定が必要です(多くの人がNginxフロントエンド付きのNodeJSバックエンドを好みます)。TCP / IP対応サーバーを作成することは、コメントでの議論には適さない複雑なトピックであり、この特定の問題を検出するためだけにセットアップするのはやりすぎです。
CubicleSoft

2
//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リンク

こんにちは。ブラウザのローカルストレージとタイムスタンプを使用して、「ブラウザとタブを閉じるイベントの検出」クリックを達成できました。このソリューションを使用することで、皆さんの問題が解決されることを願っています。

最初の調査の結果、ブラウザーを閉じると、ブラウザーがすべてのタブを1つずつ閉じてブラウザーを完全に閉じることがわかりました。したがって、タブを閉じるまでの時間遅延はほとんどないことがわかりました。そのため、この時間遅延を主な検証ポイントとして、ブラウザーとタブのクローズイベントの検出を実現できました。

Chromeブラウザバージョン76.0.3809.132でテストしましたが、動作していました

:)あなたが私の答えが役に立ったと思ったら投票してください...


さて、これは私にアイデアを与えました。ログイン後、イベントの前に、unloadのタイムスタンプとローカルストレージの10秒を設定しています。ロード時に時間が経過したかどうかを確認してから、ログインページにリダイレクトします。ありがとう:)
G4BB3R

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

2
here also can be string, that will be shown to the userFirefoxでは機能しませんが、
Chrome

戻り値(文字列)は、MSIE <= 11でのみ表示されます。そのため、基本的に他のすべてのブラウザでは役に立ちません。
OSWorX 2019年

1

このような「アンロード」イベントのイベントハンドラーでwindow.closedの助けを借りてそれをチェックすることは可能ですが、タイムアウトの使用が必要です(したがって、遅延が発生したり、ウィンドウが閉じられない場合、結果は保証されません):

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!';
  }
}

1

私は上記のソリューションをすべて試しましたが、特にプロジェクトにいくつかの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) {

                                        }
               });
       }

0
window.onbeforeunload = function ()
{       

    if (isProcess > 0) 
    {
        return true;       
    }   

    else
    { 
        //do something      
    }
}; 

この関数は、ブラウザーでのプロセス中にウィンドウを閉じるかページを更新すると、確認ダイアログボックスを表示します。この関数はすべてのブラウザーで機能します。ajaxプロセスでisProcess varを設定する必要があります。


セットisProcessの完全なサンプル?
Kiquenet 2018

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

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

実際、ユーザーがタブを閉じた場合にのみ確認メッセージを表示したかったのです。これは私のために働いています。しかし、同じページのリンクをクリックすると確認メッセージが表示されるという問題に直面しています。萌えについては、w3schools.com / code / tryit.asp?filename
Mohammed

1
なにsendkeylog
Kiquenet 2018

0

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

};


1
JavaScriptコードに問題があります。私が最初に気づいたのはresize、ウィンドウがぼやけていると、常にバインドし続けるということです。100倍ぼやけた場合、リスナーは100人になり、ブラウザの速度が低下します。
カイル

$(window).off( 'resize')を配置しましたが、これで十分でしょうか?
ブルーノエンリケ

技術的には、jQueryを介して他の場所に追加された他のハンドラーも削除されます。
カイル

-2

これを試してください、これはあなたのために働くと確信しています。

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

-3

これを試して。それが動作します。jquery unloadメソッドは非推奨です。

window.onbeforeunload = function(event) {
    event.returnValue = "Write something clever here..";
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.