📜 ⬆️ ⬇️

The task of communication between tabs and identifying the active tab

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 Slave
2. 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'); // 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> <!--  (title)    . --> <script type="text/javascript" src="duel.min.js"></script> <link rel="stylesheet" type="text/css" href="pretty.css"> </head> <body> <!-- div #preview     ,      iframe   youtube --> <div id="preview"><div>PLAY</div></div> <a href="index.html" target="_blank">  </a> <script type="text/javascript"> /**     player */ var player = duel.channel('player'); /**   - */ var previewDiv = document.getElementById('preview'); /** *     player */ player.on('stop', function () { /** *  iframe */ var frame = document.getElementsByTagName('iframe')[0]; frame.parentNode.removeChild(frame); /** *   */ previewDiv.style.display = 'block'; /** *    */ document.title = ''; }); previewDiv.onclick = function () { /** *   stop   player */ player.broadcast('stop'); /** *    iframe    youtube */ 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 site
DuelJS repository on github
Another demo DuelJS
Readthedocs documentation

Source: https://habr.com/ru/post/247739/


All Articles