如何知道浏览器选项卡是否已使用 Javascript 打开?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25661543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 21:39:41  来源:igfitidea点击:

How to know if browser tab is already open using Javascript?

javascriptexternalbrowser-tabexternal-links

提问by User014019

How to know or check if the two browser tab is already open and if those tab are open, the user will receive an alert box or msg box saying that 'the url is already open', something like that, in pure/native JavaScript? This browser tab is contain an external website which is I don't have any privileges to manipulate or change it. Thanks

如何知道或检查两个浏览器选项卡是否已打开,如果这些选项卡已打开,用户将收到一个警告框或消息框,说“url 已打开”,类似于纯/原生 JavaScript?此浏览器选项卡包含一个外部网站,我无权操作或更改它。谢谢

Example URLs

示例 URL

yahoo.com and google.com

I want to alert the user if there's already open tab for yahoo.com and google.com

如果 yahoo.com 和 google.com 已经打开标签,我想提醒用户

And I want to use tabCreate to open the url like this:

我想使用 tabCreate 打开这样的网址:

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

采纳答案by hex494D49

You may use something like following

您可以使用以下内容

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

Working jsBin| More on window.open method

工作jsBin| 更多关于 window.open 方法

If you want to control more than one window, use the snippet below

如果您想控制多个窗口,请使用以下代码段

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

Working jsBin

工作jsBin

If you don't want them to load in separated window, just exclude this line

如果您不希望它们在单独的窗口中加载,只需排除此行

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

and remove randomreference from the next line

random从下一行删除引用

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

Side note: As you can see above, we created two windows with some third party content; you should know that there's no way to get any reference (to the parent/opener window) from them.

旁注:正如您在上面看到的,我们创建了两个包含一些第三方内容的窗口;你应该知道没有办法从他们那里得到任何引用(到父窗口/打开窗口)。

回答by Casey Chu

One basic idea is to store the tab count in either a cookie or localStorage, incrementing it on page load and decrementing it on page unload:

一个基本的想法是将标签计数存储在 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;
};

Try opening this fiddlein multiple tabs.

尝试在多个选项卡中打开这个小提琴

Note that this technique is pretty fragile, though. For example, if for some reason the browser crashes, the unload handler won't run, and it'll go out of sync.

但是请注意,这种技术非常脆弱。例如,如果由于某种原因浏览器崩溃,卸载处理程序将不会运行,并且会失去同步。

回答by Grzegorz ?ur

The answer by Casey Chuworks fine until the browser crashes with the page open. On any next execution, the localStorageobject will have initialized tabCountwith non zero value. Therefore a better solution is to store the value in a session cookie. The session cookie will be removed when browser exits successfully. When the browser crashes the session cookie will actually be preserved but fortunately only for one next execution of the browser.

Casey Chu回答工作正常,直到浏览器在页面打开时崩溃。在任何下一次执行中,该localStorage对象将tabCount使用非零值进行初始化。因此,更好的解决方案是将值存储在会话 cookie 中。当浏览器成功退出时,会话 cookie 将被删除。当浏览器崩溃时,会话 cookie 实际上会被保留,但幸运的是只用于浏览器的下一次执行。

Object sessionStorageis distinct for each tab so it cannot be used for sharing tab count.

sessionStorage每个选项卡的对象都是不同的,因此它不能用于共享选项卡计数。

This is the improved solution using js-cookielibrary.

这是使用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);
};

回答by Paul Higgins

This answer: https://stackoverflow.com/a/28230846is an alternative that doesn't require Cookies/js-cookie library. It better suited my needs. In a nutshell (see linked answer for full description):

这个答案: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.
}