How can I use yepnope.js with $(document).ready() effectively?

Ash Clarke picture Ash Clarke · Apr 14, 2011 · Viewed 7.7k times · Source

I have been implementing the yepnope script loader as part of the modernizr.js library. I have successfully got jQuery to load and jQuery dependent scripts afterwards. I am new to asynchronous loading of resources, so it's a bit new to me. I have been searching around, but haven't had much luck with the following.

My question is what are your opinions on how to effectively replace the functionality of $(document).ready() when working with the yepnope.js framework.

My theory was to create a appropriately named function in my base library and then set that variable on my pages to an anonymous function containing my existing $(document).ready() code. This variable would then be called by yepnope after all the scripts had loaded in the complete callback.

Would you agree that this is a good way of doing it, or am I approaching this entirely the wrong way?

(For those unaware, the asynchronous nature of yepnope.js means that the document calls $ or jQuery before the yepnope loader has finished, throwing a "$ is undefined" error <- please correct me if that is wrong.)

First question, hope it's a good one.

Answer

Sc0ttyD picture Sc0ttyD · Dec 19, 2011

This is the technique I use. It allows me to sprinkle $(document).ready() style calls wherever I like. Using this method, you can take a site that already uses jQuery and has existing $(document).ready() calls, and easily retrofit yepnope.

First, add this line of JS, preferably in the document head, before any javascript that calls $(document).ready():

<script>
    var docready=[],$=function(o){function r(fn){docready.push(fn);}if(typeof o === 'function') r(o);return{ready: r}};
</script>

Then, have your yepnope jQuery test object set similar to this:

yepnope({
    load: '//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js',
    complete: function() {
        $ = jQuery;         
        for(n in docready) $(document).ready(docready[n]);
    }
});

We create a fake $(document).ready() before jQuery loads. This stores every $(document).ready() call in an array, docready. Then, once jQuery has loaded, we overwrite our temporary $ object with the now loaded real jQuery object. Then, we iterate through all the stored $(document).ready() calls, and execute them for real.

UPDATED: improved version from Chris Jones that also covers $(function() {}) style invocations.