How to communicate between iframe and the parent site?

204,860

Solution 1

With different domains, it is not possible to call methods or access the iframe's content document directly.

You have to use cross-document messaging.

parent -> iframe

For example in the top window:

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

and in the iframe:

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

iframe -> parent

For example in the top window:

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

and in the iframe:

window.top.postMessage('hello', '*')

Solution 2

In 2018 and modern browsers you can send a custom event from iframe to parent window.

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: Of course, you can send events in opposite direction same way.

document.querySelector('#iframe_id').contentDocument.dispatchEvent(event)

Solution 3

This library supports HTML5 postMessage and legacy browsers with resize+hash https://github.com/ternarylabs/porthole

Edit: Now in 2014, IE6/7 usage is quite low, IE8 and above all support postMessage so I now suggest to just use that.

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

Solution 4

Use event.source.window.postMessage to send back to sender.

From Iframe

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

Then from parent say back.

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

Solution 5

the window.top property should be able to give what you need.

E.g.

alert(top.location.href)

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

Share:
204,860

Related videos on Youtube

Danny Fox
Author by

Danny Fox

Updated on July 23, 2021

Comments

  • Danny Fox
    Danny Fox over 2 years

    The website in the iframe isn't located in the same domain, but both are mine, and I would like to communicate between the iframe and the parent site. Is it possible?

  • Andreas Köberle
    Andreas Köberle about 12 years
    As the iframe isn't on the same domain he can't access its parent.
  • Danny Fox
    Danny Fox about 12 years
    thank you, but unfortunately it doesn't works in older browsers.
  • Apollon
    Apollon over 11 years
    @Pumbaa80 : Can you put a simple example?
  • Ansel Halliburton
    Ansel Halliburton over 11 years
    In the parent: window.onmesage = function().... In the iframe: window.top.postMessage('hello', '*')
  • Zelenova
    Zelenova almost 11 years
    @Pumbaa80 when I do that, I get two errors in the chrome console, but still, it works. Unsafe JavaScript attempt to access frame with URL file:///iframe.html from frame with URL file:///parent.html. Domains, protocols and ports must match.
  • Ansel Halliburton
    Ansel Halliburton almost 11 years
    @Zelenova That may be due to a bug in Chrome: code.google.com/p/chromium/issues/detail?id=94618
  • Stijn de Witt
    Stijn de Witt about 10 years
    It's not a bug. File urls can be very unsafe and browsers are treating them with ever increasing care. Back in the old days you could put a link to file://C:/Windows/system32/whatever on a webpage and make it point right into the user's system folder. These days browsers mostly ignore clicks on links like that. Run a webserver and access your code through that and you'll see the errors diappear.
  • tvshajeer
    tvshajeer about 9 years
    Can you provide a demo please. @Pumbaa80
  • rodiwa
    rodiwa over 8 years
    As a good practice, never use the '*' for your target. In fact, MDN says - "Always provide a specific targetOrigin, not *, if you know where the other window's document should be located. Failing to provide a specific target discloses the data you send to any interested malicious site."
  • Harry
    Harry over 7 years
    With the caveat that IE8/9 only support strings caniuse.com/#search=postmessage (See known issues)
  • codewandler
    codewandler almost 7 years
    this can be worked around by encoding your event objects to json and decode them on the other side.
  • phoenisx
    phoenisx over 6 years
    We can even use window.frames[index] to get child frame (<iframe>, <object>, <frame>), equivalent to getElementsByTagName("iframe")[index].contentWindow. To get Parent Window Object from IFrames, it is better to use window.parent, as window.top represents the Top Most Parent Window
  • Guillaume Harari
    Guillaume Harari over 5 years
    Hello, do I have to be on the same domain to do it ?
  • Stranger in the Q
    Stranger in the Q over 5 years
  • Dan Atkinson
    Dan Atkinson over 4 years
    It should be noted that dispatchEvent is supported in all major browsers. IE9 was the first version it came in, so most OSs now work with it. caniuse.com/#search=dispatchEvent
  • Avan
    Avan over 4 years
    I am not able to communicate from parent to iframe with this method.
  • radtek
    radtek about 4 years
    Yeah I can't get it to work either, the iframe js is loading after the parent window so it is not there to receive the msg when sent. it only works from iframe to parent for me.
  • Cannicide
    Cannicide almost 4 years
    There is a simple solution to that Avan and @radtek. All you have to do is first dispatch an event from the iframe to the parent that notifies the parent that the iframe is loaded (essentially a "ready message"). The parent will be listening for messages and if it receives the "ready message" event, it can then reply to the iframe with whatever message you want to send. That way it sends the message to the iframe only once the iframe is loaded. And of course the iframe page will only send the message to the parent once it is loaded.
  • radtek
    radtek almost 4 years
    Already figured it out sometime ago, made a prototype repo - github.com/radzhome/django_sso_service
  • Alex Filatov
    Alex Filatov over 3 years
    I've done same thing for VSCode, see my blog post alfilatov.com/posts/…
  • Alex Filatov
    Alex Filatov over 3 years
    not too informative, I've tried to descrive the process in my blog post alfilatov.com/posts/…
  • flyingace
    flyingace about 3 years
    As of this writing, March of 2021, cross-browser support for window.onmessage is not complete: developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers‌​/…
  • flyingace
    flyingace about 3 years
    As of this writing, March of 2021, cross-browser support for window.onmessage is not complete: developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers‌​/…
  • Jérôme Beau
    Jérôme Beau about 3 years
    I tested it and it works only for same origin frames. Cross-origin will result in a SecurityError when accessing window.parent
  • ch271828n
    ch271828n almost 3 years
    @user123444555621 hey that's onmessage not onmesage :) I copy-and-paste and it does not work then i see this bug
  • kevlened
    kevlened over 2 years
    @flyingace The only caveat I'm aware of is cross-domain iframe messaging on IE. Are you aware of any gaps between modern browsers?
  • Gal Bracha
    Gal Bracha almost 2 years
    Make sure when you set the iframe to add the following for this to work: <iframe sandbox="allow-scripts allow-same-origin" src="..."></iframe>
  • Michael Freidgeim
    Michael Freidgeim almost 2 years
    Does dispatchEvent better then postMessage? From the answer stackoverflow.com/questions/30183600/… postMessage is safer and support cross-domains