Accessing Html Document Content in other Frames
Here’s a question that I see pop up quite frequently on newsgroups: How do I access content across frames or an iFrame using JavaScript code? It’s actually quite easy once you understand how the windowing mechanism in the browser works.
Imagine you have two pages – one that holds an iFrame and another that holds the content for the iFrame. Both the host page and the iFrame contain a <div id=”message”> tag that is used to write some content into the other frame.
Here’s the top level page:
<div class="errordisplay" id="message"> original </div> <iframe src="FramesPage2.aspx" id="frame1" height="400"> </iframe> <script type="text/javascript"> window.onload = function() { var frame = document.getElementById("frame1"); var msg = frame.contentDocument.getElementById("message"); msg.innerHTML = "Hello World from Frame Page 1"; }; </script>
And here the iFrames source page that gets loaded into the iFrame:
<div class="errordisplay" id="message"> original </div> <script type="text/javascript"> var msg = window.parent.document.getElementById("message"); msg.innerHTML = "Updated from iFrame"; </script>
The above works both with iFrames, Frames or separate windows that were loaded from the current window.
From the top level window that contains the iFrame you start by getting a reference to the iFrame by using plain old getElementById to select the iFrame by Id. Alternately you can also access the frame via window.frames[0] (or appropriate numeric index). Once the iFrame is selected you can use the contentDocument property to access the child frame content. From there you can access document methods as you normally would – in this case by using getElementById() and then assigning some HTML to the display <div> tag in the child frame.
In the child frame to reference back to the parent frame is easier yet: You can use the window.parent property to get a reference to the parent frame. You can then simply reference the document and continue on accessing elements in the parent document.
Cross Frame Functions
The previous code is - ahem - functional, but realistically accessing cross frame elements is probably not something you should do extensively. When you control elements in another browser window you are stuck with directly coding against the DOM – using libraries like jQuery for example isn’t possible since tools like it work against content in the current window.
If your interaction is any more complex that say grabbing or setting a single value , it’s probably better to create functions in the target frame and call these functions across the frame border rather than the individual DOM commands individually. That way you can encapsulate the functionality in the child page, which makes it easier to code and test the functionality, and it also allows you to use any libraries the way you normally would. You can then simply call the function from the parent page to perform more complex tasks indirectly.
To call a function across frames is fairly easy. Assume that the iFrame code I showed earlier also includes a function called showMessage in script code that updates it’s internal message <div> tag like this:
<script type="text/javascript"> function showMessage(m) { document.getElementById("message").innerHTML = m; } </script>
To call this function from the parent frame you can use a couple of approaches. The easiest is to use the frames collection:
<script type="text/javascript"> window.onload = function() { window.frames[0].showMessage("Hello from Main Page in iFrame"); }; </script>
The individual frame is essentially a reference to the window object in the child frame and all global JavaScript functions are functions off the window object. So you can directly call the function of the frame. Easy. The main issue with this that you need to know (or find) the frame index first.
You can also get it through the frame DOM element in the parent page and use its contentWindow property to get at the child window:
<script type="text/javascript"> window.onload = function() { var frame = document.getElementById("frame1"); var win = frame.contentWindow; win.showMessage("Hello from Main Page in iFrame"); }; </script>
and this works as well.
With the abillity to call functions it’s much easier to offload processing to other frames more efficiently which allows for creation of self contained modules that let you interact with only a few small interface points. For example, you can create window objects that load content dynamically and yet act independently and without interfering with each other.
The Voices of Reason
# re: Accessing Html Document Content in other Frames
# re: Accessing Html Document Content in other Frames
It is possible to communicate between pages from sub-domains by modifying the
document.domain property.
Look at http://blogs.msdn.com/dthorpe/archive/2007/09/27/cross-domain-communication-using-domain-lowering.aspx
# re: Accessing Html Document Content in other Frames
Everyone is correct, you cannot access anything in the frame if the contents are not sitting on the same domain as the parent. I am working on something right now at my job where we transfer to a banking application provided by our bank that handles credit card and echeck transactions. To keep them disconnected from our site while they were on the banking application, I wrote a "lightbox" style modal iframe. This banking application allows me to set a URL to redirect the user to when their transaction completed. The application also has an Exit/Cancel button that I also can set.
While I was unable to access the frame while the user was on the banking application, I still was able to control it immediately before and immediately after they were done. The initial page in the iframe sits on our server. It has a "Please wait..." message and automatically submits a form to this banking application onload. When they are done, they are redirected to a landing page on our server, where the necessary Javascript can safely be executed to close the lightbox. In my case, after closing the lightbox I programmatically did a postback with Javascript to do execute some server-side code a redirect them accordingly. It works real slick.
I just wanted to add this to let everyone know that you can still create an elegant and seamless transition to another application (from your application) using just Javascript and iframes. What's important is making sure the other application is capable of redirecting back to a landing page on your server.
Regards...
# re: Accessing Html Document Content in other Frames
# re: Accessing Html Document Content in other Frames
1. location.hash - Using hash property - see http://tagneto.blogspot.com/2006/06/cross-domain-frame-communication-with.html
2. window.name - see http://www.sitepen.com/blog/2008/07/22/windowname-transport/
3. Proxying the site in the same domain (bad design)
4. Inline scripts (can work on another domains) - and start using fully client centric operations(e.g script render and handled data and GUI) - This is hard.
5. flash local connection - see http://livedocs.adobe.com/flex/2/langref/flash/net/LocalConnection.html
6. and there are more like this
FYI - IE solves this by using new method of cross document messaging - see http://msdn.microsoft.com/en-us/library/cc511311(VS.85).aspx
Also don't forget that when running under IE you might not see cookies in the iframe because you are considered as 3rd party domain the solution is to add P3P headers to your site or be at Local intranet or Trusted zones see MSDN article - http://support.microsoft.com/kb/293222/)
More over guess you already know it but IFRAME are not XHTML 1.1 compliant, alternative is using OBJECT element.
lastly i would like to suggest reading a very nice research from Microsoft about the cross domain communication and solutions at http://research.microsoft.com/en-us/um/people/helenw/papers/subspace.pdf
# re: Accessing Html Document Content in other Frames
# re: Accessing Html Document Content in other Frames
1) location.hash isn't exactly elegant
2) window.name - looks like a giant hack
3) Proxying the site in the same domain - not ideal agreed
4) Inline scripts - great idea, but doesn't solve the problem of cross-domain scripting with a site that's not your own!
5) Flash local connection - same problem
Ultimately we have to face facts and admit that there are some things browsers just weren't designed to do - cross site scripting was designed to protect page content and therefore I'd say it's doing its job.
# re: Accessing Html Document Content in other Frames
Some links explaining this technique
http://rockstargirl.org/sandbox/bidynodes/
http://ajaxpatterns.org/On-Demand_Javascript#Technical_Story
It can be very useful in certain real-world scenarios, such as a catalog control/page on a central site that several related sites load, and is known to work on IE, Firefox, and WebKit (Safari/iPhone/gPhone/Palm Pre).
# re: Accessing Html Document Content in other Frames
iframe.contentWindow has better support though.
# re: Accessing Html Document Content in other Frames
# re: Accessing Html Document Content in other Frames
I tried the code first posted and it does what I want it to do in FireFox and Safari, but IE 8, when run from the server, gives me an error at the bottom of the browser window (doesnt' say what the error is, just that little yellow triangle and "error on page".) Funny thing is if I open the parent file in IE 8 locally, it works fine. Also tried uploading to a different server, and it works fine in IE. Does anyone know how I can tell my server to allow IE 8 to use this javascript code? (maybe with an .htaccess file?)
# re: Accessing Html Document Content in other Frames
Just so you are aware, the method you've suggested above only works when the iframe picks up content from the same domain as the page hosting the iframe.
In your example above, if you had <iframe src="http://google.com" />, you cannot manipulate the content (or even get the properties).
We had an site that was going to host pages from a sub-domain in our site. We were going to use javascript to re-size the iframe based on the content so it looked as if the iframe was actually part of the page. As soon as it came from a sub-domain, you could not get access to any of the document properties of the iframe. It did work if the page src was from the original domain.
Regards,
Grant