2 * @license RequireJS order 1.0.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.
3 * Available via the MIT or new BSD license.
4 * see: http://github.com/jrburke/requirejs for details
6 /*jslint nomen: false, plusplus: false, strict: false */
7 /*global require: false, define: false, window: false, document: false,
10 //Specify that requirejs optimizer should wrap this code in a closure that
11 //maps the namespaced requirejs API to non-namespaced local variables.
12 /*requirejs namespace: true */
16 //Sadly necessary browser inference due to differences in the way
17 //that browsers load and execute dynamically inserted javascript
18 //and whether the script/cache method works when ordered execution is
19 //desired. Currently, Gecko and Opera do not load/fire onload for scripts with
20 //type="script/cache" but they execute injected scripts in order
21 //unless the 'async' flag is present.
22 //However, this is all changing in latest browsers implementing HTML5
23 //spec. With compliant browsers .async true by default, and
24 //if false, then it will execute in order. Favor that test first for forward
26 var testScript = typeof document !== "undefined" &&
27 typeof window !== "undefined" &&
28 document.createElement("script"),
30 supportsInOrderExecution = testScript && (testScript.async ||
32 Object.prototype.toString.call(window.opera) === "[object Opera]") ||
33 //If Firefox 2 does not have to be supported, then
34 //a better check may be:
35 //('mozIsLocallyAvailable' in window.navigator)
36 ("MozAppearance" in document.documentElement.style))),
38 //This test is true for IE browsers, which will load scripts but only
39 //execute them once the script is added to the DOM.
40 supportsLoadSeparateFromExecute = testScript &&
41 testScript.readyState === 'uninitialized',
43 readyRegExp = /^(complete|loaded)$/,
49 //Done with the test script.
52 //Callback used by the type="script/cache" callback that indicates a script
53 //has finished downloading.
54 function scriptCacheCallback(evt) {
55 var node = evt.currentTarget || evt.srcElement, i,
58 if (evt.type === "load" || readyRegExp.test(node.readyState)) {
59 //Pull out the name of the module and the context.
60 moduleName = node.getAttribute("data-requiremodule");
62 //Mark this cache request as loaded
63 cached[moduleName] = true;
65 //Find out how many ordered modules have loaded
66 for (i = 0; (resource = cacheWaiting[i]); i++) {
67 if (cached[resource.name]) {
68 resource.req([resource.name], resource.onLoad);
70 //Something in the ordered list is not loaded,
76 //If just loaded some items, remove them from cacheWaiting.
78 cacheWaiting.splice(0, i);
81 //Remove this script tag from the DOM
82 //Use a setTimeout for cleanup because some older IE versions vomit
83 //if removing a script node while it is being evaluated.
84 setTimeout(function () {
85 node.parentNode.removeChild(node);
91 * Used for the IE case, where fetching is done by creating script element
92 * but not attaching it to the DOM. This function will be called when that
93 * happens so it can be determined when the node can be attached to the
94 * DOM to trigger its execution.
96 function onFetchOnly(node) {
97 var i, loadedNode, resourceName;
99 //Mark this script as loaded.
100 node.setAttribute('data-orderloaded', 'loaded');
102 //Cycle through waiting scripts. If the matching node for them
103 //is loaded, and is in the right order, add it to the DOM
104 //to execute the script.
105 for (i = 0; (resourceName = scriptWaiting[i]); i++) {
106 loadedNode = scriptNodes[resourceName];
108 loadedNode.getAttribute('data-orderloaded') === 'loaded') {
109 delete scriptNodes[resourceName];
110 require.addScriptToDom(loadedNode);
116 //If just loaded some items, remove them from waiting.
118 scriptWaiting.splice(0, i);
125 load: function (name, req, onLoad, config) {
126 var url = req.nameToUrl(name, null),
129 //Make sure the async attribute is not set for any pathway involving
131 require.s.skipAsync[url] = true;
132 if (supportsInOrderExecution || config.isBuild) {
133 //Just a normal script tag append, but without async attribute
136 } else if (supportsLoadSeparateFromExecute) {
137 //Just fetch the URL, but do not execute it yet. The
138 //non-standards IE case. Really not so nice because it is
139 //assuming and touching requrejs internals. OK though since
140 //ordered execution should go away after a long while.
141 context = require.s.contexts._;
143 if (!context.urlFetched[url] && !context.loaded[name]) {
144 //Indicate the script is being fetched.
145 context.urlFetched[url] = true;
147 //Stuff from require.load
148 require.resourcesReady(false);
149 context.scriptCount += 1;
151 //Fetch the script now, remember it.
152 node = require.attach(url, context, name, null, null, onFetchOnly);
153 scriptNodes[name] = node;
154 scriptWaiting.push(name);
157 //Do a normal require for it, once it loads, use it as return
161 //Credit to LABjs author Kyle Simpson for finding that scripts
162 //with type="script/cache" allow scripts to be downloaded into
163 //browser cache but not executed. Use that
164 //so that subsequent addition of a real type="text/javascript"
165 //tag will cause the scripts to be executed immediately in the
167 if (req.specified(name)) {
175 require.attach(url, null, name, scriptCacheCallback, "script/cache");