JavaScript; communication between tabs/windows with same origin

79,539

Solution 1

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

Solution 2

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

Solution 3

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

Solution 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.)

Solution 5

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

Share:
79,539

Related videos on Youtube

brillout
Author by

brillout

https://brillout.com/

Updated on July 05, 2022

Comments

  • brillout
    brillout over 1 year

    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.
    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 specifications)

    Two ways I am aware of doing this:

    • messaging by server: where window B regularly 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 regularly 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)

    The ultimate goal is to make something like Facebook where if you open four Facebook tabs and chat in one tab, the chat is up to date in every Facebook tab, which is neat!

  • brillout
    brillout almost 14 years
    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
    brillout almost 14 years
    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
  • Andy E
    Andy E almost 14 years
    @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 en.wikipedia.org/wiki/Comet_(programming).
  • brillout
    brillout almost 14 years
    i just tried your trick combined with window.postMessage(), namely window.open(null,'windowName').postMessage('test msg',"*"). sadly didn't seem to work
  • brillout
    brillout almost 14 years
    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!
  • T.J. Crowder
    T.J. Crowder almost 14 years
    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...
  • brillout
    brillout almost 14 years
    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.
  • T.J. Crowder
    T.J. Crowder almost 14 years
    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...
  • brillout
    brillout over 13 years
    nice, a shame that it doesn't seem to be implemented
  • brillout
    brillout over 13 years
    it doesn't seems to solve my problem, but thanks anyway
  • rektide
    rektide over 13 years
    its implemented in moz, webkit, and i believe opera.
  • brillout
    brillout over 11 years
    It isn't implemented in Firefox: caniuse.com/sharedworkers
  • brillout
    brillout about 11 years
    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.
  • Kai Aragaki
    Kai Aragaki about 11 years
    The flash-based method and the cookie-based fallback doesn't have this limitation (obviously, they have other downsides).
  • inf3rno
    inf3rno about 10 years
    Use intercom.js: github.com/diy/intercom.js it's a complete implementation of that approach...
  • vsync
    vsync over 9 years
  • purebill
    purebill over 9 years
    It is a painful bug in IE (even in IE11) 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.
  • s3m3n
    s3m3n over 9 years
    No IE support at all, even IE11.
  • adentum
    adentum almost 7 years
    If synchronizing your data across multiple tabs is what you want I wrote a blog article on it here: ebenmonney.com/blog/… .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
  • Thomas Poole
    Thomas Poole over 6 years
    I think this is what I want for HTML5 multi-screen gaming...
  • serdar.sanri
    serdar.sanri over 6 years
    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.
  • Doin
    Doin over 3 years
    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
    Doin over 3 years
    MDN has a whole paragraph of the limitations of this trick: developer.mozilla.org/en-US/docs/Web/API/Window/open#Example‌​s (see the yellow note box).
  • T.J. Crowder
    T.J. Crowder over 3 years
    @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.)
  • Doin
    Doin over 3 years
    @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).
  • T.J. Crowder
    T.J. Crowder over 3 years
    @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. :-)
  • Doin
    Doin over 3 years
    Oops, I missed that! The surrounding <div> didn't have one, so I thought the closest I could get was the "Examples" heading, somewhat above it. Well, darn!