Hey! I'm making a game called Terra Mango. You should check it out.

How to Setup jQuery.ready Callbacks Before jQuery is Loaded

We all know that "best practice" states that we should place all of our external javascript files at the end of the document body. And generally, we'd like to put all of our own scripts into a /js/scripts.js file and place it right after jQuery (and our other scripts).

This is all fine and dandy, but sometimes I just want to slap some DOM-dependent jQuery code right into the middle of my HTML. What if I'm lazy and don't want to put my code in my scripts.js file? What if I want to do something like this?

<body>  
 <div id="main">
  <script>
    $(function(){
     $("#main").prepend( "<p>Heyo!</p>" );
    });
   </script>
  </div>
 <div>...more HTML...</div>
<script src="/js/jquery.js"></script>
<script src="/js/scripts.js"></script>
</body>

Obviously, since jQuery is loaded at the BOTTOM of the page it is not going to work; following the best practice as describe above isn't going to play nice when combined with our inline/in-body scripts without some extra effort.

Here is that extra effort:

<head>
    <script>
        (function(a){
            _q=function(){return a;};
            $=function(f){
                typeof f==="function" && a.push(arguments);
                return $;
            };
            jQuery=$.ready=$;
        }([]));
    </script>
</head>
<body>
    <div id="main">
        <script>
            $(function() {
                $( "#main" ).prepend( "<p>Heyo!</p>" );
            });
        </script>
        <div>...more HTML...</div>
    </div>
    <script src="/js/jquery.js"></script>
    <script>
        (function( i, s, q, l ) {
            for( q = window._q(), l = q.length; i < l; ) {
                $.apply( this, s.call( q[ i++ ] ) );
            }
            window._q = undefined;
        }( 0, Array.prototype.slice ));
    </script>
    <script src="/js/scripts.js"></script>
</body>

What the first <script> does is emulate jQuery's ready function by storing the arguments of any calls to $.ready where the first argument is a function into an array. This array is private to our globally scoped __q method, which, when called, returns the array.

The last inline  <script> loops through the array by calling _q() and then applies the arguments originally passed to our imposter $.ready to the real $.ready.

You can use these common $.ready styles:

$(elementOrSelector).ready(function(){});
$(function(){});
$.ready(function(){});
$(function(){});

Warning: $(document).bind("ready", function(){}) will not work. Get over it.

Here is the minified version:

// first part (in document head)
(function(a){_q=function(){return a;};$=function(f){typeof f==="function"&&a.push(arguments);return $;};jQuery=$.ready=$;}([]));
// Second part (after jQuery)
(function(i,s,q,l){for(q=window.__q(),l=q.length;i<l;){$.apply(this,s.call(q[i++]));}window.__q=undefined;}(0,Array.prototype.slice)); 
Comments for this blog entry