54

I'm trying to get the document object of an iframe, but none of the examples I've googled seem to help. My code looks like this:

<html>
    <head>
        <script>
            function myFunc(){
                alert("I'm getting this far");
                var doc=document.getElementById("frame").document;
                alert("document is undefined: "+doc);
            }
        </script>
    </head>
    <body>
        <iframe src="http://www.google.com/ncr" id="frame" width="100%" height="100%" onload="myFync()"></iframe>
    </body>
</html>

I have tested that I am able to obtain the iframe object, but .document doesn't work, neither does .contentDocument and I think I've tested some other options too, but all of them return undefined, even examples that are supposed to have worked but they don't work for me. So I already have the iframe object, now all I want is it's document object. I have tested this on Firefox and Chrome to no avail.

Vito Gentile
  • 13,336
  • 9
  • 61
  • 96
Dude Dawg
  • 1,465
  • 2
  • 15
  • 26
  • You just needed to highlight your markup and click the button which looks like `{}` to indent it as code. Ive edited your post to make it clearer. – Jamiec Sep 27 '11 at 14:08
  • 1
    Duplicate of [HTML: Getting document from IFrame](http://stackoverflow.com/questions/3999101/html-getting-document-from-iframe) and [Invoking javascript in iframe from parent page](http://stackoverflow.com/q/251420/94197). – Andy E Sep 27 '11 at 14:11
  • @Jamiec, thanks! I thought I had to click {} for every new line – Dude Dawg Sep 27 '11 at 14:31
  • @Andy E, I know it's a duplicate, but the other examples didn't work for me. – Dude Dawg Sep 27 '11 at 14:32

4 Answers4

82

Try the following

var doc=document.getElementById("frame").contentDocument;

// Earlier versions of IE or IE8+ where !DOCTYPE is not specified
var doc=document.getElementById("frame").contentWindow.document;

Note: AndyE pointed out that contentWindow is supported by all major browsers so this may be the best way to go.

Note2: In this sample you won't be able to access the document via any means. The reason is you can't access the document of an iframe with a different origin because it violates the "Same Origin" security policy

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 2
    AFAIK, all browsers support the non-standard `contentWindow` property, so it's safest just to go with that. – Andy E Sep 27 '11 at 14:13
  • @AndyE the documentation I could find didn't give a definitive yes / no on that. Do you have something I could reference? – JaredPar Sep 27 '11 at 14:14
  • only [the dottoro reference](http://help.dottoro.com/ljctglqj.php). It's references are usually (technically) correct. – Andy E Sep 27 '11 at 14:18
  • 1
    @DudeDawg you're running into a same origin violation here. You can't access the `document` of an iframe which comes from a different domain – JaredPar Sep 27 '11 at 14:45
  • @JaredPar, OK, then I understand what's wrong. I guess I'll try to work around the problem. – Dude Dawg Sep 27 '11 at 15:03
  • 2
    @Andy E, @JaredPar: I think it was older (pre-3.0) versions of Safari that didn't support `contentWindow` but did support `contentDocument`. `contentDocument` made it into a standard long before `contentWindow` (DOM 2 versus HTML5) so I used to favour that but now `contentWindow` is pretty much safe to use on its own. – Tim Down Sep 27 '11 at 15:12
  • @Tim: ah, thanks for clarifying. If anyone with Safari 2 reads this, well, then I guess they ought to think about upgrading their browser ;-) – Andy E Sep 27 '11 at 18:03
  • @Commenters, not even a +1 for my pre-Safari 2 safe code :-)? – James Hill Sep 27 '11 at 19:10
  • 1
    Is there a way of doing this in 2014 and all the modern browsers? – Andrei Sep 12 '14 at 15:21
6

For even more robustness:

function getIframeWindow(iframe_object) {
  var doc;

  if (iframe_object.contentWindow) {
    return iframe_object.contentWindow;
  }

  if (iframe_object.window) {
    return iframe_object.window;
  } 

  if (!doc && iframe_object.contentDocument) {
    doc = iframe_object.contentDocument;
  } 

  if (!doc && iframe_object.document) {
    doc = iframe_object.document;
  }

  if (doc && doc.defaultView) {
   return doc.defaultView;
  }

  if (doc && doc.parentWindow) {
    return doc.parentWindow;
  }

  return undefined;
}

and

...
var el = document.getElementById('targetFrame');

var frame_win = getIframeWindow(el);

if (frame_win) {
  frame_win.targetFunction();
  ...
}
...
Dominique Fortin
  • 2,212
  • 15
  • 20
6

This is the code I use:

var ifrm = document.getElementById('myFrame');
ifrm = (ifrm.contentWindow) ? ifrm.contentWindow : (ifrm.contentDocument.document) ? ifrm.contentDocument.document : ifrm.contentDocument;
ifrm.document.open();
ifrm.document.write('Hello World!');
ifrm.document.close();

contentWindow vs. contentDocument

  • IE (Win) and Mozilla (1.7) will return the window object inside the iframe with oIFrame.contentWindow.
  • Safari (1.2.4) doesn't understand that property, but does have oIframe.contentDocument, which points to the document object inside the iframe.
  • To make it even more complicated, Opera 7 uses oIframe.contentDocument, but it points to the window object of the iframe. Because Safari has no way to directly access the window object of an iframe element via standard DOM (or does it?), our fully modern-cross-browser-compatible code will only be able to access the document within the iframe.
James Hill
  • 60,353
  • 20
  • 145
  • 161
1

In my case, it was due to Same Origin policies. To explain it further, MDN states the following:

If the iframe and the iframe's parent document are Same Origin, returns a Document (that is, the active document in the inline frame's nested browsing context), else returns null.