What's the most concise cross-browser way to access an <iframe> element's window and document?
Solution 1
During the time I made many tests, and finally came up with this short but robust syntax which works on every browser I could test:
var doc = iframe.contentDocument ?
iframe.contentDocument : (iframe.contentWindow.document || iframe.document);
EDIT: @DaggNabbit noticed that a reference error in iframe.contentWindow.document
, if iframe.contentWindow
is not set, would block the code execution, not allowing iframe.document
to be returned.
So I refined my code:
var doc = iframe.contentDocument ?
iframe.contentDocument :
(iframe.contentWindow ? iframe.contentWindow.document : iframe.document);
NOTE: iframe.document
is a workaround for IE5.
Solution 2
There's an easier way that's been around longer... use window.frames
to get a reference to the frame's window object.
By name or id:
var iframe_doc = window.frames.my_iframe.document;
or if you prefer:
var iframe_doc = window.frames['my_iframe'].document;
or by index:
var iframe_doc = window.frames[0].document;
Good reference for window.frames
here: http://developer.mozilla.org/en/DOM/window.frames
An excerpt:
each item in the window.frames pseudo-array represents the window object corresponding to the given <frame>'s or <iframe>'s content, not the (i)frame DOM element (i.e. window.frames[ 0 ] is the same thing as document.getElementsByTagName( "iframe" )[ 0 ].contentWindow)
Solution 3
all of the modern browsers except Chrome support both iframereference.contentWindow
and iframereference.contentDocument
, but only if the page opened in the iframe is on the same domain as the page containing the iframe.
To include Chrome, use var iwin=iframereference.contentWindow,
idoc=iwin.document;
.contentDocument
is the window.document
of the page in the iframe,
as is contentWindow.document
, but not .contentDocument.document
.
Chrome may include support for .contentDocument
in some future version- I hope so, because it is also the way all the other browsers find the document contained in an Object element, type text/html
, where the data attribute is the url of an html page.
Related videos on Youtube
Comments
-
Bungle about 2 years
I'm trying to figure out the best way to access an
<iframe>
element'swindow
anddocument
properties from a parent page. The<iframe>
may be created via JavaScript or accessed via a reference stored in an object property or a variable, so, if I understand correctly, that rules out the use ofdocument.frames
.I've seen this done a number of ways, but I'm unsure about the best approach. Given an
<iframe>
created in this way:var iframe = document.createElement('iframe'); document.getElementsByTagName('body')[0].appendChild(iframe);
I'm currently using this to access the
document
, and it seems to work OK across the major browsers:var doc = iframe.contentWindow || iframe.contentDocument; if (doc.document) { doc = doc.document; }
I've also see this approach:
var iframe = document.getElementById('my_iframe'); iframe = (iframe.contentWindow) ? iframe.contentWindow : (iframe.contentDocument.document) ? iframe.contentDocument.document : iframe.contentDocument; iframe.document.open(); iframe.document.write('Hello World!'); iframe.document.close();
That confuses me, since it seems that if
iframe.contentDocument.document
is defined, you're going to end up trying to accessiframe.contentDocument.document.document
.There's also this:
var frame_ref = document.getElementsByTagName('iframe')[0]; var iframe_doc = frame_ref.contentWindow ? frame_ref.contentWindow.document : frame_ref.contentDocument;
In the end, I guess I'm confused as to which properties hold which properties, whether
contentDocument
is equivalent todocument
or whether there is such a property ascontentDocument.document
, etc.Can anyone point me to an accurate/timely reference on these properties, or give a quick briefing on how to efficiently access an
<iframe>
'swindow
anddocument
properties in a cross-browser way (without the use of jQuery or other libraries)?Thanks for any help!
-
Bungle almost 14 yearsThanks, kennebec! So, I did some testing keeping in mind your feedback. It actually looks like IE (at least IE 7) is the straggler on contentDocument; Chrome appeared to support it. Would
var win = iframe.contentWindow; var doc = iframe.contentDocument || iframe.contentWindow.document;
be a sufficient and stable cross-browser (back to IE 6) check for thewindow
anddocument
objects? -
yodabar over 12 yearsThe one-line solution I posted takes into account all these considerations :)
-
Dagg Nabbit over 10 yearsThe last part of this condition seems fishy. It assumes
iframe.contentWindow
exists by referencing a property of it. If it doesn't exist, it will throw a ReferenceError, and the|| iframe.document
part will never execute. Even if|| iframe.document
does execute, it probably won't do anything useful (assumingiframe
is an iframe element, it won't have adocument
property unless someone stuck it there). Apparently this would not work in Safari circa 2004. What's wrong withframes
? -
Dagg Nabbit over 10 yearsAlso, the mixed use of a ternary and short-circuiting
||
operator makes this unnecessarily unwieldy. Above comment aside, why not just writevar doc = iframe.contentDocument || iframe.contentWindow.document || iframe.document;
? -
yodabar over 10 years@DaggNabbit thanks for your clarification: "It assumes iframe.contentWindow exists by referencing a property of it": no, it means that if
iframe.document
is not set, theniframe.contentWindow.document
is. If you want to check the existence of thecontentWindow
property and itsdocument
sub-property, you may do that indeed, but my tests on different browsers shown that ifcontentDocument
property is not set thencontentWindow
andcontentWindow.document
are. -
Dagg Nabbit over 10 yearsMy point was that
iframe.contentWindow.document || iframe.document
is not useful for two reasons: 1, iframe elements don't have adocument
property, and 2,iframe.contentWindow.document
shouldn't ever evaluate to false. If iframes have acontentWindow
window property then it will surely have adocument
property, but if they don't havecontentWindow
it will throw a ReferenceError, soiframe.document
is never evaluated anyway. The whole thing could be written asvar doc = iframe.contentDocument || iframe.contentWindow.document
-
yodabar over 10 yearsOk, I understand your point. Yes, if
iframe.contentWindow.document
is not set, then the reference error interrupts the execution andiframe.document
would never got returned. There should be another ternary operator, I will correct my answer. Regardingiframe.document
, it is not a standard, but allows the code to work in IE5 (you know how IE is tricky). -
Dagg Nabbit over 10 yearsAre you sure
iframe.document
works in IE5? I can't find any record of it, but I did find people saying that onlywindow.frames
would work in that version of IE, here. -
yodabar over 10 yearsSure mate, there are some libraries using this solution; for example scheduler.js; look at row 217: scheduler.cfunited.com/js/scheduler.js Cheers!
-
Dagg Nabbit over 10 yearsThat code looks pretty sketchy to me... assigning values to undeclared variables, calling functions which don't exist (
addEvent
), dumping everything in the global scope. Honestly I'm not sure how that code can even work; I guess it must depend on some other code? Now I'm really curious about iframe.document in ie5, maybe I'll see if I can get it to run under wine or something. -
yodabar over 10 yearsGetting a demonstration of that code is an interest of mine, too! I hope I can reproduce the environment to test it, or, alternatively, finding useful information to clarify if it works or not in IE5. Just for confirmation that the normal known methods do not work, here's a test which states the solution does NOT work on IE5 (but works on IE5.5 and greater): xkr.us/articles/dom/iframe-document
-
yodabar over 10 yearsUsing some source code search engines I find various scripts using
document.getElementById('iframe').document
; try searchingiframe.document
on meanpath.com or code.ohloh.net I also tried search.nerdydata.com but it does not search for the exact string entered. -
Dagg Nabbit over 10 yearsHehe, I tried searching around too, but couldn't find anything. Even if it does work, I'd probably just stick to
window.frames
which has worked everywhere since the dawn of interwebs.