Reputation: 26238
I've created a friendly iframe (same domain) and added it to the DOM with JavaScript. It's visible on my page. Inspecting the HTML looks like:
<iframe id="test_frame" frameSpacing="0" height="100" src="javascript:window['contents']" width="100" name="test_frame">
<!DOCTYPE html>
<html>
<head>
<title>test_frame</title>
<base target=_top>
</head>
<body style="margin: 0px; padding: 0px">
<p>Hello World</p>
</body>
</html>
</iframe>
Then I run the following in order to access the markup in the iframe's <body>
:
alert(window.frames["test_frame"].document.body.innerHTML);
which fails for Internet Explorer 6-10 because body
is null
. The document
object of the iframe exists, but appears to have no readable properties. Other browsers simply display the string <p>Hello World</p>
.
But interestingly, the following works in IE 6-10, and all other browsers:
window.setTimeout(function(){
alert(window.frames["test_frame"].document.body.innerHTML);
}, 1);
To my knowledge setTimeout
executes the passed function in the global scope. So I tried using call but it does not work:
(function(){
alert(window.frames["test_frame"].document.body.innerHTML);
}).call(window);
I have seen similar cases where wrapping code in a setTimeout resolves IE iframe difficulties. What is the mechanism or logic behind this in IE? Is there a proper workaround?
Above tests were run in standards mode, with no other errors than those stated.
Upvotes: 1
Views: 1276
Reputation: 27317
What is the mechanism or logic behind this in IE? Is there a proper workaround?
The mechanism is very simple: wait one milisecond (four; actually), then attempt to access the iFrame.
Timing is everything. If you call too soon, you will see an empty iFrame. Even if the src
is javascript code, you have to let the code run.
If you access the iFrame just after it is encountered in the DOM: most likely it will be empty. It has not been fetched from the Internet yet. Even if the src
is javascript:...
, the iFrame will be empty.
If you do it 1 millisecond after the page load, most likely it has not been fetched yet either. However, if it's in the browser cache (normally a page shouldn't be) or it's a data (or javascript, in your case) URL, however, this will likely work (nothing's granted, though). The document.body
element may already exist at this point - even if it's going to be empty.
The intended workflow is that you wait for the iFrame load
event. You can safely attach it just after you create the iFrame or set its src
. Finding a cross-browser set of events that messages this reliably is a tricky issue, but load
should work cross-browser.
If the load
event fails to be late enough, wait an extra millisecond. This should not be neccessary, but there might be a stupid bug in IE (I don't think there is).
It you are firing it from the console, this should be successful. Indeed, this has always been the case according to my observation.
Upvotes: 1