Is there any equivalent of "$(document).ready()" with pure Javascript?

Question:

In jQuery, we need to use $(document).ready() to know if the document has loaded and then safely run our jQuery script.

According to jQuery documentation

A page can't be manipulated safely until the document is "ready." jQuery detects this state of readiness for you.

Translation:

The page cannot be safely manipulated until the document is "ready". jQuery detects this state of readiness for you.

Now, in the case of pure Javascript, without jQuery or any other framework, is there any way to detect that the document has been loaded, to have the same guarantee we have with $(document).ready() ?

Answer:

What jQuery does is read the document.readyState property when the page loads, and if it's not already loaded, it listens for one of the load or DOMContentLoad events. The first event to be called triggers the ready .

In practice, simplifying it would be like this ( jsFiddle ):

function ready() {
    // quando esta função correr o DOM está acessível
}

function completed() {
    document.removeEventListener("DOMContentLoaded", completed);
    window.removeEventListener("load", completed);
    ready();
}

if (document.readyState === "complete" ||
    (document.readyState !== "loading" && !document.documentElement.doScroll)) {
    ready(); // está pronto!
} else { // ainda não está pronto...
    document.addEventListener("DOMContentLoaded", completed);
    window.addEventListener("load", completed);
}

IE 8 had a bug with the scroll and that's why this line refers to Scroll. There is a very good article about it ( link ), but as IE8 is no longer supported it can be removed.

The MooTools version is similar, a little more complex and therefore more complete, and uses MooTools' internal event mechanism. It also takes into account older browsers that do not have readystatechange . But that doesn't matter nowadays.


For modern browsers this can be done ( link ):

var domReady = function(ready) {
    if (document.readyState != 'loading') return ready();
    document.addEventListener('DOMContentLoaded', ready);
    function _ready() {
        document.removeEventListener('DOMContentLoaded', ready);
        ready();
    }
}

For older browsers this could be done ( link ), keeping it simple:

var domReady = function(ready) {
    var attacher = document.addEventListener ? {
        add: 'addEventListener',
        remove: 'removeEventListener'
    } : {
        add: 'attachEvent',
        remove: 'detachEvent'
    };

    function completed() {
        document[attacher.remove]("DOMContentLoaded", completed);
        window[attacher.remove]("load", completed);
        ready();
    }

    if (document.readyState === "complete" ||
        (document.readyState !== "loading" && !document.documentElement.doScroll)) {
        ready(); // está pronto!
    } else { // ainda não está pronto...
        document[attacher.add]("DOMContentLoaded", completed);
        window[attacher.add]("load", completed);
    }
}
Scroll to Top