80

I have two windows: window A and window B.

  • window A and window B have same domain
  • window A and window B doesn't have any parent window.

Questions:

  1. Is it possible for window A to get a reference of window B?
  2. what is the most elegant way to make window A notify something to window B?
    (including new HTML5 specs)

Two ways i am aware of doing this:

  • messaging by server: where window B regulary asks the server if window A has notified something
  • messaging by local data (HTML5): when window A wants to notify something it changes the local data, window B regulary checks the local data for any changes.

But the two ways are not so elegant.
For example it would be nice to get a reference of window B and use window.postMessage() (HTML5)

Ultimate goal is to make something like facebook where if you open 4 facebook tabs and chat in one tab, the chat is up to date in every facebook tab, which is neat!

brillout
  • 8,117
  • 9
  • 60
  • 74
  • [My answer to 'Sharing websocket across browser tabs?'](http://stackoverflow.com/questions/9554896/sharing-websocket-across-browser-tabs/11458341#11458341) may help you. – Donghwan Kim Jul 12 '12 at 18:47
  • 1
    http://stackoverflow.com/questions/19125823/how-is-it-possible-to-share-single-js-resource-between-browser-tabs/19165781#19165781 Currently intercom.js is the best option for sharing single socket between tabs. – inf3rno Oct 03 '13 at 22:26
  • @Gothdo: How can this be a duplicate if it has been ask before the other question? – brillout Dec 13 '16 at 08:04
  • @brillout.com http://meta.stackoverflow.com/q/251938/3853934 – Michał Perłakowski Dec 13 '16 at 11:47

7 Answers7

127

I'm sticking to the shared local data solution mentioned in the question using localStorage. It seems to be the best solution in terms of reliability, performance, and browser compatibility.

localStorage is implemented in all modern browsers.

The storage event fires when other tabs makes changes to localStorage. This is quite handy for communication purposes.

References can be found here:
Webstorage
Webstorage - storage event

brillout
  • 8,117
  • 9
  • 60
  • 74
  • 8
    Use intercom.js: https://github.com/diy/intercom.js/ it's a complete implementation of that approach... – inf3rno Oct 03 '13 at 23:18
  • 9
    Demo page - http://html5demos.com/storage-events – vsync Jun 15 '14 at 15:15
  • It is a painful bug in IE (even in IE11) http://goo.gl/jmFGzb that breaks all this approach if you are trying to communicate between iframes with the same origin that are embedded into some parent windows. Widget for a site is a good example. – purebill Jul 23 '14 at 16:33
  • If synchronizing your data across multiple tabs is what you want I wrote a blog article on it here: http://www.ebenmonney.com/blog/how-to-implement-remember-me-functionality-using-token-based-authentication-and-localstorage-in-a-web-application .With this you can save your data with functions such as torageManager.saveSyncedSessionData('data', 'key') or storageManager.savePermanentData('data', 'key') and your data will be synchronized with all opened tabs. It uses localStorage and sessionStorage underneath – adentum Dec 15 '16 at 03:28
  • I think this is what I want for HTML5 multi-screen gaming... – Thomas Poole Mar 29 '17 at 00:03
29

The BroadcastChannel standard allows to do this. Right now it is implemented in Firefox and 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);
});
Joel Richard
  • 14,593
  • 6
  • 46
  • 37
  • I might be wrong, but there doesn't seem to be a way for a window or tab to reply to a BroadcastChannel message sender specifically, is there? What I mean is that if A broadcasts to B, C, D, E, there's no way for D to then initiate a private conversation with A. (The `event.source` parameter suggests that there ought to be, but I examined this in my Firefox v78 debugger, and it was set to *null*). – Doin Jul 28 '20 at 19:33
13

SharedWorker is the WHATWG/ HTML5 spec for a common process that can communicate amongst tabs.

rektide
  • 946
  • 7
  • 17
4

Besides the upcoming SharedWorker, you can also use cross-document messaging, which is much more widely supported. In this scenario, there must a be a main window that is responsible for opening all other windows with window.open. The child windows can then use postMessage on their window.opener.

If using flash is an option for you, there is also the much older LocalConnection virtually supported on any client with flash installed (example code).

Other fallbacks methods:
postMessage plugin for jQuery with window.location.href fallback for older browsers
cookie-based solution for non-instant communication

Community
  • 1
  • 1
zah
  • 4,925
  • 1
  • 31
  • 27
  • 1
    the assumption that all windows have been opened from one window is in many cases too restrictive. In the scenario described in the question window A and window B doesn't have any parent window. – brillout Sep 11 '12 at 18:44
  • The flash-based method and the cookie-based fallback doesn't have this limitation (obviously, they have other downsides). – zah Sep 11 '12 at 22:36
  • postMessage is only available if second window is opened from original window and frames, iframes etc. it does not support if you have same domain on different tabs. – serdar.sanri Jul 27 '17 at 21:13
4

You said your:

utlimate goal is to make something like facebook where if you open 4 facebook tabs, and chat in one tab, the chat is actualize on every facebook tab, wich is neat!

That should happen as a by-product of your design, the views querying the model (probably the server) for updates to the chat, rather than your having to design in cross-view communication. Unless you're dealing with transferring huge amounts of data, why worry about it? It seems like it'll complicate things without a huge gain.

Years ago I found that if I did window.open using the name of an existing window and a blank URL, I got a reference to the existing window (this behavior is even documented on MDN and a comment on the MSDN docs suggests it works in IE as well; that said, in 2017 someone added a somewhat ranty note to the MDN article listing some limitations — I haven't independently verified them). But that was years ago, I don't know how universal the support for it is in today's world, and of course you won't have a window name to look for unless all of your windows include a named iframe for communication, named uniquely via server-side code, and then communicated to the other windows by means of server-side code... (Scary thought: That might actually be feasible. Store the "current" window names related to a logged-in account in a table, give the list to any new window created that logs into that account, cull old inactive entries. But if the list is slightly out of date, you'll open new windows when searching for others... And I bet support is iffy from browser to browser.)

T.J. Crowder
  • 879,024
  • 165
  • 1,615
  • 1,639
  • actualy this is what i am basicly doing: the whole state of the web app is stored in the local data of the browser. since the local data is shared by window A and B, if window A changes the local data, window B would only need to re-read the local data to get the new state. but for it window B needs to know when it has to re-read the local data. One way of doing that is to make window B regulary check the local data. But it would be nicer to make window A tell window B "hey window B, check out the new state and re-read the local data!" nice rep nice trick for the window reference – brillout Feb 10 '10 at 13:31
  • 2
    i just tried your trick combined with window.postMessage(), namely window.open(null,'windowName').postMessage('test msg',"*"). sadly didn't seem to work – brillout Feb 10 '10 at 14:14
  • Not `null`, an empty string; from the MDC link above: *"Providing an empty string for strUrl is a way to get a reference to an open window by its name without changing the window's location."* The comment on MSDN says the same thing. Not that I'm saying that's going to do it, but... – T.J. Crowder Feb 10 '10 at 14:45
  • it doesn't seem to make a difference. the thing is that your trick doesn't seem to work with chrome. do you know the name of the trick? so i can research an alternative for google chrome. – brillout Feb 10 '10 at 15:53
  • No, I'm afraid I don't know of any special name for it. Well, I did warn you I didn't know if the support across browsers was very good. :-) And I'm not amazingly surprised about Chrome, given the whole multiple processes thing... – T.J. Crowder Feb 10 '10 at 16:06
  • MDN has a whole paragraph of the limitations of this trick: https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Examples (see the yellow note box). – Doin Jul 28 '20 at 21:27
  • @Doin - That page is linked above in the paragraph where I say "...And I bet support is iffy from browser to browser." :-) (Although the paragraph you mention looks fairly ranty -- remember that MDN is community-edited.) – T.J. Crowder Jul 29 '20 at 07:25
  • 1
    @T.J. Crowder Ah yes, I didn't realise it was indeed almost the same link, sorry. (I was trying to #-link as directly as possible to that note, here). It was fairly ranty in a way, but also full of very *specific* problems/limitations... which I would assume (without some reason to believe the contrary) were factually correct, whatever the tone was like. But I don't mean to be dismissive of your answer: If there's a use case where the discussed limitations aren't a problem, it could be a very good solution (especially for older browser support). – Doin Jul 29 '20 at 08:30
  • @Doin - Good idea trying to link to the note directly. I right-clicked it and it did indeed have an `id`, so I've added that to the answer. :-) – T.J. Crowder Jul 29 '20 at 08:47
  • Oops, I missed that! The surrounding `
    ` didn't have one, so I thought the closest I could get was the "Examples" heading, somewhat above it. Well, darn!
    – Doin Jul 31 '20 at 06:45
1

AFAIK, it is impossible to communicate across windows if they do not have the same parent.

If they have both been opened from a parent window, you should be able to get hold of the parent's variable references.

In the parent, open the windows like this:

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

in ChildA, access childB like this:

childB = window.opener.childA
Pekka
  • 418,526
  • 129
  • 929
  • 1,058
  • 1
    the question stills remains: what is the most elegant way to make them communicate? even indirectly, e.g. over the server. by a matter of fact that facebook made it, it is possible. thanks for the rep! – brillout Feb 10 '10 at 13:02
  • @romuwild: You're welcome for the rep ;-) it looks like that is the only option for you (through the server). You might be interested to know that facebook uses long polling comet, an http interaction where the server doesn't terminate the connection, instead pushing data through the connection as it becomes available. See http://en.wikipedia.org/wiki/Comet_(programming). – Andy E Feb 10 '10 at 13:42
  • or through local data instead of the server. but yeah seems to be the only option. thanks for the link, i wasn't aware of it! – brillout Feb 10 '10 at 14:18
0

I have a neat way to do such trick, but with restrictions: you should allow popups for your domain and you will get one page always opened (as tab or as popup) which will implement communications between windows.

Here's an example: http://test.gwpanel.org/test/page_one.html (refresh page after enabling popups for domain)

The main feature of this trick - popup is being opened with url fragment '#' in the end, this force browser to don't change window location and store all the data. And window.postMessage do the rest.