Basically, I have an iframe
embedded in a page and the iframe
has some JavaScript routines I need to invoke from the parent page.
Now the opposite is quite simple as you only need to call parent.functionName()
, but unfortunately, I need exactly the opposite of that.
Please note that my problem is not changing the source URL of the iframe
, but invoking a function defined in the iframe
.
The IFRAME should be in the
frames[]
collection. Use something likeThere are some quirks to be aware of here.
HTMLIFrameElement.contentWindow
is probably the easier way, but it's not quite a standard property and some browsers don't support it, mostly older ones. This is because the DOM Level 1 HTML standard has nothing to say about thewindow
object.You can also try
HTMLIFrameElement.contentDocument.defaultView
, which a couple of older browsers allow but IE doesn't. Even so, the standard doesn't explicitly say that you get thewindow
object back, for the same reason as (1), but you can pick up a few extra browser versions here if you care.window.frames['name']
returning the window is the oldest and hence most reliable interface. But you then have to use aname="..."
attribute to be able to get a frame by name, which is slightly ugly/deprecated/transitional. (id="..."
would be better but IE doesn't like that.)window.frames[number]
is also very reliable, but knowing the right index is the trick. You can get away with this eg. if you know you only have the one iframe on the page.It is entirely possible the child iframe hasn't loaded yet, or something else went wrong to make it inaccessible. You may find it easier to reverse the flow of communications: that is, have the child iframe notify its
window.parent
script when it has finished loaded and is ready to be called back. By passing one of its own objects (eg. a callback function) to the parent script, that parent can then communicate directly with the script in the iframe without having to worry about what HTMLIFrameElement it is associated with.If the iFrame and the containing document is on a different domain, the methods previously posted might not work, but there is a solution:
For example, if document A contains an iframe element that contains document B, and script in document A calls postMessage() on the Window object of document B, then a message event will be fired on that object, marked as originating from the Window of document A. The script in document A might look like:
To register an event handler for incoming events, the script would use addEventListener() (or similar mechanisms). For example, the script in document B might look like:
This script first checks the domain is the expected domain, and then looks at the message, which it either displays to the user, or responds to by sending a message back to the document which sent the message in the first place.
via http://dev.w3.org/html5/postmsg/#web-messaging
Just for the record, I've ran into the same issue today but this time the page was embedded in an object, not an iframe (since it was an XHTML 1.1 document). Here's how it works with objects:
(sorry for the ugly line breaks, didn't fit in a single line)
Quirksmode had a post on this.
Since the page is now broken, and only accessible via archive.org, I reproduced it here:
IFrames
On this page I give a short overview of accessing iframes from the page they’re on. Not surprisingly, there are some browser considerations.
An iframe is an inline frame, a frame that, while containing a completely separate page with its own URL, is nonetheless placed inside another HTML page. This gives very nice possibilities in web design. The problem is to access the iframe, for instance to load a new page into it. This page explains how to do it.
Frame or object?
The fundamental question is whether the iframe is seen as a frame or as an object.
top.frames[1].frames[2]
and such). Does the iframe fit into this frame hierarchy?document.getElementById('theiframe'))
to access it. In general browsers allow both views on 'real' (hard-coded) iframes, but generated iframes cannot be accessed as frames.NAME attribute
The most important rule is to give any iframe you create a
name
attribute, even if you also use anid
.Most browsers need the
name
attribute to make the iframe part of the frame hierarchy. Some browsers (notably Mozilla) need theid
to make the iframe accessible as an object. By assigning both attributes to the iframe you keep your options open. Butname
is far more important thanid
.Access
Either you access the iframe as an object and change its
src
or you access the iframe as a frame and change itslocation.href
.document.getElementById('iframe_id').src = 'newpage.html'; frames['iframe_name'].location.href = 'newpage.html'; The frame syntax is slightly preferable because Opera 6 supports it but not the object syntax.
Accessing the iframe
So for a complete cross–browser experience you should give the iframe a name and use the
syntax. As far as I know this always works.
Accessing the document
Accessing the document inside the iframe is quite simple, provided you use the
name
attribute. To count the number of links in the document in the iframe, doframes['testiframe'].document.links.length
.Generated iframes
When you generate an iframe through the W3C DOM the iframe is not immediately entered into the
frames
array, though, and theframes['testiframe'].location.href
syntax will not work right away. The browser needs a little time before the iframe turns up in the array, time during which no script may run.The
document.getElementById('testiframe').src
syntax works fine in all circumstances.The
target
attribute of a link doesn't work either with generated iframes, except in Opera, even though I gave my generated iframe both aname
and anid
.The lack of
target
support means that you must use JavaScript to change the content of a generated iframe, but since you need JavaScript anyway to generate it in the first place, I don't see this as much of a problem.Text size in iframes
A curious Explorer 6 only bug:
When you change the text size through the View menu, text sizes in iframes are correctly changed. However, this browser does not change the line breaks in the original text, so that part of the text may become invisible, or line breaks may occur while the line could still hold another word.