What's the most concise cross-browser way to access an <iframe> element's window and document?

14,835

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.

Share:
14,835

Related videos on Youtube

Bungle
Author by

Bungle

Front-End Developer. #SOreadytohelp

Updated on April 23, 2022

Comments

  • Bungle
    Bungle about 2 years

    I'm trying to figure out the best way to access an <iframe> element's window and document 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 of document.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 access iframe.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 to document or whether there is such a property as contentDocument.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>'s window and document properties in a cross-browser way (without the use of jQuery or other libraries)?

    Thanks for any help!

  • Bungle
    Bungle almost 14 years
    Thanks, 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 the window and document objects?
  • yodabar
    yodabar over 12 years
    The one-line solution I posted takes into account all these considerations :)
  • Dagg Nabbit
    Dagg Nabbit over 10 years
    The 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 (assuming iframe is an iframe element, it won't have a document property unless someone stuck it there). Apparently this would not work in Safari circa 2004. What's wrong with frames?
  • Dagg Nabbit
    Dagg Nabbit over 10 years
    Also, the mixed use of a ternary and short-circuiting || operator makes this unnecessarily unwieldy. Above comment aside, why not just write var doc = iframe.contentDocument || iframe.contentWindow.document || iframe.document;?
  • yodabar
    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, then iframe.contentWindow.document is. If you want to check the existence of the contentWindow property and its document sub-property, you may do that indeed, but my tests on different browsers shown that if contentDocument property is not set then contentWindow and contentWindow.document are.
  • Dagg Nabbit
    Dagg Nabbit over 10 years
    My point was that iframe.contentWindow.document || iframe.document is not useful for two reasons: 1, iframe elements don't have a document property, and 2, iframe.contentWindow.document shouldn't ever evaluate to false. If iframes have a contentWindow window property then it will surely have a document property, but if they don't have contentWindow it will throw a ReferenceError, so iframe.document is never evaluated anyway. The whole thing could be written as var doc = iframe.contentDocument || iframe.contentWindow.document
  • yodabar
    yodabar over 10 years
    Ok, I understand your point. Yes, if iframe.contentWindow.document is not set, then the reference error interrupts the execution and iframe.document would never got returned. There should be another ternary operator, I will correct my answer. Regarding iframe.document, it is not a standard, but allows the code to work in IE5 (you know how IE is tricky).
  • Dagg Nabbit
    Dagg Nabbit over 10 years
    Are you sure iframe.document works in IE5? I can't find any record of it, but I did find people saying that only window.frames would work in that version of IE, here.
  • yodabar
    yodabar over 10 years
    Sure 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
    Dagg Nabbit over 10 years
    That 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
    yodabar over 10 years
    Getting 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
    yodabar over 10 years
    Using some source code search engines I find various scripts using document.getElementById('iframe').document; try searching iframe.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
    Dagg Nabbit over 10 years
    Hehe, 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.