Can anyone explain why, in Internet Explorer, code sample 1 doesn't work while code sample 2 works?
Code 1 (non-functional)
Modernizr.load([
{
load: [
'../includes/css/foo.css',
'../includes/js/foo.js',
'../includes/js/bar.js'
],
complete: function() {
initBar();
}
}
]);
Code 2 (functional)
Modernizr.load([
{
load: [
'../includes/css/foo.css',
'../includes/js/foo.js',
'../includes/js/bar.js'
],
complete: function() {
window.initBar();
}
}
]);
bar.js
var initBar = function() {
// code here
};
It works fine in other browsers. I've tried moving the blocks to the head section as well as beneath the page. I've also tried wrapping the contents of the callback in $(document).ready()
, but none have worked with code 1.
The error I am getting specifically is:
SCRIPT5009: « initBar » est indéfini
It is almost as if the callback is executed before the resources are finished loading, but if that was the case then why does code sample 2 work?
Also I will note that on refresh the page loads fine (most likely due to the fact that the resources are cached), but it also loads fine after clearing the cache. I have to restart my browser session after clearing the cache to reproduce the problem.
UPDATE: This problem extends to more than just functions. Any global variable defined in a JS file that is loaded doesn't seem to be accessible directly. It also occurs if I load the CSS at the top of the page rather than with the other resources asynchronously. In fact I'm also noticing this problem with some jQuery plugins that are loaded in this manner.
UPDATE 2:
Here is the console.log()
output as per debugging instructions below. I've changed bar to be an object instead of a function for the sake of illustrating this.
Internet Explorer:
HTML1300: Une navigation s’est produite.
Fichier : test18.php
before .load() called
before bar accessed
typeof bar = undefined
typeof window.bar = undefined
SCRIPT5009: « bar » est indéfini
Fichier : test18.js, ligne : 14, colonne : 13
before bar defined
So it appears that the complete
function executes before bar
is defined. I find it strange that window.bar
is also undefined yet works...
Firefox
[02:10:46,448] "before .load() called"
[02:10:47,184] "before bar defined"
[02:10:47,184] "before bar accessed"
[02:10:47,184] "typeof bar = object"
[02:10:47,184] "typeof window.bar = object"
Chrome
before .load() called
before bar defined
before bar accessed
typeof bar = object
typeof window.bar = object
Both Firefox and Chrome appear to be loading and executing the resources in the correct order.
First off, you should know that
.load()
in modernizr comes from the yepnope library so that's where you find the detailed documentation for it.Here are the possible things that could be different in different browsers that I can think of:
The exact timing of the loading of the scripts and thus the timing of when the
complete()
function gets called.The caching in the browser (which can affect the load timing).
Because you are defining
initBar
by assigning it to a variable instead of a regularfunction initBar()
definition, the function will not exist until that line of code executes whereasfunction initBar()
will exist at script parse time.Make sure you version 1.5 or higher of the yepnope loading library (I don't know what modernizr version that corresponds to. The yepnope doc for
.load()
says this: "In versions of yepnope prior to 1.5 this [when the complete function is called] could vary from time to time".There are notes on this page that the yepnope library may not wait for .css files to load before calling the complete callback unless you have an add-in present. I don't know if that throws off the whole complete timing or what as I note that you do have .css files in your load list.
So, here's what I'd suggest to debug this:
1) Change your initBar definition to this:
2) Make sure your initBar definition is in the proper scope and reachable from your other code. Look out for things like being inside another function (onload, document.ready, etc...) which might make it unreachable.
3) Insert some
console.log()
statements like this to do some timing debugging:Then, see what order things come out in and what the typeof statements say. The idea here is to try to figure out if things are executing in the wrong order or if a scope is wrong.
4) Try loading the .css file separately so it won't be affecting the .js loading.
Here's a replacement script that can load multiple scripts dynamically to replace the modernizr buggy
.load()
code. This one loads them all in parallel. This works only for scripts files (though the same concept could be used for.css
files.Sample usage:
Working demo: http://jsfiddle.net/jfriend00/qs44R/
If you need them loaded sequentially (one after the other because of dependencies between them), then you could use this:
Working demo: http://jsfiddle.net/jfriend00/9aVLW/