web-dev-qa-db-fra.com

Communication Javascript entre les onglets / fenêtres du navigateur

Quel est le moyen le plus fiable de faire communiquer Javascript entre les onglets/fenêtres du même navigateur? Par exemple, lorsque l'onglet 2 démarre la lecture audio, l'onglet 1 en est informé et peut mettre son lecteur en pause.

Je construis un site avec un lecteur de musique ... donc pour le moment, si vous ouvrez deux onglets vers le site, vous pouvez commencer à écouter de la musique sur les deux. C'est évidemment mauvais, alors j'essaie de trouver une solution.

Des idées? Merci

142
adamJLev

Ceci est une ancienne réponse, je suggère d'utiliser la version moderne décrite ici:

Javascript; communication entre onglets/fenêtres de même origine


Vous pouvez communiquer entre les fenêtres du navigateur (et les onglets également) à l'aide de cookies.

Voici un exemple d'expéditeur et de destinataire:

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>
91
Roman Goyenko

Pour une solution plus moderne, consultez https://stackoverflow.com/a/12514384/270274

Citation:

Je m'en tiens à la solution de données locales partagées mentionnée dans la question en utilisant localStorage. Cela semble être la meilleure solution en termes de fiabilité, de performances et de compatibilité des navigateurs.

localStorage est implémenté dans tous les navigateurs modernes.

L'événement storage est déclenché lorsque un autre onglet modifie localStorage. C'est assez pratique pour la communication.

Référence:
http://dev.w3.org/html5/webstorage/
http://dev.w3.org/html5/webstorage/#the-storage-event

143
brillout

Je ne pense pas que vous ayez besoin de cookies. Le code js de chaque document peut accéder aux autres éléments du document. Vous pouvez donc les utiliser directement pour partager des données. Votre première fenêtre w1 ouvre w2 et enregistre la référence

var w2 = window.open(...) 

Dans w2, vous pouvez accéder à w1 à l'aide de la propriété opener de window.

15
donkeydown

Vous pouvez le faire via l'API de stockage local. Notez que cela ne fonctionne qu'entre 2 onglets. vous ne pouvez pas mettre à la fois l'expéditeur et le destinataire sur la même page:

Sur la page de l'expéditeur:

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

Sur la page du destinataire

    $(document).ready(function () {

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

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

Il existe également une technologie expérimentale appelée Broadcast Channel API spécialement conçu pour la communication entre différents contextes de navigateur de même origine. Vous pouvez poster et recevoir des messages depuis un autre contexte de navigateur sans y avoir de référence:

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

De toute évidence, il s’agit d’une technologie expérimentale qui n’est pas encore prise en charge par tous les navigateurs.

10
Leonid Vasilev

La fenêtre ci-dessous (w1) ouvre une autre fenêtre (w2). Toute fenêtre peut envoyer/recevoir un message vers/depuis une autre fenêtre. Nous devrions donc idéalement vérifier que le message provient de la fenêtre (w2) que nous avons ouverte.

En w1

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

Dans w2 (abc.do)

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

Vous pouvez communiquer entre les fenêtres (à onglets ou non) si elles ont une relation parent-enfant.

Créer et mettre à jour une fenêtre enfant:

<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>

Les fenêtres enfants peuvent utiliser l'objet parent pour communiquer avec le parent qui l'a engendré. Vous pouvez ainsi contrôler le lecteur de musique à partir de l'une ou l'autre des fenêtres.

Voir en action ici: https://jsbin.com/cokipotajo/edit?html,js,output

9
Victor Stoddard

La communication entre différents contextes d'exécution de JavaScript était prise en charge avant HTML5 si les documents avaient la même origine. Si ce n'est pas le cas ou si vous n'avez aucune référence à l'autre objet Window, vous pouvez utiliser la nouvelle API postMessage introduite avec HTML5. J'ai élaboré un peu sur les deux approches dans cette réponse de stackoverflow .

8
Martin Andersson

Trouver autrement en utilisant HTML5 localstorage, j'ai créé une bibliothèque avec des événements tels que l'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});
};

il enverra des messages à toutes les autres pages mais pas pour celle en cours.

1
jcubic