Jordan Reiter Jordan Reiter - 4 months ago 9
jQuery Question

Handling code which relies on jQuery before jQuery is loaded

I'd like to follow the general guideline of putting all JavaScript at the very bottom of the page, to speed up loading time and also to take care of some pesky issues with conflicting jQuery versions in a web app (Django).

However, every so often I have some code, code which depends on jQuery, but which must be further up on the page (basically the code can't be moved to the bottom).

I'm wondering if there's an easy way to code this so that even though jQuery is not yet defined the code works when jQuery is defined.

The following seems, I have to say, like overkill but I don't know of another way to do it:

function run_my_code($) {
// jquery-dependent code here
$("#foo").data('bar', true);
}
var t = null;
function jquery_ready() {
if (window.jQuery && window.jQuery.ui) {
run_my_code(window.jQuery);
} else {
t = window.setTimeout(jquery_ready, 100);
}
}
t = window.setTimeout(jquery_ready, 100);


Actually, I might need to use code more than once in a page, code that doesn't know about other code, so even this probably won't work unless I rename each jquery_ready to something like jquery_ready_guid, jquery_ready_otherguid and so on.

Clarification



Just so this is clear, I am putting the include to JavaScript (
<script type="text/javascript" src="jquery.min.js" />
) at the very bottom of the page, just before the
</body>
. So I can't use the
$
.

Answer

Your way is the only way that I know of, though I would ensure that the scoping is a little tighter:

(function() {
  var runMyCode = function($) {
    // jquery-dependent code here
    $("#foo").data('bar', true);
  };

  var timer = function() {
    if (window.jQuery && window.jQuery.ui) {
      runMyCode(window.jQuery);
    } else {
      window.setTimeout(timer, 100);
    }
  };
  timer();
})();

Update

Here's a little deferred loader I cobbled together:

var Namespace = Namespace || { };
Namespace.Deferred = function () {
  var functions = [];
  var timer = function() {
    if (window.jQuery && window.jQuery.ui) {
        while (functions.length) {
            functions.shift()(window.jQuery);
        }
    } else {
        window.setTimeout(timer, 250);
    }
  };
  timer();
  return {
    execute: function(onJQueryReady) {
        if (window.jQuery && window.jQuery.ui) {
            onJQueryReady(window.jQuery);
        } else {
            functions.push(onJQueryReady);
        }
    }
  };
}();

Which would then be useable like so:

Namespace.Deferred.execute(runMyCode);
Comments