0

My web page has an iframe, and I change its src when the user clicks on a showNewPage button. I need to know when the browser has finished loading the DOM of the iframe, but without waiting for all the images to be downloaded.

var myIFrame = document.getElementById("myIframe")
var count = 0;
funcion showNewPage() {
  myIFrame.src = "http://example.com/page_" + count;
  count++;
}

This code calls doSomething() when the iframe has finished loading the DOM and all images:

myIFrame.addEventListener("load", function(event) { doSomething(); });

How to ask myIFrame to call doSomething() when the iframe has finished loading the DOM, but not yet all the images?


ps: There is an event DOMContentLoaded instead of load which achieves this; but this event is not available for an iframe. It's available only for a document or a window. Doing as follows does not work neither, because myIFrame.contentWindow returns null at the very beginning:

myIFrame.contentWindow.addEventListener("DOMContentLoaded", function(event) { doSomething(); });

ps: this other question does not answer my question, as it relies on onload event, which waits until all images are downloaded: How to detect when an iframe has already been loaded

David Portabella
  • 12,390
  • 27
  • 101
  • 182
  • Maybe place `DOMContentLoaded`on the iframe itself and make it output some hidden flag that the main window can communicate with? – A. Meshu Dec 18 '19 at 22:52
  • 1
    Does this answer your question? [How to detect when an iframe has already been loaded](https://stackoverflow.com/questions/17158932/how-to-detect-when-an-iframe-has-already-been-loaded) – ℛɑƒæĿᴿᴹᴿ Dec 18 '19 at 22:53
  • 1
    @A.Meshu, the iframe does not fire the `DOMContentLoaded` event; it only fires the `load` event. This is the issue. – David Portabella Dec 19 '19 at 07:22
  • @ℛɑƒæĿ, the question you mention uses the `onload` event, which is fired when all images finished downloading. I need to know when the DOM is loaded without waiting for all the images to be downloaded. – David Portabella Dec 19 '19 at 07:24

1 Answers1

1

As you found out, trying to get its .contentWindow before the iframe has been initialized will return null.

One way around this is to

  • initialize your frame with an empty document (about:blank),
  • get a reference to your iframe's contentWindow, this will always be the same object, however events we attach on it will get removed at every new navigation...
  • add an unload event listener (since it's the closest to the navigation)
  • wait just a frame so our contentWindow start the navigation
  • add your DOMContentLoaded and our unload event listeners so we can reiterate at next navigation

frame.onload = e => {
  const win = frame.contentWindow;
  frame.onload = null;
  win.addEventListener( 'unload', attachEvents );
  YOUR_CALLBACK(); // make it fire even at beginning?

  function attachEvents()  {
    setTimeout( () => {
      win.addEventListener( 'DOMContentLoaded', YOUR_CALLBACK );
      win.addEventListener( 'unload', attachEvents ); // do it again at next navigation
    }, 0 );
  };
};
frame.src = "about:blank";

As a fiddle since StackSnippets over-protected iframes don't allow us to access inner frames' content...

Kaiido
  • 123,334
  • 13
  • 219
  • 285