147 votes

Communication entre les onglets/fenêtres du navigateur à l'aide de JavaScript

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

Je suis en train de construire un site avec un lecteur de musique... donc pour le moment si vous ouvrez deux onglets sur le site, vous pouvez lancer la musique sur les deux. C'est évidemment mauvais, donc j'essaie de trouver une solution.

2 votes

La lecture automatique de l'audio est mauvaise quoi qu'il arrive. Pourquoi ne pas laisser les utilisateurs cliquer sur un bouton "lecture" et mettre manuellement en pause l'autre onglet s'ils se trouvent dans cette situation ?

8 votes

Il n'y a pas de jeu automatique. Mais ce serait bien si l'utilisateur n'avait pas à mettre manuellement en pause l'autre onglet. Youtube fait cela par exemple (avec flash)

5 votes

+1 Bonne question, je suis en train de résoudre ce problème exact dans mon application de chat sur le site web.

146voto

brillout.com Points 2289

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

Citation :

Je m'en tiens à la solution des données locales partagées mentionnée dans la question en utilisant localStorage . Il semble que ce soit la meilleure solution en termes de fiabilité, de performances et de compatibilité avec les navigateurs.

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

El storage se déclenche lorsque otros Les onglets apportent des modifications à localStorage . C'est très pratique pour la communication.

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

5 votes

C'est mieux que la solution acceptée. Elle ne vous oblige pas à vérifier constamment les nouvelles informations, n'a pas de délai et vous permet de recevoir tous les événements.

2 votes

J'ai des problèmes avec localStorage sur IE11, voir ce post (j'ai fait face au point # 3) blogs.msdn.com/b/ieinternals/archive/2009/09/16/ donc la solution cockie est meilleure (pour IE au moins). J'ai également essayé de désactiver les cockies mais cela fonctionne toujours (sous IE 11).

3 votes

Bonne page de démonstration - html5demos.com/storage-events#view-source

91voto

Roman Goyenko Points 2870

Mise à jour vers une solution moderne, en laissant l'ancienne ci-dessous pour des raisons historiques.

Vous pouvez utiliser l'API du canal de diffusion pour envoyer et recevoir des 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.');

Pour recevoir le message :

// A handler that only logs the event to the console:
bc.onmessage = function (ev) {
  console.log(ev);
}

et pour fermer le canal :

// Disconnect the channel
bc.close();

IL S'AGIT D'UNE ANCIENNE MÉTHODE HISTORIQUE, UTILISEZ LA MÉTHODE CI-DESSUS POUR LES NAVIGATEURS MODERNES !

Vous pouvez communiquer entre les fenêtres du navigateur (et les onglets aussi) en utilisant des cookies.

Voici un exemple d'émetteur et de récepteur :

expéditeur.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>

récepteur.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>

2 votes

J'ai aussi pensé à quelque chose comme ça, mais j'espérais une meilleure solution que cookies/setTimeout. C'est peut-être la seule solution. Merci

0 votes

Quel type de lecteur utilisez-vous ? S'il s'agit d'un lecteur flash, vous pouvez faire des choses avec flash qui pourraient être plus élégantes.

16 votes

Ne pas passer une chaîne de caractères à setTimeout - vous utilisez eval en faisant ça. Au lieu de cela, passez la fonction directement avec setTimeout(updateMessage, 100)

16voto

donkeydown Points 470

Je ne pense pas que vous ayez besoin de cookies. Le code JavaScript 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 en utilisant la propriété opener de window .

2 votes

UTILISER DES COOKIES ? Mangez-les et profitez-en ! Il existe un moyen BEAUCOUP plus simple ! Il suffit d'accéder à une variable de l'autre fenêtre. Vous avez une valeur var dans w1, accédez-y depuis w2 whit window.opener.value !

2 votes

Disons que l'utilisateur les ouvre tous. Y a-t-il une solution similaire dans ce cas ?

0 votes

Je pense que vous pouvez ouvrir autant de fenêtres que vous le souhaitez et utiliser cette solution. La référence à toute nouvelle fenêtre doit être enregistrée quelque part. La référence à la fenêtre parent est toujours disponible. Je ne vois pas de limitation jusqu'à présent. @Fardinak

10voto

Martin Andersson Points 1869

La communication entre différents contextes d'exécution JavaScript était supportée même avant HTML5 si les documents étaient de la même origine.

Si ce n'est pas le cas ou si vous n'avez pas de référence à l'autre Window vous pouvez alors utiliser le nouvel objet API postMessage introduit avec HTML5. J'ai développé un peu les deux approches dans cette réponse de Stack Overflow .

5 votes

L'API postMessage n'est pas conçue pour cela. stackoverflow.com/a/1100416/470117 Vous avez besoin de la référence de la fenêtre ciblée pour poster un message pour cette fenêtre spécifique.

9voto

Victor Stoddard Points 158

Vous pouvez communiquer entre les fenêtres (avec ou sans onglet) si elles ont une relation enfant-parent.

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>

Child Windows peut utiliser le parent pour communiquer avec le parent qui l'a engendré, de sorte que vous pouvez contrôler le lecteur de musique à partir de n'importe quelle fenêtre.

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

0 votes

Un problème ici est que nous ne pouvons pas (sans faire de piratage) partager un lien vers notre vue synchronisée...

0 votes

@yckart Il y a tellement de façons de faire cela, mais la façon la plus courante que j'ai vue est d'envoyer la chaîne à une boîte de saisie dans l'autre fenêtre. Vous pouvez créer un écouteur d'événements pour un changement de valeur. Exemple : stackoverflow.com/questions/9994120/ . Je pense qu'il serait préférable de simplement appeler une fonction javascript dans l'autre fenêtre, en lui passant l'URL. Par exemple, <a href="javascript:window.parent.mySendURL(url)"> depuis la fenêtre enfant ou <a href="javascript:myChildWindow.mySendURL(url)"> depuis la fenêtre parent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X