web-dev-qa-db-ja.com

JavaScriptを使用してブラウザのタブがすでに開いているかどうかを知る方法は?

2つのブラウザータブがすでに開いているかどうかを確認または確認する方法、およびそれらのタブが開いている場合、ユーザーは、「URLがすでに開いている」という警告ボックスまたはメッセージボックスを受け取ります(ピュア/ネイティブJavaScriptのようなものですか?)。このブラウザタブには外部Webサイトが含まれていますが、これを操作または変更する権限がありません。ありがとう

URLの例

yahoo.com and google.com

Yahoo.comとgoogle.comのタブがすでに開いている場合にユーザーに警告したい

そして、私はこのようなURLを開くためにtabCreateを使用したいと思います:

tabCreate("http://maps.google.com/", "tabMapsPermanentAddress");
mean to open a new tab, it is use in creating chrome extension
14
User014019

あなたは次のようなものを使うかもしれません

<!-- HTML -->
<a id="opener">Open window</a>

// JavaScript
var a = document.getElementById('opener'), w;        
a.onclick = function() {
  if (!w || w.closed) {
    w = window.open("https://www.google.com","_blank","menubar = 0, scrollbars = 0");
  } else {
    console.log('window is already opened');
  }
  w.focus();
};

ワーキングjsBin | window.openメソッドの詳細

複数のウィンドウを制御する場合は、以下のスニペットを使用してください

<!-- HTML -->
<a href="https://www.google.com" class="opener">Open google.com</a> | 
<a href="http://www.yahoo.com" class="opener">Open yahoo.com</a> 

//JavaScript
window.onload = function(){
  var a = document.querySelectorAll('.opener'), w = [], url, random, i;
  for(i = 0; i < a.length; i++){
    (function(i){
      a[i].onclick = function(e) {
        if (!w[i] || w[i].closed) {
          url = this.href;
          random = Math.floor((Math.random() * 100) + 1); 
          w[i] = window.open(url, "_blank", random, "menubar = 0, scrollbars = 0");
        } else {
          console.log('window ' + url + ' is already opened');
        }
        e.preventDefault();
        w[i].focus();
      };
    })(i);
  }
};

ワーキングjsBin

別のウィンドウに読み込ませたくない場合は、この行を除外してください

random = Math.floor((Math.random()*100)+1);

次の行からrandom参照を削除します

w[i] = window.open(url, "_blank", random, "menubar=0,scrollbars=0");

補足:上記のように、サードパーティのコンテンツを含む2つのウィンドウを作成しました。それらから(親/オープナーウィンドウへの)参照を取得する方法がないことを知っておく必要があります。

9
hex494D49

基本的な考え方の1つは、タブカウントをCookieまたはlocalStorageに保存し、ページの読み込み時にインクリメントし、ページのアンロード時にデクリメントすることです。

if (+localStorage.tabCount > 0)
    alert('Already open!');
else
    localStorage.tabCount = 0;

localStorage.tabCount = +localStorage.tabCount + 1;
window.onunload = function () {
    localStorage.tabCount = +localStorage.tabCount - 1;
};

複数のタブで このフィドルを開く を試してください。

ただし、この手法は非常に壊れやすいことに注意してください。たとえば、なんらかの理由でブラウザがクラッシュした場合、アンロードハンドラは実行されず、同期しなくなります。

5
Casey Chu

Casey Chuによる回答 は、ページを開いたままブラウザがクラッシュするまで正常に動作します。次の実行では、localStorageオブジェクトはゼロ以外の値でtabCountを初期化します。したがって、より良い解決策は、セッションCookieに値を格納することです。ブラウザが正常に終了すると、セッションCookieは削除されます。ブラウザーがクラッシュすると、セッションCookieは実際には保持されますが、幸いなことにブラウザーの次の1回の実行に対してのみ保持されます。

オブジェクトsessionStorageはタブごとに異なるため、タブ数の共有には使用できません。

これは js-cookie ライブラリを使用して改善されたソリューションです。

if (+Cookies.get('tabs') > 0)
    alert('Already open!');
else
    Cookies.set('tabs', 0);

Cookies.set('tabs', +Cookies.get('tabs') + 1);

window.onunload = function () {
        Cookies.set('tabs', +Cookies.get('tabs') - 1);
};
4
Grzegorz Żur

この回答: https://stackoverflow.com/a/28230846 は、Cookies/js-cookieライブラリを必要としない代替手段です。それは私のニーズにより適していました。一言で言えば(完全な説明についてはリンクされた回答を参照してください):

$(window).on('storage', message_receive);

...

// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
    localStorage.setItem('message',JSON.stringify(message));
    localStorage.removeItem('message');
}


// receive message
//
function message_receive(ev)
{
    if (ev.originalEvent.key!='message') return; // ignore other keys
    var message=JSON.parse(ev.originalEvent.newValue);
    if (!message) return; // ignore empty msg or msg reset

    // here you act on messages.
    // you can send objects like { 'command': 'doit', 'data': 'abcd' }
    if (message.command == 'doit') alert(message.data);

    // etc.
}
0
Paul Higgins