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
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>
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 modifielocalStorage
. 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
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.
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);
}
});
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.
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", "*");
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
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 .
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.