How to stop Javascript from running until an iFrame’s DOM is ready

We’ll start by writing a generic ready() function which can be reused for any document, be it the main window‘s one or one within an iFrame.

1const ready = (doc, callback) => {
2 if (doc.readyState !== 'loading') { return callback() }
3 return doc.addEventListener('DOMContentLoaded', callback)
4}

The above checks if the document passed is still in the loading phase1. If it is, then an event listener will be added to trigger the callback once DOMContentLoaded is fired2. If it is not, then the callback will be run there and then.

Next we need to query the document within the iFrame. This should be done once the iFrame’s parent document is ready.

1const iframe = document.querySelector('.my-iframe')
2const iframeDoc = iframe.contentDocument
3
4// Or, if ie8 support is needed:
5
6const iframe = document.querySelector('.my-iframe')
7const iframeDoc = iframe.contentDocument || iframe.contentWindow.document

Now that we have the iFrame’s document, let’s make use of it. Just below the above snippet, call the ready() function.

1ready(iframeDoc, iframeScripts)

All that’s left to do is create the iframeScripts() function.

1const iframeScripts = () => {
2 // The iFrame has loaded.
3 // Do things here...
4}

Pieced together, the above snippets should look something like this in your file.

1const ready = (doc, callback) => {
2 if (doc.readyState !== 'loading') { return callback() }
3 return doc.addEventListener('DOMContentLoaded', callback)
4}
5
6const mainScripts = () => {
7 // Do things...
8
9 // Listen to the iFrame's document.
10 const iframe = document.querySelector('.my-iframe')
11 const iframeDoc = iframe.contentDocument
12 ready(iframeDoc, iframeScripts)
13}
14
15const iframeScripts = () => {
16 // The iFrame has loaded.
17 // Do things here...
18}
19
20ready(document, mainScripts)