With jQuery, we all know the wonderful .ready() function:
$('document').ready(function(){});
However, let’s say I want to run a function that is written in standard JavaScript with no library backing it, and that I want to launch a function as soon as the page is ready to handle it. What’s the proper way to approach this?
I know I can do:
window.onload="myFunction()";
Or I can use the body tag:
<body onload="myFunction()">
Or I can even try at the bottom of the page after everything, but the end body or html tag like:
<script type="text/javascript">
myFunction();
</script>
What is a cross-browser(old/new)-compliant method of issuing one or more functions in a manner like jQuery’s $.ready()?
The simplest thing to do in the absence of a framework that does all the cross-browser compatibility for you is to just put a call to your code at the end of the body. This is faster to execute than an
onloadhandler because this waits only for the DOM to be ready, not for all images to load. And, this works in every browser.For modern browsers (anything from IE9 and newer and any version of Chrome, Firefox or Safari), if you want to be able to implement a jQuery like
$(document).ready()method that you can call from anywhere (without worrying about where the calling script is positioned), you can just use something like this:Usage:
If you need full cross browser compatibility (including old versions of IE) and you don’t want to wait for
window.onload, then you probably should go look at how a framework like jQuery implements its$(document).ready()method. It’s fairly involved depending upon the capabilities of the browser.To give you a little idea what jQuery does (which will work wherever the script tag is placed).
If supported, it tries the standard:
with a fallback to:
or for older versions of IE, it uses:
with a fallback to:
And, there are some work-arounds in the IE code path that I don’t quite follow, but it looks like it has something to do with frames.
Here is a full substitute for jQuery’s
.ready()written in plain javascript:The latest version of the code is shared publicly on GitHub at https://github.com/jfriend00/docReady
Usage:
This has been tested in:
Working implementation and test bed: http://jsfiddle.net/jfriend00/YfD3C/
Here’s a summary of how it works:
docReady(fn, context)docReady(fn, context)is called, check if the ready handler has already fired. If so, just schedule the newly added callback to fire right after this thread of JS finishes withsetTimeout(fn, 1).document.addEventListenerexists, then install event handlers using.addEventListener()for both"DOMContentLoaded"and"load"events. The “load” is a backup event for safety and should not be needed.document.addEventListenerdoesn’t exist, then install event handlers using.attachEvent()for"onreadystatechange"and"onload"events.onreadystatechangeevent, check to see if thedocument.readyState === "complete"and if so, call a function to fire all the ready handlers.Handlers registered with
docReady()are guaranteed to be fired in the order they were registered.If you call
docReady(fn)after the document is already ready, the callback will be scheduled to execute as soon as the current thread of execution completes usingsetTimeout(fn, 1). This allows the calling code to always assume they are async callbacks that will be called later, even if later is as soon as the current thread of JS finishes and it preserves calling order.