Remotely exchange data between iFrame and parent (jQuery .vs. HTML5)
Posted by bcmoney on November 17, 2010 in AJAX, HTML, JavaScript with No Comments

One of the many nagging web development problems that the HTML5 working group is addressing with the new HTML specification, is the difficulty in working with content or exchanging data in between an iFrame and the main (origin) page which embeds it, as well as across separate windows (tabs) and domains.
jQuery
In order to accomplish the exchange of data between iFrames, while we wait for more browsers to support the new Communications section of the HTML5 spec (more specifically the postMessage function), the following is a quick way to make the communication magic happen with the convenience of jQuery:
<!DOCTYPE html> <html> <head> <title>Remote iFrame communication - jQuery</title> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script> </head> <body> <iframe id="frameDemo" name="frameDemo" src="test.html" width="80%" height="200"></iframe> <script type="text/javascript"> function getIframeContents(selector){ $("#frameDemo").load(function(){ response = $("#frameDemo").contents().find(selector).html(); alert(response); $("#responses").html(response).show(); }); } getIframeContents("#test"); </script> </body> </html>
-OR-
Don’t blink, immediately on page load this demo will extract the contents of the “test” <div> from the framed HTML document (using the getIframeContent function), output the value it extracted to the parent HTML document’s DOM (also via an alert, just to make sure you didn’t miss it), then change the value that <div> to something else we specify (using the setIframeContent function).
This can be useful for extracting or passing data from widgets and with other self-contained code that you don’t necessarily want to run within your main page, but from which you might want to snag or update some data. It has possibly lots of other practical uses, for example if you were building a news reader you could use an RSS feed’s link to pull the full content of the link and display it without the user having to leave the page.
NOTE: Though the getting of content should work fine it may require a server-side proxy to grab the content first through a proxied AJAX request, depending on the browser(s) you want to support. Of course, the setting content of the iFrame part will only work if the page is on the same domain as your calling page, due to the same-origin policy restriction, which is unfortunately in place for a good reason.
JavaScript
What if you don’t have access to jQuery for licensing or dependency limitations at work, or have been hiding under a rock and don’t really know what jQuery is or how to use it? In order to do the same thing in plain-old, vanilla, pure JavaScript without the benefit of full cross-browser support of jQuery, we can still accomplish this by refactoring as in the following:
<!DOCTYPE html> <html> <head> <title>Remote iFrame communication - JS</title> </head> <body> <iframe id="remoteFrame" name="remoteFrame" src="test.html" width="80%" height="200"> Error loading iFrame! </iframe> <div id="responses"> ... </div> <script type="text/javascript"> function getIframeContents(id) { var frame = document.getElementById('remoteFrame'); var response = childGetElementById(id); var incoming = response.innerText||response.textContent; alert(incoming); document.getElementById('responses').innerHTML = '<b>remoteFrame said:</b> "'+(incoming)+'"'; } function setIframeContents(id, msg) { var frame = document.getElementById('remoteFrame'); var content = frame.contentDocument || frame.contentWindow.document; content.getElementById(id).innerHTML = msg; } function childLoaded() { getIframeContents('remoteIframeData'); setIframeContents('remoteIframeData', '<b>parentFrame said:</b> Goodbye!'); } </script> </body> </html>
You then need to add the following additional JavaScript “wake-up call” to the child iFrame:
parent.childGetElementById = function (id){ return document.getElementById(id); }; parent.childLoaded();
-OR-
HTML5
Just for completeness’ sake, here’s how you’ll eventually be able to accomplish the same effect cross-browser, once the HTML5 specification is finalized and fully supported by the modern browsers (not to mention when legacy browsers like IE6/7/8 are long gone, which is hopefully sooner rather than later). The exciting thing is that this should work on mobile device browsers that implement the HTML5 spec as well (can you say goodbye SMS and texting plans?!? I can only wish).
<!DOCTYPE html> <html lang="en"> <head> <title>HTML5 postMessage (cross domain) <style type="text/css"> iframe { width: 100%; border: 2px solid #ccc; } </style> </head> <body><script type="text/javascript"> var theFrame = document.getElementById("frameDemoHTML5").contentWindow; var onmessage = (function(e) { document.getElementById('responses').innerHTML = e.data + " (received on: '" + document.location + "' from: '" + e.origin + "')"; console.log(e.data + "(from: " + e.origin + ")"); setTimeout(function(){ theFrame.postMessage("Goodbye... thanks for coming!", "http://www.bryancopeland.com")} , 2500); //set allowed origin(s) return; }); if (typeof window.addEventListener != 'undefined') { window.addEventListener('message', onmessage, false); } else if (typeof window.attachEvent != 'undefined') { window.attachEvent('onmessage', onmessage); } </script> </body> </html> <iframe id="frameDemoHTML5" src="http://bcmoney-mobiletv.com/blog/wp-content/uploads/2010/11/postMessage.html"></iframe>
-OR-
(that download is the same as the one above, I just tossed all the files you’ll need in the same zip…)
Let’s not forget the file from JSBin which has the logic to do the 2-way communication between child iFrame and parent window which embeds the iFrame.
The only weakness of this approach is that you need to have control of the file on the remote domain, or, convince the owners to add in the required messaging code to respond to incoming messages from your domain. Lastly, note how the ability to check the origin functions much the same way as Flash’s crossdomain.xml, which is actually one of the few things I think Flash got right in terms of security and sandboxing requests to whitelisted domains.
Related articles
- Using Javascript postMessage to Talk to iFrames (viget.com)
- HTML5 Can Get the Job, But Can HTML5 Do the Job? (readwriteweb.com)
- These Are The HTML5 Apps That Are Scaring The Pants Off Apple (AAPL) (businessinsider.com)
- 30 Must See HTML5 Tutorials (spyrestudios.com)
- jQuery: Load Page in a Div (devcurry.com)
- Using HTML5 postMessage (ajaxian.com)
- What is HTML5? (radar.oreilly.com)

Tags: HTML5, iFrame, JQuery, postMessage