Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect DOMContentLoaded in iframe

I was surprised to find the following doesn't appear to work, insofar as the DOMContentLoaded event doesn't fire (this.els is an object of elements).

this.els.stage_ifr.prop('src', 'templates/'+ee.globals.creating+'/item'+this.id);
this.els.stage_ifr[0].addEventListener('DOMContentLoaded', function() {
    alert('loaded!');
}, false);

The page loads into the iframe fine, but no callback. The DOM level zero onload, however, works.

this.els.stage_ifr[0].onload = function() { alert('loaded!'); }; //<-- fires

A workaround is to prepare a globally-accessible jQuery deferred object in the parent page and resolve it via a DOM-ready event fired from the page called into the iframe, rather than listening for DOM-ready from the parent.

Paraent page:

dfd = new $.Deferred;
dfd.done(function() { alert("frame page's DOM is ready!"); });

Frame page:

$(function() { window.parent.dfd.resolve(); });

Nonetheless it would be good to know what's up with the first approach...

like image 925
Mitya Avatar asked Jun 06 '13 11:06

Mitya


People also ask

How do I know if I am DOMContentLoaded?

If you want to know "exactly" if DOMContentLoaded was fired, you could use a boolean flag like this: var loaded=false; document. addEventListener('DOMContentLoaded',function(){ loaded=true; ... }

How can I tell if an iframe page is loaded?

Comparing the object's location with the window object's parent location: Here, we simply compare the object's location with the window object's parent location. If the result is true, then the webpage is in an iFrame. If it is false, then it is not in an iFrame.

What triggers DOMContentLoaded?

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

Does DOMContentLoaded wait for scripts?

DOMContentLoaded and styles External style sheets don't affect DOM, so DOMContentLoaded does not wait for them. The reason for this is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above.


1 Answers

In the process of answering this question, I discovered the reason your DOMContentLoaded event listener doesn't work. It appears to me that you have two issues.

First, you're trying to listen for the DOMContentLoaded event on the iFrame itself. That isn't an iFrame event. It is a document event. So you have to reach into the iFrame to get the contentWindow and then get the document from that. That leads into the second issue.

Second, when an iFrame is first created, it has a dummy document in it that is NOT the same document as will eventually be there when dynamic content is loaded via the .src attribute. So, even if you did:

this.els.stage_ifr.contentWindow.document

to get the document in the iFrame, it will not necessarily be the right document and thus the DOMContentLoaded event won't fire on it (I've seen this behavior in Chrome).


MDN says that one can listen for the DOMFrameContentLoaded event on the iFrame itself and this will correspond with when the underlying document actually gets DOMContentLoaded. Unfortunately, I can't get this event to work in any browser. So, at this moment, the only work-around I know of is to either trigger the load event from within the iFrame itself where it can listen to its own DOMContentLoaded event (it can call out to the parent window if need be) or to just listen for the load event on the iFrame object and know that it won't fire until resources such as style sheets and images in the iFrame are also loaded.


Anyway, I thought I'd explain some of what was going on with your initial code and offer another solution even though this question was posted more than a year ago (though never answered).


Update:

I've developed a method of tracking DOMContentLoaded for an iFrame loaded with the same origin as its parent. You can see the code here.

like image 137
jfriend00 Avatar answered Sep 21 '22 03:09

jfriend00