javascriptjqueryiframenestedpostmessage

how to use postMessage to communicate from nested iFrames to the root document?


I'm developing a plugin which has to manage fairly complex pages with nested iframes like this:

page.html
<body>
 <iframe A>
  <iframe B>
   <div bla></div>
  </iframe>
 </iframe>
 <iframe C>
   <div foo></div>
 </iframe>
</body>

The plugin will run in multiple instances (one on the main page, one for each iFrame). To inform iFrames about the root instance, I'm passing the root URL as a parameter when generaring the iFrame like so:

 ...
 newHTML = document.createElement("iframe");
 newHTML.setAttribute("src", options.src + "?" + priv.encodeURI(rootPath));

So the iFrame will be loaded with a URL like this:

 http://www.path/to/iFrame.html?base=...encodeURI(window.location.href.of.root)

My problem is, I need to postMessage from a nested iFrame to the root and I cannot get it to work. Here is what I'm doing:

// sending a message
var adressArray = window.location.href.split("?");
options.src = options.src || adressArray[0];
window.postMessage(options, options.src);

// receiving
window.addEventListener("message", receiveMessage, false);

function receiveMessage(event) {
  console.log(event.data);
  console.log(event.origin);
  console.log(window);
}

My problem is, both the call and the listener are in the same plugin, but should listen in different instances of the plugin. So the postmessage will be fired by the instance of frame B for example and the listener on my page.html instance should detect the message.

I thought the targetOrigin property was to specify the destination of where the postMessage should be sent to. Instead I'm ending up sending the URL of my posting iFrame (B), which gets recorded by the parent iFrame (A) instead of the page.html instance listening for it.

Question:
Is it possible to send a postMessage "across" two (or any number of) parents, without articifially "bubbling" it up the tree? Say the instance of iFrame B wants to say "Hello" to the instance of page.html, how would I do this using postMessage, when I can make the "root instance URL" available to every iFrame?

Thanks!

Question:


Solution

  • window.top seems to be my friend as it returns the top-most window element.

    When I postMessage to:

    var top = window.top;
    top.postMessage("foo", currentFrameUrl);
    

    it's working correctly.

    I will continue passing the URL though, because on cross domain iFrames, window.top will surely not work...