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

时间:2014-09-04 09:13:31

标签: javascript external browser-tab external-links

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

示例网址

yahoo.com and google.com

我想提醒用户是否已经打开了yahoo.com和google.com的标签

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

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

5 个答案:

答案 0 :(得分:9)

您可以使用以下内容

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

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

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

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

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

并从下一行中删除random引用

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

附注:正如您在上面所看到的,我们创建了两个带有第三方内容的窗口;你应该知道没有办法从它们那里得到任何参考(到父/开启窗口)。

答案 1 :(得分:6)

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

在多个标签中尝试opening this fiddle

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

只是想把它扔在这里,因为我希望我有类似的东西。随心所欲。

如果您想要一个解决方案来检查您是否是不需要 cookie、作为 React 钩子工作并且无论浏览器是否崩溃的活动选项卡,您可以使用这个 useIsActiveTab 网络钩子如果您是最近的活动选项卡/窗口,则返回 true。您还可以使用 activateTab 将自己设置为活动标签。

import { useEffect, useState } from 'react';

const CHARACTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const CHARACTERS_LENGTH = CHARACTERS.length;

function generateTabId() {
  let result = '';
  const prefix = 'TAB_';
  const length = 15;
  for (let i = 0; i < length - prefix.length; i++) {
    result += CHARACTERS.charAt(Math.floor(Math.random() * CHARACTERS_LENGTH));
  }
  if (prefix.includes('_')) {
    return `${prefix}${result}`;
  }
  return `${prefix}_${result}`;
};

const tabId = generateTabId();

export function activateTab(): void {
  localStorage.setItem('activeTab', tabId);
  const event = new Event('thisStorage');
  window.dispatchEvent(event);
}

export function useIsActiveTab(): boolean {
  const [isActiveTab, setIsActiveTab] = useState(false);
  useEffect(() => {
    setActiveTab();
    function updateIsActiveTab() {
      setIsActiveTab(checkIfActiveTab());
    }
    window.addEventListener('storage', updateIsActiveTab);
    window.addEventListener('thisStorage', updateIsActiveTab);
    updateIsActiveTab();
    return () => {
      window.removeEventListener('storage', updateIsActiveTab);
      window.removeEventListener('thisStorage', updateIsActiveTab);
    };
  }, []);
  return isActiveTab;
}

function checkIfActiveTab(): boolean {
  const activeTab = localStorage.getItem('activeTab');
  if (!activeTab) {
    console.error('localStorage.activeTab is not set');
    return true;
  }
  if (activeTab === tabId) {
    return true;
  }
  return false;
}

function setActiveTab(): void {
  localStorage.setItem('activeTab', tabId);
}