Communication between browser tabs/windows using JavaScript
JavascriptBrowserJavascript 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.