I'm getting my head around Modernizr polyfill loading today and running into some trouble. I like the idea of loading jQuery in parallell and so have the CDN URI (with a local fallback) up top. Then I get in to loading some polyfills which are all jQuery plugins that I was using prior to discovering Modernizr.
The trouble is, the plugins are smaller and load before jQuery is done and exocuted, so '$' and 'jQuery' objects both wind up undefined. The yepnope docs say that the loader is supposed to respect the execution order of dependant scripts despite parallell downlaoding, but following the sample syntax to the letter still produces the error.
Can y'all have a look at my code below and see where I'm wanting? This snippet lies directly under the Modernizer minimized code; which is situated in my <head>
. FYI, there is a slew of effects jQuery code that also get loaded at the bottom of my <body>
, but I want the polyfills to work before I go setting up the 'complete:' function for them.
Modernizr.load([
{
load: '//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js',
complete: function () {
if (!window.jQuery)
Modernizr.load('js/jquery.1.7.1.min.js');
}
},
{//Border Radius
test : Modernizr.borderradius,
nope : 'js/polyfills/jquery.curvycorners.js'
},
{//Text Shadow
test: Modernizr.textshadow,
nope: 'js/polyfills/jquery.textshadow.min.js',
complete: function(){
$(function(){
$("h2").textShadow();
$("h3").textShadow();
$("a.facebook").textShadow();
$("a.twitter").textShadow();
});
}
},
{//Box Shadow
test: Modernizr.boxshadow,
nope: 'js/polyfills/jquery.boxshadow.js'
}
]);
After a lot of research and experimentation, it looks this is an issue with yepnope at a concept level. Because of the load timeline for jQuery, the plugins will always go looking for it before it is ready. While a nested load() in the jQuery test's complete function is one way to hack it, you're then looking at a decent amount of time that the user will see the page without polyfills. While this might be ok for form validation, it looks as bad as a FOUC when you're polyfilling border-radius
and text-shadow
the way I am in this example.
The best solution I found was to load jQuery via the HTML5 boilerplate method:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.7.1.min.js">\x3C/script>')</script>
Then place a Modernizr.load()
in the $(document).ready();
. While this offsets most of the parallel-load optimization benefits of Modernizr, it maintains the yepnope progressive enhancement principal, lets you use Modernizr for HTML5 shimming (which is just tidy IMHO), and ensures that jQuery is definitely available for polyfills. An upshot too is that you can safely use $()
selection in the complete function, which can be handy.