Comment communiquer entre iframe et le site parent?

185

Le site Web dans l'iframe ne se trouve pas dans le même domaine , mais les deux sont à moi, et j'aimerais communiquer entre le iframeet le site parent. C'est possible?

Danny Fox
la source

Réponses:

309

Avec différents domaines, il n'est pas possible d'appeler des méthodes ou d'accéder directement au document de contenu de l'iframe.

Vous devez utiliser la messagerie inter-document .

Par exemple dans la fenêtre du haut:

 myIframe.contentWindow.postMessage('hello', '*');

et dans l'iframe:

window.onmessage = function(e){
    if (e.data == 'hello') {
        alert('It works!');
    }
};

Si vous publiez un message d'iframe dans la fenêtre parent

window.top.postMessage('hello', '*')
user123444555621
la source
2
merci, mais malheureusement cela ne fonctionne pas dans les anciens navigateurs.
Danny Fox
106
Dans le parent: window.onmesage = function().... Dans l'iframe:window.top.postMessage('hello', '*')
user123444555621
3
Ce n'est pas un bug. Les URL de fichiers peuvent être très dangereuses et les navigateurs les traitent avec une attention toujours plus grande. Dans l'ancien temps, vous pouviez mettre un lien vers file://C:/Windows/system32/whateverune page Web et le faire pointer directement dans le dossier système de l'utilisateur. De nos jours, les navigateurs ignorent généralement les clics sur des liens comme celui-ci. Exécutez un serveur Web et accédez à votre code via celui-ci et vous verrez les erreurs apparaître.
Stijn de Witt
4
Comme bonne pratique, n'utilisez jamais le «*» pour votre cible. En fait, MDN dit: "Fournissez toujours une cible spécifique, pas *, si vous savez où le document de l'autre fenêtre doit être situé. Ne pas fournir une cible spécifique révèle les données que vous envoyez à tout site malveillant intéressé."
rodiwa
2
Nous pouvons même utiliser window.frames[index]pour obtenir child frame ( <iframe>, <object>, <frame>), équivalent à getElementsByTagName("iframe")[index].contentWindow. Pour obtenir un objet de fenêtre parent à partir d'IFrames, il est préférable d'utiliser window.parent, comme le window.topreprésente la fenêtre la plus parente
phoenisx
46

Il doit être ici, car réponse acceptée de 2012

En 2018 et dans les navigateurs modernes, vous pouvez envoyer un événement personnalisé de l'iframe à la fenêtre parent.

iframe:

var data = { foo: 'bar' }
var event = new CustomEvent('myCustomEvent', { detail: data })
window.parent.document.dispatchEvent(event)

parent:

window.document.addEventListener('myCustomEvent', handleEvent, false)
function handleEvent(e) {
  console.log(e.detail) // outputs: {foo: 'bar'}
}

PS: Bien sûr, vous pouvez envoyer des événements dans la direction opposée de la même manière.

document.querySelector('#iframe_id').contentDocument.dispatchEvent(event)
Étranger dans le Q
la source
1
Bonjour, dois-je être sur le même domaine pour le faire?
Guillaume Harari
1
Il convient de noter qu'il dispatchEventest pris en charge dans tous les principaux navigateurs. IE9 était la première version, donc la plupart des systèmes d'exploitation fonctionnent maintenant avec. caniuse.com/#search=dispatchEvent
Dan Atkinson
1
Je ne peux pas communiquer de parent à iframe avec cette méthode.
Avan le
Ouais, je ne peux pas le faire fonctionner non plus, l'iframe js se charge après la fenêtre parent donc il n'est pas là pour recevoir le msg lorsqu'il est envoyé. cela ne fonctionne que de l'iframe au parent pour moi.
radtek
14

Cette bibliothèque prend en charge les navigateurs HTML5 postMessage et hérités avec redimensionnement + hachage https://github.com/ternarylabs/porthole

Edit: Maintenant, en 2014, l'utilisation d'IE6 / 7 est assez faible, IE8 et surtout le support, postMessagedonc je suggère maintenant de simplement l'utiliser.

https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage

jpillora
la source
Avec l'avertissement que IE8 / 9 ne prend en charge que les chaînes caniuse.com/#search=postmessage (voir les problèmes connus)
Harry
cela peut être contourné en encodant vos objets événement en json et en les décodant de l'autre côté.
codewandler
3

la window.toppropriété doit pouvoir donner ce dont vous avez besoin.

Par exemple

alert(top.location.href)

Voir http://cross-browser.com/talk/inter-frame_comm.html

sambomartin
la source
10
Comme l'iframe n'est pas sur le même domaine, il ne peut pas accéder à son parent.
Andreas Köberle le
1

Vous pouvez aussi utiliser

postMessage(message, '*');

gonzarodriguezt
la source
1

Utilisez event.source.window.postMessagepour renvoyer à l'expéditeur.

Depuis Iframe

window.top.postMessage('I am Iframe', '*')
window.onmessage = (event) => {
    if (event.data === 'GOT_YOU_IFRAME') {
        console.log('Parent received successfully.')
    }
}

Puis de la part des parents, répondez.

window.onmessage = (event) => {
    event.source.window.postMessage('GOT_YOU_IFRAME', '*')
}
Binh Ho
la source