Javascript; comunicação entre guias / janelas com a mesma origem

Eu tenho duas janelas: janela A e janela B.

  • janela A e janela B têm mesmo domínio
  • A janela A e a janela B não possuem nenhuma janela pai.

Questões:

  1. É possível que a janela A obtenha uma referência da janela B?
  2. Qual é a maneira mais elegante de fazer a janela A notificar algo para a janela B?
    (incluindo novas especificações HTML5)

Duas maneiras eu estou ciente de fazer isso:

  • Mensagens pelo servidor: onde a janela B pede ao servidor se a janela A notificou algo
  • Mensagens por dados locais (HTML5): quando a janela A deseja notificar algo, altera os dados locais, a janela B verifica regularmente os dados locais em busca de alterações.

Mas os dois caminhos não são tão elegantes.
Por exemplo, seria bom obter uma referência da janela B e usar window.postMessage () (HTML5)

O objective final é fazer algo como o facebook, onde se você abrir quatro abas do facebook e conversar em uma aba, o chat está atualizado em todas as abas do facebook, o que é legal!

Estou aderindo à solução de dados locais compartilhada mencionada na pergunta usando localStorage . Parece ser a melhor solução em termos de confiabilidade, desempenho e compatibilidade com navegadores.

localStorage é implementado em todos os navegadores modernos.

O evento de storage acionado quando outras guias fazem alterações no localStorage . Isso é muito útil para fins de comunicação.

Referências podem ser encontradas aqui:
Armazenamento web
Webstorage – evento de armazenamento

O padrão BroadcastChannel permite fazer isso. No momento, ele é implementado no Firefox e no Chrome ( caniuse , mdn ):

 // tab 1 var ch = new BroadcastChannel('test'); ch.postMessage('some data'); // tab 2 var ch = new BroadcastChannel('test'); ch.addEventListener('message', function (e) { console.log('Message:', e.data); }); 

SharedWorker é a especificação WHATWG / HTML5 para um processo comum que pode se comunicar entre as guias.

Você disse o seu:

O objective do utlimate é fazer algo como o facebook, onde se você abrir 4 abas do facebook, e conversar em uma aba, o chat é atualizado em todas as abas do facebook, o que é legal!

Isso deve acontecer como um subproduto de seu design, as exibições consultando o modelo (provavelmente o servidor) para atualizações no bate-papo, em vez de você ter que projetar em uma comunicação de visão cruzada. A menos que você esteja lidando com grandes quantidades de dados, por que se preocupar com isso? Parece que vai complicar as coisas sem um ganho enorme.

Anos atrás eu descobri que, se eu fiz window.open usando o nome de uma janela existente e uma URL em branco, obtive uma referência à janela existente (esse comportamento é documentado no MDC e um comentário na documentação do MSDN sugere que ele funciona em IE também). Mas isso foi há anos, eu não sei quão universal é o suporte para isso no mundo de hoje, e é claro que você não terá um nome de janela para procurar a menos que todas as suas janelas incluam um iframe nomeado para comunicação, nomeado exclusivamente através do código do lado do servidor e, em seguida, comunicado às outras janelas por meio de código do lado do servidor … (Pensamento assustador: Isso pode realmente ser viável. Armazenar os nomes de janela “atual” relacionados a uma conta conectada em uma tabela , dar a lista para qualquer nova janela criada que se conecta a essa conta, cull antigas inputs inativas.Mas se a lista estiver um pouco desatualizada, você vai abrir novas janelas ao procurar por outros … E eu aposto que o suporte é duvidoso de navegador para o navegador.)

Além do próximo SharedWorker , você também pode usar o envio de mensagens entre documentos , que é muito mais amplamente suportado . Nesse cenário, deve haver uma janela principal responsável por abrir todas as outras janelas com window.open . As janelas filho podem usar postMessage em seu window.opener .

Se usar flash é uma opção para você, há também o muito mais antigo LocalConnection virtualmente suportado em qualquer cliente com flash instalado ( código de exemplo ).

Outros methods de fallbacks:
plugin postMessage para jQuery com fallback window.location.href para navegadores mais antigos
solução baseada em cookie para comunicação não instantânea

AFAIK, é impossível comunicar através das janelas se não tiverem o mesmo pai.

Se ambos tiverem sido abertos a partir de uma janela pai, você poderá se apossar das referências de variables ​​dos pais.

No pai, abra as janelas assim:

 childA = window.open(...); childB = window.open(...) 

em ChildA, acesse childB assim:

 childB = window.opener.childA 

Eu tenho uma maneira legal de fazer esse truque, mas com restrições: você deve permitir popups para o seu domínio e você terá uma página sempre aberta (como tabulação ou como popup) que implementará as comunicações entre as janelas.

Veja um exemplo: http://test.gwpanel.org/test/page_one.html (atualize a página depois de ativar os pop-ups para o domínio)

A principal característica deste truque – popup está sendo aberto com fragment de url ‘#’ no final, este navegador de força para não alterar a localização da janela e armazenar todos os dados. E o window.postMessage faz o resto.