I'm trying to help developing a library and for it I'm trying to work with page loading.
In the process I want to make the library completely compatible with the use of defer and async.
What I want is simple:
How can I know that DOMContentLoaded was fired by the time the file is executed?
Why is this so difficult?
In IE, document.readyState show interactive before DOMContentLoaded.
I won't use browser detection in any way, it's against the policy of me and the rest of the participants.
What's the correct alternative?
Edit:
Seems like I wasn't clear enough. I'm not interested to know if the load event has already occurred!!! I already knew how to solve that problem! I want to know how to solve with DOMContentLoaded!!!
For seeing if all resources in the page have been loaded:
if (document.readyState === "complete" || document.readyState === "loaded") {
// document is already ready to go
}
This has been supported in IE and webkit for a long time. It was added to Firefox in 3.6. Here's the spec. "loaded"
is for older Safari browsers.
If you want to know when the page has been loaded and parsed, but all subresources have not yet been loaded (which is more akin to DOMContentLoaded
), you can add the "interactive" value:
if (document.readyState === "complete"
|| document.readyState === "loaded"
|| document.readyState === "interactive") {
// document has at least been parsed
}
Beyond this, if you really just want to know when DOMContentLoaded has fired, then you'll have to install an event handler for that (before it fires) and set a flag when it fires.
This MDN documentation is also a really good read about understanding more about the DOM states.
The document.readyState
is changed when this event is fired.
So you can check the readyState
value and this way tell if the event was fired or not.
Here's an code to run start()
when document is ready for it:
if (/comp|inter|loaded/.test(document.readyState)){
// In case DOMContentLoaded was already fired, the document readyState will be one of "complete" or "interactive" or (nonstandard) "loaded".
// The regexp above looks for all three states. A more readable regexp would be /complete|interactive|loaded/
start();
}else{
// In case DOMContentLoaded was not yet fired, use it to run the "start" function when document is read for it.
document.addEventListener('DOMContentLoaded', start, false);
}
Try this or look at this link
<script>
function addListener(obj, eventName, listener) { //function to add event
if (obj.addEventListener) {
obj.addEventListener(eventName, listener, false);
} else {
obj.attachEvent("on" + eventName, listener);
}
}
addListener(document, "DOMContentLoaded", finishedDCL); //add event DOMContentLoaded
function finishedDCL() {
alert("Now DOMContentLoaded is complete!");
}
</script>
Note
If you have a <script>
after a <link rel="stylesheet" ...>
the page will not finish parsing - and DOMContentLoaded
will not fire - until the stylesheet is loaded
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;
...
}
then check with:
if(loaded) ...
Here is the thing, if some other library (such as jQuery) already used DOMContentLoaded, you can't use it again. That can be bad news, because you end up without being able to use it. You are gonna say, why not just use $(document).ready()
, because, NO!, not everything needs to use jQuery, specially if it is a different library.