Como se comunicar entre o iframe e o site pai?

185

O site no iframe não está localizado no mesmo domínio , mas ambos são meus e eu gostaria de me comunicar entre o iframesite e o pai. É possível?

Danny Fox
fonte

Respostas:

308

Com domínios diferentes, não é possível chamar métodos ou acessar o documento de conteúdo do iframe diretamente.

Você precisa usar mensagens entre documentos .

Por exemplo, na janela superior:

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

e no iframe:

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

Se você estiver postando uma mensagem do iframe na janela pai

window.top.postMessage('hello', '*')
user123444555621
fonte
2
obrigado, mas infelizmente não funciona em navegadores mais antigos.
Danny Fox
106
No parent: window.onmesage = function().... No iframe:window.top.postMessage('hello', '*')
user123444555621
3
Não é um bug. Os URLs de arquivo podem ser muito inseguros e os navegadores os tratam com um cuidado cada vez maior. Antigamente, era possível colocar um link file://C:/Windows/system32/whateverem uma página da Web e apontá-lo diretamente para a pasta do sistema do usuário. Atualmente, os navegadores ignoram cliques em links como esse. Execute um servidor da web e acesse seu código por meio disso e você verá os erros aparecerem.
Stijn de Witt
4
Como uma boa prática, nunca use o '*' para o seu destino. De fato, a MDN diz - "Sempre forneça um targetOrigin específico, não *, se você souber onde o documento da outra janela deve estar localizado. A falha em fornecer um destino específico divulga os dados que você envia para qualquer site malicioso interessado".
Rodiwa
2
Podemos até usar window.frames[index]para obter um quadro filho ( <iframe>, <object>, <frame>), equivalente a getElementsByTagName("iframe")[index].contentWindow. Para obter objeto de janela pai de IFrames, é melhor usar window.parent, como window.toprepresenta o mais alto Parent Janela
phoenisx
46

Deve estar aqui, porque resposta aceita de 2012

Em 2018 e navegadores modernos, você pode enviar um evento personalizado do iframe para a janela pai.

iframe:

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

pai:

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

PS: Claro, você pode enviar eventos na direção oposta da mesma maneira.

document.querySelector('#iframe_id').contentDocument.dispatchEvent(event)
Estranho no Q
fonte
1
Olá, preciso estar no mesmo domínio para fazer isso?
Guillaume Harari
1
Note-se que dispatchEventé suportado em todos os principais navegadores. O IE9 foi a primeira versão em que entrou, então a maioria dos sistemas operacionais agora trabalha com ele. caniuse.com/#search=dispatchEvent
Dan Atkinson
1
Não consigo me comunicar do pai para o iframe com esse método.
Avan
Sim, também não consigo fazê-lo funcionar, o iframe js está sendo carregado após a janela pai, portanto não existe para receber a mensagem quando enviada. só funciona de iframe para pai para mim.
radtek 18/03
14

Esta biblioteca suporta navegadores HTML5 postMessage e herdados com redimensionamento + hash https://github.com/ternarylabs/porthole

Edit: Agora em 2014, o uso do IE6 / 7 é bastante baixo, o IE8 e, acima de tudo, o suporte, postMessageentão agora sugiro apenas usá-lo.

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

jpillora
fonte
Com a ressalva de que o IE8 / 9 único apoio cordas caniuse.com/#search=postmessage (Veja problemas conhecidos)
Harry
isso pode ser contornado, codificando os objetos de evento para json e decodificando-os do outro lado.
Codewandler
3

a window.toppropriedade deve poder fornecer o que você precisa.

Por exemplo

alert(top.location.href)

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

sambomartin
fonte
10
Como o iframe não está no mesmo domínio, ele não pode acessar o pai.
Andreas Köberle
1

Você também pode usar

postMessage(message, '*');

gonzarodriguezt
fonte
1

Use event.source.window.postMessagepara enviar de volta ao remetente.

Do Iframe

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

Então, dos pais, diga de volta.

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