Communication between browser tabs/windows using JavaScript

JavascriptBrowser

Javascript Problem Overview


What's the most reliable way to have JavaScript communicate between tabs/windows of the same browser? For example, when Tab 2 starts audio playback, Tab 1 somehow knows about this and can pause its player.

I'm building a site with a music player... so at the moment if you open two tabs to the site, you could start music on both. This is obviously bad, so I'm trying to find a solution.

Javascript Solutions


Solution 1 - Javascript

For a more modern solution check out https://stackoverflow.com/a/12514384/270274

Quote: > 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. > > Reference:
> http://dev.w3.org/html5/webstorage/<br> > http://dev.w3.org/html5/webstorage/#the-storage-event

Solution 2 - Javascript

Update to a modern solution, leaving the old one below for historical reasons.

You can use Broadcast Channel API to send and receive messages https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API

// Connection to a broadcast channel
const bc = new BroadcastChannel('test_channel');

// Example of sending of a very simple message
// It doesn't have to be a string, it could be a JS object
bc.postMessage('This is a test message.');

To receive the message:

// A handler that only logs the event to the console:
bc.onmessage = function (ev) {
  console.log(ev);
}

and to close the channel:

// Disconnect the channel
bc.close();

THIS IS HISTORICAL OLD WAY TO DO IT, USE THE METHOD ABOVE FOR MODERN BROWSERS!

You can communicate between browser windows (and tabs too) using cookies.

Here is an example of sender and receiver:

sender.html

<h1>Sender</h1>

<p>Type into the text box below and watch the text 
   appear automatically in the receiver.</p>

<form name="sender">
<input type="text" name="message" size="30" value="">
<input type="reset" value="Clean">
</form>

<script type="text/javascript"><!--
function setCookie(value) {
	document.cookie = "cookie-msg-test=" + value + "; path=/";
	return true;
}
function updateMessage() {
	var t = document.forms['sender'].elements['message'];
	setCookie(t.value);
	setTimeout(updateMessage, 100);
}
updateMessage();
//--></script>

receiver.html:

<h1>Receiver</h1>

<p>Watch the text appear in the text box below as you type it in the sender.</p>

<form name="receiver">
<input type="text" name="message" size="30" value="" readonly disabled>
</form>

<script type="text/javascript"><!--
function getCookie() {
	var cname = "cookie-msg-test=";
	var ca = document.cookie.split(';');
	for (var i=0; i < ca.length; i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(cname) == 0) {
			return c.substring(cname.length, c.length);
		}
	}
	return null;
}
function updateMessage() {
	var text = getCookie();
	document.forms['receiver'].elements['message'].value = text;
	setTimeout(updateMessage, 100);
}
updateMessage();
//--></script>

Solution 3 - Javascript

I don't think you need cookies. Each document's JavaScript code can access the other document elements. So you can use them directly to share data.

Your first window w1 opens w2 and save the reference

var w2 = window.open(...)

In w2 you can access w1 using the opener property of window.

Solution 4 - Javascript

There is also an experimental technology called Broadcast Channel API that is designed specifically for communication between different browser contexts with same origin. You can post messages to and recieve messages from another browser context without having a reference to it:

var channel = new BroadcastChannel("foo");
channel.onmessage = function( e ) {
  // Process messages from other contexts.
};
// Send message to other listening contexts.
channel.postMessage({ value: 42, type: "bar"});

Obviously this is experiental technology and is not supported accross all browsers yet.

Solution 5 - Javascript

You can do this via the local storage API. Note that this works only between two tabs. You can't put both sender and receiver on the same page:

On the sender page:

localStorage.setItem("someKey", "someValue");

On the receiver page:

    $(document).ready(function () {

        window.addEventListener('storage', storageEventHandler, false);

        function storageEventHandler(evt) {
            alert("storage event called key: " + evt.key);
        }
    });

Solution 6 - Javascript

Below window(w1) opens another window(w2). Any window can send/receive message to/from another window. So we should ideally verify that the message originated from the window(w2) we opened.

In w1

var w2 = window.open("abc.do");
window.addEventListener("message", function(event){
    console.log(event.data);
});

In w2(abc.do)

window.opener.postMessage("Hi! I'm w2", "*");

Solution 7 - Javascript

Communicating between different JavaScript execution context was supported even before HTML5 if the documents was of the same origin.

If not or you have no reference to the other Window object, then you could use the new postMessage API introduced with HTML5. I elaborated a bit on both approaches in this Stack Overflow answer.

Solution 8 - Javascript

You can communicate between windows (tabbed or not) if they have a child-parent relationship.

Create and update a child window:

<html>
<head>
<title>Cross window test script</title>
<script>
var i = 0;
function open_and_run() {
    var w2 = window.open("", "winCounter"); 
    var myVar=setInterval(function(){myTimer(w2)},1000);
}

function myTimer(w2) {
    i++;
    w2.document.body.innerHTML="<center><h1>" + i + "</h1><p></center>";
}
</script>
</head>
<body>
Click to open a new window 
<button onclick="open_and_run();">Test This!</button>    
</body>
</html>

Child windows can use the parent object to communicate with the parent that spawned it, so you could control the music player from either window.

See it in action here: https://jsbin.com/cokipotajo/edit?html,js,output

Solution 9 - Javascript

I found a different way using HTML5 localstorage. I've created a library with events like API:

sysend.on('foo', function(message) {
    console.log(message);
});
var input = document.getElementsByTagName('input')[0];
document.getElementsByTagName('button')[0].onclick = function() {
    sysend.broadcast('foo', {message: input.value});
};

https://github.com/jcubic/sysend.js

It will send messages to all other pages, but not to the current one.

EDIT:

The library in the newest version also supports broadcast channel communication, but still, it works in IE11 that only supports local Storage. It also supports cross-origin communication (different domains) but a little bit of code.

The latest API also supports the emit function that executes events also on the same page.

Even latest version, also suport managing the windows, send message to particular window or get list of widows/tabs.

Solution 10 - Javascript

With Flash you can communicate between any window, any browser (yes, from Firefox to Internet Explorer at runtime) ...any form of instance of Flash (Shockwave or ActiveX).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionadamJLevView Question on Stackoverflow
Solution 1 - JavascriptbrilloutView Answer on Stackoverflow
Solution 2 - JavascriptRoman GoyenkoView Answer on Stackoverflow
Solution 3 - JavascriptdonkeydownView Answer on Stackoverflow
Solution 4 - JavascriptLeonid VasilevView Answer on Stackoverflow
Solution 5 - JavascriptDavid DehghanView Answer on Stackoverflow
Solution 6 - JavascriptAshwin AggarwalView Answer on Stackoverflow
Solution 7 - JavascriptMartin AnderssonView Answer on Stackoverflow
Solution 8 - JavascriptVictor StoddardView Answer on Stackoverflow
Solution 9 - JavascriptjcubicView Answer on Stackoverflow
Solution 10 - JavascriptJakob SternbergView Answer on Stackoverflow