A good example of a task is vk.com. Each time you play music or video in one tab, in other tabs, playback stops. And if you contact the Internet for help in solving this problem, you will probably find a description of
Storage Events or
Page Visibility API or even ready-made solutions, for example
Visibility.js .
On Habré already had a review of these things, for example,
here and
again .

')
I went this way, but not one of the solutions did not suit me. I wanted something simple, lightweight and not requiring in-depth study of the details.
The solution, which came out as a result, acquired the name DuelJS (just a random unique name) and below I will try to compare it with Visibility.js in order to avoid unnecessary criticism in my own way.
Active tab
A convenient cross-browser wrapper for a simple reflection of the state “this tab is now active”, in visibility.js will look like this:
if ('visible' == Visibility.state()) {
The Visibility tab has 3 states:
visible ,
hidden and
prerender .
The advantage of Visibility are also callbacks, which you can hang on many events, such as tab activation, setInterval in the active window, and the like.
The DuelJS philosophy is slightly simplified:
1. All tabs have only 2 states -
Master and
Slave2. Master tab is a tab in which the work is being done - nothing superfluous, all the others are Slave.
With this approach, only one function is sufficient:
window.isMaster () - check if the tab is a wizard.
if (window.isMaster()) {
Communication between tabs
We now turn to communications between the tabs. The most suitable solution seemed to me to use
Storage Events , although they are not without problems. By the way, I also found in Google such options as using the
postMessage API or WebSockets.
The main problem of Storage Events is their poor support by
some MSIE, although until recently other browsers might have problems with it too.
Since Visibility.js is essentially a wrapper over Page Visibility API - it doesn't work with Storage Events.
In DuejJS, there is a cross-browser wrapper over Storage Events, which is expressed in the following philosophy:
1. Communications between tabs are carried out using channels
2. Inside a channel, tabs can trigger events that other tabs on this channel can respond to.
Creating a channel is quite simple:
var ch = duel.channel('channel_name');
Now we define the behavior when calling the
qwerty event:
ch.on('qwerty', function (a, b, c, ...) {})
The channel's
on method determines its behavior. In the function passed by the second parameter there can be any number of arguments, or not at all.
Starting an event is just as easy. The word
on is now replaceable with
broadcast , and the arguments to be passed are inserted after the event name:
ch.broadcast('qwerty', a, b, c, ...)
Creating a player with behavior like on vk.com
For impatient readers immediately give a
link to a working example .
The main essence of the application is in three lines:
1. var player = duel.channel ('player'); (channel definition)
2. player.on ('stop', function () {... (definition of behavior at the stop event)
3. player.broadcast ('stop'); (start event stop)
The full page code looks like this: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script type="text/javascript" src="duel.min.js"></script> <link rel="stylesheet" type="text/css" href="pretty.css"> </head> <body> <div id="preview"><div>PLAY</div></div> <a href="index.html" target="_blank"> </a> <script type="text/javascript"> var player = duel.channel('player'); var previewDiv = document.getElementById('preview'); player.on('stop', function () { var frame = document.getElementsByTagName('iframe')[0]; frame.parentNode.removeChild(frame); previewDiv.style.display = 'block'; document.title = ''; }); previewDiv.onclick = function () { player.broadcast('stop'); var frame = document.createElement("iframe"); frame.width = '859'; frame.height = '480'; frame.src = '//www.youtube.com/embed/xsV8TrF4gN0?rel=0&autoplay=1'; frame.frameborder = '0'; previewDiv.parentNode.insertBefore(frame, previewDiv.nextSibling); previewDiv.style.display = 'none'; document.title = '...'; } </script> </body> </html>
Conclusion
I would be very happy if this solution helps you and you use it in your projects. I am open to ideas for improvement. Liba is cross-browser and works, including in IE, through built-in hacks.

useful links
DuelJS brief documentation on the siteDuelJS repository on githubAnother demo DuelJSReadthedocs documentation