web-dev-qa-db-ja.com

ユーザーがサイトの複数のタブを開いているかどうかを検出できますか?

私はサイト登録プロセス全体について考えています。

ユーザーがサイトにアクセスしてサインアップし、メールを送信したことを伝え、メールアドレスを確認する必要があるとします。だから彼はヒット Ctrl+T、ポップアップで新しいタブを開き、Gmail favボタンを押します。長いウェルカムメールの単語は読みませんが、最初に表示されるリンクをクリックします。 Gmailはさらに別のタブでサイトを開きます...

彼は、サイトを開くために2つのタブを必要とせず、必要もありません。登録するまで、アクセスを禁止した警告ページを表示したいだけです。

どうしようか?本当に良い仕事をしてくれたサイトを1つ(ただし、それが何だったか忘れてしまいました)見ました。

ユーザーが既にサイトへのタブを開いているかどうかを検出できれば、いいかもしれません。新しい確認タブを自動的に閉じるか、閉じることができると伝えて、他のタブに戻ることができます。 (これで更新してログインしました)。

または、迷惑な「メールを確認してください」というメッセージが表示されたとき、彼は直接自分のメールにアクセスし、サイトを自分のメールに置き換えます。その場合、タブを閉じたくありませんが、以前の場所を保存して、そこに再度リダイレクトすることはできますか?

とにかく、それは単なるユースケースです...問題はまだ残っています。 ユーザーが既にサイトへのタブを開いているかどうかを検出できますか?


この質問は、ではありませんユーザーがいつを完了したかを検出する方法についてですサインアッププロセス。 Ajaxポーリングまたは彗星はその問題を解決できます。具体的には、ユーザーが既にサイトに開いているタブを持っているかどうかを知りたいです。

33
mpen

私はここでのパーティーにかなり遅れています(1年以上)が、信じられないほど簡単でエレガントなソリューション(そしておそらくあなたが見たそのWebサイトが使用していたもの)を見逃していることに気づかざるを得ませんでした。

JavaScriptを使用すると、現在開いているウィンドウの名前を変更できます。

window.name = "myWindow";

次に、確認メールを送信するときに、次のようにします(HTMLメールを送信していると想定)。

<a href="verificationlink.php" target="myWindow">Verify</a>

これにより、ウェブサイトが既に読み込まれているウィンドウ内でverificationLinkが開くはずです。すでに閉じている場合は、指定されたウィンドウ名で新しいタブが開きます。

41
88ad

元のタブからAJAXリクエストを[〜#〜] x [〜#〜]秒ごとに送信して、サーバーからリクエストを受け取ったかどうかをサーバーに尋ねることができますEメール。

2番目のタブを自動的に閉じることはできませんが、X秒後に最初のタブから聞いたかどうかをサーバーに尋ねることができます。

6
SLaks

ユーザーが別のタブ、別のウィンドウ、または別のブラウザーを開いたときに、ページ機能を停止できます

$(window).blur(function(){
    // code to stop functioning or close the page  
});
6
user2511671

ここにあるのは少し異なるユースケースですが、サイトが別のタブでアクセスされているかどうかを検出します。この場合、コールセンターのページを使用するユーザーを1つのタブのみに制限したいと考えました。それはうまく機能し、純粋にクライアント側です。

// helper function to set cookies
function setCookie(cname, cvalue, seconds) {
    var d = new Date();
    d.setTime(d.getTime() + (seconds * 1000));
    var expires = "expires="+ d.toUTCString();
    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}

// helper function to get a cookie
function getCookie(cname) {
    var name = cname + "=";
    var decodedCookie = decodeURIComponent(document.cookie);
    var ca = decodedCookie.split(';');
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

// Do not allow multiple call center tabs
if (~window.location.hash.indexOf('#admin/callcenter')) {
    $(window).on('beforeunload onbeforeunload', function(){
        document.cookie = 'ic_window_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
    });

    function validateCallCenterTab() {
        var win_id_cookie_duration = 10; // in seconds

        if (!window.name) {
            window.name = Math.random().toString();
        }

        if (!getCookie('ic_window_id') || window.name === getCookie('ic_window_id')) {
            // This means they are using just one tab. Set/clobber the cookie to prolong the tab's validity.
            setCookie('ic_window_id', window.name, win_id_cookie_duration);
        } else if (getCookie('ic_window_id') !== window.name) {
            // this means another browser tab is open, alert them to close the tabs until there is only one remaining
            var message = 'You cannot have this website open in multiple tabs. ' +
                'Please close them until there is only one remaining. Thanks!';
            $('html').html(message);
            clearInterval(callCenterInterval);
            throw 'Multiple call center tabs error. Program terminating.';
        }
    }

    callCenterInterval = setInterval(validateCallCenterTab, 3000);
}
5
Anthony Vipond

ユーザーはサーバーでセッションを維持します。登録する前にユーザーの場所を保存しないでください。ユーザーが登録を確認したら、場所をセッションから読み取り、そのページにリダイレクトします。タブマジックは必要ありません。それは確かに私がサインアッププロセスから期待するものではありません。

2
spender

ジョンの答えを具体化するために、プレーンなJSとlocalStorageを使用し、現在開いているタブの数でDOMを更新する実用的なソリューションを次に示します。このソリューションは、1つのブラウザー内の特定のドメインで開いているタブ/ウィンドウの数を検出しますが、異なるブラウザー間でカウントを維持しないことに注意してください。

ストレージイベントを使用して、ページを更新する必要なく、開いているすべてのタブ/ウィンドウ全体でカウントを同期させます。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title></title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="robots" content="noindex, nofollow">
<meta name="googlebot" content="noindex, nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
(function() {
    var stor = window.localStorage;
    window.addEventListener("load", function(e) {
        var openTabs = stor.getItem("openTabs");
        if (openTabs) {
            openTabs++;
            stor.setItem("openTabs", openTabs)
        } else {
            stor.setItem("openTabs", 1)
        }
        render();
    })
    window.addEventListener("unload", function(e) {
        e.preventDefault();
        var openTabs = stor.getItem("openTabs");
        if (openTabs) {
            openTabs--;
            stor.setItem("openTabs", openTabs)
        }
        e.returnValue = '';
    });
    window.addEventListener('storage', function(e) {
        render();
    })

    function render() {
        var openTabs = stor.getItem("openTabs");
        var tabnum = document.getElementById("tabnum");
        var dname = document.getElementById("dname");
        tabnum.textContent = openTabs;
        dname.textContent = window.location.Host
    }
}());
</script>
</head>
<body>
<div style="width:100%;height:100%;text-align:center;">
    <h1 >You Have<h1>
        <h1 id="tabnum">0</h1>
    <h1>Tab(s) of <span id="dname"></span> Open</h1>
</div>
</body>
</html>
2

他の回答に追加するには:localStorageを使用することもできます。 「openedTabs」のようなエントリがあります。ページが開いたら、この数を増やします。ユーザーがページを離れたら、ページを減らします。

1
John

各タブのlocalstorageにデータを保存して同じ数を数えることで、開いたサイトのタブの数を追跡することができます。私は githubリポジトリ を作成しました。ユーザーが開いたウェブサイト。

これを使用するには、ページにtab-counter.jsを含めてください。開いているタブの数の追跡が開始されます。

console.log(tabCount.tabsCount());
1
Shubanker