├── .github └── ISSUE_TEMPLATE │ ├── bug.md │ ├── enhancement.md │ └── support.md ├── .gitignore ├── LICENSE.md ├── README.md ├── css.js ├── css.min.js ├── require-1.0.0.js └── tests ├── index.html ├── style ├── test.css └── test2.css ├── test-body.html ├── test-cross-domain.html ├── test-multiple.html ├── test-nested.html ├── test-onload.html ├── test-simple.html └── test.js /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: Use this template if the issue describes a bug in the code of this repository. 4 | 5 | --- 6 | 7 | 16 | 17 | ### What is the unexpected/incorrect behavior and what is the impact? 18 | 19 | ### What are the exact steps required for anyone to reproduce the issue? 20 | 21 | 22 | ### Who is affected by this issue and who is involved? 23 | 24 | 25 | ### What action items are left to be done on this issue? 26 | 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement 3 | about: Use this template if the issue proposes adding a new feature or changing an existing feature. 4 | 5 | --- 6 | 7 | 14 | 15 | ### How can the enhancement be summarized in two to three sentences? 16 | 17 | ### How does the system behave currently (before applying the enhancement)? 18 | 19 | ### How should the system behave once the enhancement is implemented? 20 | 21 | ### How could this be implemented? 22 | 23 | ### Who is affected by this issue and who is involved? 24 | 25 | 26 | ### What action items are left to be done on this issue? 27 | 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Support 3 | about: Use this template if the issue is a request for 2nd level support. 4 | 5 | --- 6 | 7 | 17 | 18 | ### What concern did the customer raise, what are they trying to accomplish and what precludes them from it? 19 | 20 | ### What are the exact steps required for anyone to reproduce the issue? 21 | 22 | 23 | ### What has previously been attempted by whom to fix or work around the issue? 24 | 25 | ### In which environments does the issue occur? 26 | 27 | * Shopware: 28 | * PHP: 29 | * Affected plugins: 30 | 31 | ### Where can one find the credentials for the affected system(s)? 32 | 33 | 34 | ### Who is affected by this issue (incl. support references) and who is involved? 35 | 36 | 37 | * Gmail mail ID: 38 | 39 | ### What action items are left to be done on this issue? 40 | 41 | 42 | * [ ] Analyse the problem 43 | * [ ] When analysis on the customer system has been concluded, remove debugging state from customer system with customer consent 44 | * [ ] If necessary, inform the customer of further steps 45 | * If fixable in our code (mark done if not): 46 | * [ ] Decide whether or not to add a _needs testing_ label 47 | * [ ] Once a code fix is merged, move to _Awaiting Release_ 48 | * [ ] Alert the Product or the Code Owner for them to decide whether to the fix warrants a new release 49 | * [ ] Once the fix is released, notify `@VIISON/sales` via at-mention in a comment 50 | * [ ] Sales informs the customer 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Copyright (c) 2011 VIISON 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RequireCSS (RequireJS _css!_ plugin) 2 | 3 | A [RequireJS][1] plugin which loads and waits for css files. Uses the standard load event on browsers which support it (IE, Firefox 9+, Opera) and uses a script tags load & error events as a workaround (Chrome, Safari, Firefox < 9). Detection of link load event support is done using a link element with a data url, which fires onload immediately when supported. 4 | 5 | Only caveats __in browsers not supporting the native link load event are that there will be JavaScript parse errors__ (since browsers try to interpret the dummy script tags used for load event detection) and there will be no RequireJS error message when a stylesheet could not be found/loaded. Also beware of IE's 31 style sheets limit (fixed in IE 10). 6 | 7 | [1]: http://requirejs.org/ 8 | 9 | # Compatibility 10 | 11 | * Firefox 1.0.1+ 12 | * Safari 3.2+ 13 | * Mobile Safari 4 (iOS 3.2)+ 14 | * Chrome 1+ 15 | * Opera 9.5+ 16 | * IE 6+ 17 | 18 | # Planned 19 | 20 | * Media-Query support 21 | * r.js optimizer support 22 | 23 | # Credits 24 | 25 | * [Workaround for missing link load event][1] - Daniel Buchner, backalleycoder.com 26 | * [Inspiration to build this plugin][2] - John Hann, unscriptable.com 27 | * [Independently developed some of the same techniques and describes them in details][3] - Julian Aubourg, jaubourg.net 28 | 29 | [1]: http://www.backalleycoder.com/2011/03/20/link-tag-css-stylesheet-load-event/ 30 | [2]: https://github.com/unscriptable/curl/blob/master/src/curl/plugin/css.js 31 | [3]: http://jaubourg.net/feature-testing-impossible-data-uri-and-defer 32 | -------------------------------------------------------------------------------- /css.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireCSS 0.3.1 Copyright (c) 2011, VIISON All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/VIISON/RequireCSS for details 5 | */ 6 | 7 | /*jslint forin: true */ 8 | /*global document: true, setTimeout: true, define: true */ 9 | 10 | (function () { 11 | "use strict"; 12 | 13 | var doc = document, 14 | head = doc.head || doc.getElementsByTagName('head')[0], 15 | // Eliminate browsers that admit to not support the link load event (e.g. Firefox < 9) 16 | nativeLoad = doc.createElement('link').onload === null ? undefined : false, 17 | a = doc.createElement('a'); 18 | 19 | function createLink(url) { 20 | var link = doc.createElement('link'); 21 | 22 | link.rel = "stylesheet"; 23 | link.type = "text/css"; 24 | link.href = url; 25 | 26 | return link; 27 | } 28 | 29 | function styleSheetLoaded(url) { 30 | var i; 31 | 32 | // Get absolute url by assigning to a link and reading it back below 33 | a.href = url; 34 | 35 | for (i in doc.styleSheets) { 36 | if (doc.styleSheets[i].href === a.href) { 37 | return true; 38 | } 39 | } 40 | 41 | return false; 42 | } 43 | 44 | /** 45 | * Load using the browsers built-in load event on link tags 46 | */ 47 | function loadLink(url, load) { 48 | var link = createLink(url); 49 | 50 | link.onload = function () { 51 | load(); 52 | }; 53 | 54 | head.appendChild(link); 55 | }; 56 | 57 | /** 58 | * Insert a script tag and use it's onload & onerror to know when 59 | * the CSS is loaded, this will unfortunately also fire on other 60 | * errors (file not found, network problems) 61 | */ 62 | function loadScript(url, load) { 63 | var link = createLink(url), 64 | script = doc.createElement('script'); 65 | 66 | head.appendChild(link); 67 | 68 | script.onload = script.onerror = function () { 69 | head.removeChild(script); 70 | 71 | // In Safari the stylesheet might not yet be applied, when 72 | // the script is loaded so we poll document.styleSheets for it 73 | var checkLoaded = function () { 74 | if (styleSheetLoaded(url)) { 75 | load(); 76 | 77 | return; 78 | } 79 | 80 | setTimeout(checkLoaded, 25); 81 | }; 82 | checkLoaded(); 83 | }; 84 | script.src = url; 85 | 86 | head.appendChild(script); 87 | }; 88 | 89 | function loadSwitch(url, load) { 90 | if (nativeLoad) { 91 | loadLink(url, load); 92 | } else { 93 | loadScript(url, load); 94 | } 95 | }; 96 | 97 | define(function () { 98 | var css; 99 | 100 | css = { 101 | version: '0.3.1', 102 | 103 | load: function (name, req, load) { //, config (not used) 104 | // convert name to actual url 105 | var url = req.toUrl( 106 | // Append default extension 107 | name.search(/\.(css|less|scss)$/i) === -1 ? name + '.css' : name 108 | ); 109 | 110 | // Test if the browser supports the link load event, 111 | // in case we don't know yet (mostly WebKit) 112 | if (nativeLoad === undefined) { 113 | // Create a link element with a data url, 114 | // it would fire a load event immediately 115 | var link = createLink('data:text/css,'); 116 | 117 | link.onload = function () { 118 | // Native link load event works 119 | nativeLoad = true; 120 | }; 121 | 122 | head.appendChild(link); 123 | 124 | // Schedule function in event loop, this will 125 | // execute after a potential execution of the link onload 126 | setTimeout(function () { 127 | head.removeChild(link); 128 | 129 | if (nativeLoad !== true) { 130 | // Native link load event is broken 131 | nativeLoad = false; 132 | } 133 | 134 | loadSwitch(url, load); 135 | }, 0); 136 | } else { 137 | loadSwitch(url, load); 138 | } 139 | } 140 | }; 141 | 142 | return css; 143 | }); 144 | }()); -------------------------------------------------------------------------------- /css.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license RequireCSS 0.3.1 Copyright (c) 2011, VIISON All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/VIISON/RequireCSS for details 5 | */ 6 | (function(){function e(b){var c=a.createElement("link");return c.rel="stylesheet",c.type="text/css",c.href=b,c}function f(b){var c;d.href=b;for(c in a.styleSheets)if(a.styleSheets[c].href===d.href)return!0;return!1}function g(a,c){var d=e(a);d.onload=function(){c()},b.appendChild(d)}function h(c,d){var g=e(c),h=a.createElement("script");b.appendChild(g),h.onload=h.onerror=function(){b.removeChild(h);var a=function(){if(f(c)){d();return}setTimeout(a,25)};a()},h.src=c,b.appendChild(h)}function i(a,b){c?g(a,b):h(a,b)}"use strict";var a=document,b=a.head||a.getElementsByTagName("head")[0],c=a.createElement("link").onload===null?undefined:!1,d=a.createElement("a");define(function(){var a;return a={version:"0.3.1",load:function(a,d,f){var g=d.toUrl(a.search(/\.(css|less|scss)$/i)===-1?a+".css":a);if(c===undefined){var h=e("data:text/css,");h.onload=function(){c=!0},b.appendChild(h),setTimeout(function(){b.removeChild(h),c!==!0&&(c=!1),i(g,f)},0)}else i(g,f)}},a})})() -------------------------------------------------------------------------------- /require-1.0.0.js: -------------------------------------------------------------------------------- 1 | /** vim: et:ts=4:sw=4:sts=4 2 | * @license RequireJS 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 5 | */ 6 | /*jslint strict: false, plusplus: false, sub: true */ 7 | /*global window: false, navigator: false, document: false, importScripts: false, 8 | jQuery: false, clearInterval: false, setInterval: false, self: false, 9 | setTimeout: false, opera: false */ 10 | 11 | var requirejs, require, define; 12 | (function () { 13 | //Change this version number for each release. 14 | var version = "1.0.0", 15 | commentRegExp = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, 16 | cjsRequireRegExp = /require\(\s*["']([^'"\s]+)["']\s*\)/g, 17 | currDirRegExp = /^\.\//, 18 | jsSuffixRegExp = /\.js$/, 19 | ostring = Object.prototype.toString, 20 | ap = Array.prototype, 21 | aps = ap.slice, 22 | apsp = ap.splice, 23 | isBrowser = !!(typeof window !== "undefined" && navigator && document), 24 | isWebWorker = !isBrowser && typeof importScripts !== "undefined", 25 | //PS3 indicates loaded and complete, but need to wait for complete 26 | //specifically. Sequence is "loading", "loaded", execution, 27 | // then "complete". The UA check is unfortunate, but not sure how 28 | //to feature test w/o causing perf issues. 29 | readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ? 30 | /^complete$/ : /^(complete|loaded)$/, 31 | defContextName = "_", 32 | //Oh the tragedy, detecting opera. See the usage of isOpera for reason. 33 | isOpera = typeof opera !== "undefined" && opera.toString() === "[object Opera]", 34 | empty = {}, 35 | contexts = {}, 36 | globalDefQueue = [], 37 | interactiveScript = null, 38 | checkLoadedDepth = 0, 39 | useInteractive = false, 40 | req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script, 41 | src, subPath, mainScript, dataMain, i, ctx, jQueryCheck, checkLoadedTimeoutId; 42 | 43 | function isFunction(it) { 44 | return ostring.call(it) === "[object Function]"; 45 | } 46 | 47 | function isArray(it) { 48 | return ostring.call(it) === "[object Array]"; 49 | } 50 | 51 | /** 52 | * Simple function to mix in properties from source into target, 53 | * but only if target does not already have a property of the same name. 54 | * This is not robust in IE for transferring methods that match 55 | * Object.prototype names, but the uses of mixin here seem unlikely to 56 | * trigger a problem related to that. 57 | */ 58 | function mixin(target, source, force) { 59 | for (var prop in source) { 60 | if (!(prop in empty) && (!(prop in target) || force)) { 61 | target[prop] = source[prop]; 62 | } 63 | } 64 | return req; 65 | } 66 | 67 | /** 68 | * Constructs an error with a pointer to an URL with more information. 69 | * @param {String} id the error ID that maps to an ID on a web page. 70 | * @param {String} message human readable error. 71 | * @param {Error} [err] the original error, if there is one. 72 | * 73 | * @returns {Error} 74 | */ 75 | function makeError(id, msg, err) { 76 | var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id); 77 | if (err) { 78 | e.originalError = err; 79 | } 80 | return e; 81 | } 82 | 83 | /** 84 | * Used to set up package paths from a packagePaths or packages config object. 85 | * @param {Object} pkgs the object to store the new package config 86 | * @param {Array} currentPackages an array of packages to configure 87 | * @param {String} [dir] a prefix dir to use. 88 | */ 89 | function configurePackageDir(pkgs, currentPackages, dir) { 90 | var i, location, pkgObj; 91 | 92 | for (i = 0; (pkgObj = currentPackages[i]); i++) { 93 | pkgObj = typeof pkgObj === "string" ? { name: pkgObj } : pkgObj; 94 | location = pkgObj.location; 95 | 96 | //Add dir to the path, but avoid paths that start with a slash 97 | //or have a colon (indicates a protocol) 98 | if (dir && (!location || (location.indexOf("/") !== 0 && location.indexOf(":") === -1))) { 99 | location = dir + "/" + (location || pkgObj.name); 100 | } 101 | 102 | //Create a brand new object on pkgs, since currentPackages can 103 | //be passed in again, and config.pkgs is the internal transformed 104 | //state for all package configs. 105 | pkgs[pkgObj.name] = { 106 | name: pkgObj.name, 107 | location: location || pkgObj.name, 108 | //Remove leading dot in main, so main paths are normalized, 109 | //and remove any trailing .js, since different package 110 | //envs have different conventions: some use a module name, 111 | //some use a file name. 112 | main: (pkgObj.main || "main") 113 | .replace(currDirRegExp, '') 114 | .replace(jsSuffixRegExp, '') 115 | }; 116 | } 117 | } 118 | 119 | /** 120 | * jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM 121 | * ready callbacks, but jQuery 1.6 supports a holdReady() API instead. 122 | * At some point remove the readyWait/ready() support and just stick 123 | * with using holdReady. 124 | */ 125 | function jQueryHoldReady($, shouldHold) { 126 | if ($.holdReady) { 127 | $.holdReady(shouldHold); 128 | } else if (shouldHold) { 129 | $.readyWait += 1; 130 | } else { 131 | $.ready(true); 132 | } 133 | } 134 | 135 | if (typeof define !== "undefined") { 136 | //If a define is already in play via another AMD loader, 137 | //do not overwrite. 138 | return; 139 | } 140 | 141 | if (typeof requirejs !== "undefined") { 142 | if (isFunction(requirejs)) { 143 | //Do not overwrite and existing requirejs instance. 144 | return; 145 | } else { 146 | cfg = requirejs; 147 | requirejs = undefined; 148 | } 149 | } 150 | 151 | //Allow for a require config object 152 | if (typeof require !== "undefined" && !isFunction(require)) { 153 | //assume it is a config object. 154 | cfg = require; 155 | require = undefined; 156 | } 157 | 158 | /** 159 | * Creates a new context for use in require and define calls. 160 | * Handle most of the heavy lifting. Do not want to use an object 161 | * with prototype here to avoid using "this" in require, in case it 162 | * needs to be used in more super secure envs that do not want this. 163 | * Also there should not be that many contexts in the page. Usually just 164 | * one for the default context, but could be extra for multiversion cases 165 | * or if a package needs a special context for a dependency that conflicts 166 | * with the standard context. 167 | */ 168 | function newContext(contextName) { 169 | var context, resume, 170 | config = { 171 | waitSeconds: 7, 172 | baseUrl: "./", 173 | paths: {}, 174 | pkgs: {}, 175 | catchError: {} 176 | }, 177 | defQueue = [], 178 | specified = { 179 | "require": true, 180 | "exports": true, 181 | "module": true 182 | }, 183 | urlMap = {}, 184 | defined = {}, 185 | loaded = {}, 186 | waiting = {}, 187 | waitAry = [], 188 | urlFetched = {}, 189 | managerCounter = 0, 190 | managerCallbacks = {}, 191 | plugins = {}, 192 | //Used to indicate which modules in a build scenario 193 | //need to be full executed. 194 | needFullExec = {}, 195 | fullExec = {}, 196 | resumeDepth = 0; 197 | 198 | /** 199 | * Trims the . and .. from an array of path segments. 200 | * It will keep a leading path segment if a .. will become 201 | * the first path segment, to help with module name lookups, 202 | * which act like paths, but can be remapped. But the end result, 203 | * all paths that use this function should look normalized. 204 | * NOTE: this method MODIFIES the input array. 205 | * @param {Array} ary the array of path segments. 206 | */ 207 | function trimDots(ary) { 208 | var i, part; 209 | for (i = 0; (part = ary[i]); i++) { 210 | if (part === ".") { 211 | ary.splice(i, 1); 212 | i -= 1; 213 | } else if (part === "..") { 214 | if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { 215 | //End of the line. Keep at least one non-dot 216 | //path segment at the front so it can be mapped 217 | //correctly to disk. Otherwise, there is likely 218 | //no path mapping for a path starting with '..'. 219 | //This can still fail, but catches the most reasonable 220 | //uses of .. 221 | break; 222 | } else if (i > 0) { 223 | ary.splice(i - 1, 2); 224 | i -= 2; 225 | } 226 | } 227 | } 228 | } 229 | 230 | /** 231 | * Given a relative module name, like ./something, normalize it to 232 | * a real name that can be mapped to a path. 233 | * @param {String} name the relative name 234 | * @param {String} baseName a real name that the name arg is relative 235 | * to. 236 | * @returns {String} normalized name 237 | */ 238 | function normalize(name, baseName) { 239 | var pkgName, pkgConfig; 240 | 241 | //Adjust any relative paths. 242 | if (name && name.charAt(0) === ".") { 243 | //If have a base name, try to normalize against it, 244 | //otherwise, assume it is a top-level require that will 245 | //be relative to baseUrl in the end. 246 | if (baseName) { 247 | if (config.pkgs[baseName]) { 248 | //If the baseName is a package name, then just treat it as one 249 | //name to concat the name with. 250 | baseName = [baseName]; 251 | } else { 252 | //Convert baseName to array, and lop off the last part, 253 | //so that . matches that "directory" and not name of the baseName's 254 | //module. For instance, baseName of "one/two/three", maps to 255 | //"one/two/three.js", but we want the directory, "one/two" for 256 | //this normalization. 257 | baseName = baseName.split("/"); 258 | baseName = baseName.slice(0, baseName.length - 1); 259 | } 260 | 261 | name = baseName.concat(name.split("/")); 262 | trimDots(name); 263 | 264 | //Some use of packages may use a . path to reference the 265 | //"main" module name, so normalize for that. 266 | pkgConfig = config.pkgs[(pkgName = name[0])]; 267 | name = name.join("/"); 268 | if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { 269 | name = pkgName; 270 | } 271 | } 272 | } 273 | return name; 274 | } 275 | 276 | /** 277 | * Creates a module mapping that includes plugin prefix, module 278 | * name, and path. If parentModuleMap is provided it will 279 | * also normalize the name via require.normalize() 280 | * 281 | * @param {String} name the module name 282 | * @param {String} [parentModuleMap] parent module map 283 | * for the module name, used to resolve relative names. 284 | * 285 | * @returns {Object} 286 | */ 287 | function makeModuleMap(name, parentModuleMap) { 288 | var index = name ? name.indexOf("!") : -1, 289 | prefix = null, 290 | parentName = parentModuleMap ? parentModuleMap.name : null, 291 | originalName = name, 292 | normalizedName, url, pluginModule; 293 | 294 | if (index !== -1) { 295 | prefix = name.substring(0, index); 296 | name = name.substring(index + 1, name.length); 297 | } 298 | 299 | if (prefix) { 300 | prefix = normalize(prefix, parentName); 301 | } 302 | 303 | //Account for relative paths if there is a base name. 304 | if (name) { 305 | if (prefix) { 306 | pluginModule = defined[prefix]; 307 | if (pluginModule && pluginModule.normalize) { 308 | //Plugin is loaded, use its normalize method. 309 | normalizedName = pluginModule.normalize(name, function (name) { 310 | return normalize(name, parentName); 311 | }); 312 | } else { 313 | normalizedName = normalize(name, parentName); 314 | } 315 | } else { 316 | //A regular module. 317 | normalizedName = normalize(name, parentName); 318 | 319 | url = urlMap[normalizedName]; 320 | if (!url) { 321 | //Calculate url for the module, if it has a name. 322 | url = context.nameToUrl(normalizedName, null, parentModuleMap); 323 | 324 | //Store the URL mapping for later. 325 | urlMap[normalizedName] = url; 326 | } 327 | } 328 | } 329 | 330 | return { 331 | prefix: prefix, 332 | name: normalizedName, 333 | parentMap: parentModuleMap, 334 | url: url, 335 | originalName: originalName, 336 | fullName: prefix ? prefix + "!" + (normalizedName || '') : normalizedName 337 | }; 338 | } 339 | 340 | /** 341 | * Determine if priority loading is done. If so clear the priorityWait 342 | */ 343 | function isPriorityDone() { 344 | var priorityDone = true, 345 | priorityWait = config.priorityWait, 346 | priorityName, i; 347 | if (priorityWait) { 348 | for (i = 0; (priorityName = priorityWait[i]); i++) { 349 | if (!loaded[priorityName]) { 350 | priorityDone = false; 351 | break; 352 | } 353 | } 354 | if (priorityDone) { 355 | delete config.priorityWait; 356 | } 357 | } 358 | return priorityDone; 359 | } 360 | 361 | function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) { 362 | return function () { 363 | //A version of a require function that passes a moduleName 364 | //value for items that may need to 365 | //look up paths relative to the moduleName 366 | var args = aps.call(arguments, 0), lastArg; 367 | if (enableBuildCallback && 368 | isFunction((lastArg = args[args.length - 1]))) { 369 | lastArg.__requireJsBuild = true; 370 | } 371 | args.push(relModuleMap); 372 | return func.apply(null, args); 373 | }; 374 | } 375 | 376 | /** 377 | * Helper function that creates a require function object to give to 378 | * modules that ask for it as a dependency. It needs to be specific 379 | * per module because of the implication of path mappings that may 380 | * need to be relative to the module name. 381 | */ 382 | function makeRequire(relModuleMap, enableBuildCallback) { 383 | var modRequire = makeContextModuleFunc(context.require, relModuleMap, enableBuildCallback); 384 | 385 | mixin(modRequire, { 386 | nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap), 387 | toUrl: makeContextModuleFunc(context.toUrl, relModuleMap), 388 | defined: makeContextModuleFunc(context.requireDefined, relModuleMap), 389 | specified: makeContextModuleFunc(context.requireSpecified, relModuleMap), 390 | isBrowser: req.isBrowser 391 | }); 392 | return modRequire; 393 | } 394 | 395 | /* 396 | * Queues a dependency for checking after the loader is out of a 397 | * "paused" state, for example while a script file is being loaded 398 | * in the browser, where it may have many modules defined in it. 399 | */ 400 | function queueDependency(manager) { 401 | context.paused.push(manager); 402 | } 403 | 404 | function execManager(manager) { 405 | var i, ret, err, errFile, errModuleTree, 406 | cb = manager.callback, 407 | map = manager.map, 408 | fullName = map.fullName, 409 | args = manager.deps, 410 | listeners = manager.listeners; 411 | 412 | //Call the callback to define the module, if necessary. 413 | if (cb && isFunction(cb)) { 414 | if (config.catchError.define) { 415 | try { 416 | ret = req.execCb(fullName, manager.callback, args, defined[fullName]); 417 | } catch (e) { 418 | err = e; 419 | } 420 | } else { 421 | ret = req.execCb(fullName, manager.callback, args, defined[fullName]); 422 | } 423 | 424 | if (fullName) { 425 | //If setting exports via "module" is in play, 426 | //favor that over return value and exports. After that, 427 | //favor a non-undefined return value over exports use. 428 | if (manager.cjsModule && manager.cjsModule.exports !== undefined) { 429 | ret = defined[fullName] = manager.cjsModule.exports; 430 | } else if (ret === undefined && manager.usingExports) { 431 | //exports already set the defined value. 432 | ret = defined[fullName]; 433 | } else { 434 | //Use the return value from the function. 435 | defined[fullName] = ret; 436 | //If this module needed full execution in a build 437 | //environment, mark that now. 438 | if (needFullExec[fullName]) { 439 | fullExec[fullName] = true; 440 | } 441 | } 442 | } 443 | } else if (fullName) { 444 | //May just be an object definition for the module. Only 445 | //worry about defining if have a module name. 446 | ret = defined[fullName] = cb; 447 | 448 | //If this module needed full execution in a build 449 | //environment, mark that now. 450 | if (needFullExec[fullName]) { 451 | fullExec[fullName] = true; 452 | } 453 | } 454 | 455 | //Clean up waiting. Do this before error calls, and before 456 | //calling back listeners, so that bookkeeping is correct 457 | //in the event of an error and error is reported in correct order, 458 | //since the listeners will likely have errors if the 459 | //onError function does not throw. 460 | if (waiting[manager.id]) { 461 | delete waiting[manager.id]; 462 | manager.isDone = true; 463 | context.waitCount -= 1; 464 | if (context.waitCount === 0) { 465 | //Clear the wait array used for cycles. 466 | waitAry = []; 467 | } 468 | } 469 | 470 | //Do not need to track manager callback now that it is defined. 471 | delete managerCallbacks[fullName]; 472 | 473 | //Allow instrumentation like the optimizer to know the order 474 | //of modules executed and their dependencies. 475 | if (req.onResourceLoad && !manager.placeholder) { 476 | req.onResourceLoad(context, map, manager.depArray); 477 | } 478 | 479 | if (err) { 480 | errFile = (fullName ? makeModuleMap(fullName).url : '') || 481 | err.fileName || err.sourceURL; 482 | errModuleTree = err.moduleTree; 483 | err = makeError('defineerror', 'Error evaluating ' + 484 | 'module "' + fullName + '" at location "' + 485 | errFile + '":\n' + 486 | err + '\nfileName:' + errFile + 487 | '\nlineNumber: ' + (err.lineNumber || err.line), err); 488 | err.moduleName = fullName; 489 | err.moduleTree = errModuleTree; 490 | return req.onError(err); 491 | } 492 | 493 | //Let listeners know of this manager's value. 494 | for (i = 0; (cb = listeners[i]); i++) { 495 | cb(ret); 496 | } 497 | 498 | return undefined; 499 | } 500 | 501 | /** 502 | * Helper that creates a callack function that is called when a dependency 503 | * is ready, and sets the i-th dependency for the manager as the 504 | * value passed to the callback generated by this function. 505 | */ 506 | function makeArgCallback(manager, i) { 507 | return function (value) { 508 | //Only do the work if it has not been done 509 | //already for a dependency. Cycle breaking 510 | //logic in forceExec could mean this function 511 | //is called more than once for a given dependency. 512 | if (!manager.depDone[i]) { 513 | manager.depDone[i] = true; 514 | manager.deps[i] = value; 515 | manager.depCount -= 1; 516 | if (!manager.depCount) { 517 | //All done, execute! 518 | execManager(manager); 519 | } 520 | } 521 | }; 522 | } 523 | 524 | function callPlugin(pluginName, depManager) { 525 | var map = depManager.map, 526 | fullName = map.fullName, 527 | name = map.name, 528 | plugin = plugins[pluginName] || 529 | (plugins[pluginName] = defined[pluginName]), 530 | load; 531 | 532 | //No need to continue if the manager is already 533 | //in the process of loading. 534 | if (depManager.loading) { 535 | return; 536 | } 537 | depManager.loading = true; 538 | 539 | load = function (ret) { 540 | depManager.callback = function () { 541 | return ret; 542 | }; 543 | execManager(depManager); 544 | 545 | loaded[depManager.id] = true; 546 | 547 | //The loading of this plugin 548 | //might have placed other things 549 | //in the paused queue. In particular, 550 | //a loader plugin that depends on 551 | //a different plugin loaded resource. 552 | resume(); 553 | }; 554 | 555 | //Allow plugins to load other code without having to know the 556 | //context or how to "complete" the load. 557 | load.fromText = function (moduleName, text) { 558 | /*jslint evil: true */ 559 | var hasInteractive = useInteractive; 560 | 561 | //Indicate a the module is in process of loading. 562 | loaded[moduleName] = false; 563 | context.scriptCount += 1; 564 | 565 | //Indicate this is not a "real" module, so do not track it 566 | //for builds, it does not map to a real file. 567 | context.fake[moduleName] = true; 568 | 569 | //Turn off interactive script matching for IE for any define 570 | //calls in the text, then turn it back on at the end. 571 | if (hasInteractive) { 572 | useInteractive = false; 573 | } 574 | 575 | req.exec(text); 576 | 577 | if (hasInteractive) { 578 | useInteractive = true; 579 | } 580 | 581 | //Support anonymous modules. 582 | context.completeLoad(moduleName); 583 | }; 584 | 585 | //No need to continue if the plugin value has already been 586 | //defined by a build. 587 | if (fullName in defined) { 588 | load(defined[fullName]); 589 | } else { 590 | //Use parentName here since the plugin's name is not reliable, 591 | //could be some weird string with no path that actually wants to 592 | //reference the parentName's path. 593 | plugin.load(name, makeRequire(map.parentMap, true), load, config); 594 | } 595 | } 596 | 597 | /** 598 | * Adds the manager to the waiting queue. Only fully 599 | * resolved items should be in the waiting queue. 600 | */ 601 | function addWait(manager) { 602 | if (!waiting[manager.id]) { 603 | waiting[manager.id] = manager; 604 | waitAry.push(manager); 605 | context.waitCount += 1; 606 | } 607 | } 608 | 609 | /** 610 | * Function added to every manager object. Created out here 611 | * to avoid new function creation for each manager instance. 612 | */ 613 | function managerAdd(cb) { 614 | this.listeners.push(cb); 615 | } 616 | 617 | function getManager(map, shouldQueue) { 618 | var fullName = map.fullName, 619 | prefix = map.prefix, 620 | plugin = prefix ? plugins[prefix] || 621 | (plugins[prefix] = defined[prefix]) : null, 622 | manager, created, pluginManager; 623 | 624 | if (fullName) { 625 | manager = managerCallbacks[fullName]; 626 | } 627 | 628 | if (!manager) { 629 | created = true; 630 | manager = { 631 | //ID is just the full name, but if it is a plugin resource 632 | //for a plugin that has not been loaded, 633 | //then add an ID counter to it. 634 | id: (prefix && !plugin ? 635 | (managerCounter++) + '__p@:' : '') + 636 | (fullName || '__r@' + (managerCounter++)), 637 | map: map, 638 | depCount: 0, 639 | depDone: [], 640 | depCallbacks: [], 641 | deps: [], 642 | listeners: [], 643 | add: managerAdd 644 | }; 645 | 646 | specified[manager.id] = true; 647 | 648 | //Only track the manager/reuse it if this is a non-plugin 649 | //resource. Also only track plugin resources once 650 | //the plugin has been loaded, and so the fullName is the 651 | //true normalized value. 652 | if (fullName && (!prefix || plugins[prefix])) { 653 | managerCallbacks[fullName] = manager; 654 | } 655 | } 656 | 657 | //If there is a plugin needed, but it is not loaded, 658 | //first load the plugin, then continue on. 659 | if (prefix && !plugin) { 660 | pluginManager = getManager(makeModuleMap(prefix), true); 661 | pluginManager.add(function (plugin) { 662 | //Create a new manager for the normalized 663 | //resource ID and have it call this manager when 664 | //done. 665 | var newMap = makeModuleMap(map.originalName, map.parentMap), 666 | normalizedManager = getManager(newMap, true); 667 | 668 | //Indicate this manager is a placeholder for the real, 669 | //normalized thing. Important for when trying to map 670 | //modules and dependencies, for instance, in a build. 671 | manager.placeholder = true; 672 | 673 | normalizedManager.add(function (resource) { 674 | manager.callback = function () { 675 | return resource; 676 | }; 677 | execManager(manager); 678 | }); 679 | }); 680 | } else if (created && shouldQueue) { 681 | //Indicate the resource is not loaded yet if it is to be 682 | //queued. 683 | loaded[manager.id] = false; 684 | queueDependency(manager); 685 | addWait(manager); 686 | } 687 | 688 | return manager; 689 | } 690 | 691 | function main(inName, depArray, callback, relModuleMap) { 692 | var moduleMap = makeModuleMap(inName, relModuleMap), 693 | name = moduleMap.name, 694 | fullName = moduleMap.fullName, 695 | manager = getManager(moduleMap), 696 | id = manager.id, 697 | deps = manager.deps, 698 | i, depArg, depName, depPrefix, cjsMod; 699 | 700 | if (fullName) { 701 | //If module already defined for context, or already loaded, 702 | //then leave. Also leave if jQuery is registering but it does 703 | //not match the desired version number in the config. 704 | if (fullName in defined || loaded[id] === true || 705 | (fullName === "jquery" && config.jQuery && 706 | config.jQuery !== callback().fn.jquery)) { 707 | return; 708 | } 709 | 710 | //Set specified/loaded here for modules that are also loaded 711 | //as part of a layer, where onScriptLoad is not fired 712 | //for those cases. Do this after the inline define and 713 | //dependency tracing is done. 714 | specified[id] = true; 715 | loaded[id] = true; 716 | 717 | //If module is jQuery set up delaying its dom ready listeners. 718 | if (fullName === "jquery" && callback) { 719 | jQueryCheck(callback()); 720 | } 721 | } 722 | 723 | //Attach real depArray and callback to the manager. Do this 724 | //only if the module has not been defined already, so do this after 725 | //the fullName checks above. IE can call main() more than once 726 | //for a module. 727 | manager.depArray = depArray; 728 | manager.callback = callback; 729 | 730 | //Add the dependencies to the deps field, and register for callbacks 731 | //on the dependencies. 732 | for (i = 0; i < depArray.length; i++) { 733 | depArg = depArray[i]; 734 | //There could be cases like in IE, where a trailing comma will 735 | //introduce a null dependency, so only treat a real dependency 736 | //value as a dependency. 737 | if (depArg) { 738 | //Split the dependency name into plugin and name parts 739 | depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap)); 740 | depName = depArg.fullName; 741 | depPrefix = depArg.prefix; 742 | 743 | //Fix the name in depArray to be just the name, since 744 | //that is how it will be called back later. 745 | depArray[i] = depName; 746 | 747 | //Fast path CommonJS standard dependencies. 748 | if (depName === "require") { 749 | deps[i] = makeRequire(moduleMap); 750 | } else if (depName === "exports") { 751 | //CommonJS module spec 1.1 752 | deps[i] = defined[fullName] = {}; 753 | manager.usingExports = true; 754 | } else if (depName === "module") { 755 | //CommonJS module spec 1.1 756 | manager.cjsModule = cjsMod = deps[i] = { 757 | id: name, 758 | uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined, 759 | exports: defined[fullName] 760 | }; 761 | } else if (depName in defined && !(depName in waiting) && 762 | (!(fullName in needFullExec) || 763 | (fullName in needFullExec && fullExec[depName]))) { 764 | //Module already defined, and not in a build situation 765 | //where the module is a something that needs full 766 | //execution and this dependency has not been fully 767 | //executed. See r.js's requirePatch.js for more info 768 | //on fullExec. 769 | deps[i] = defined[depName]; 770 | } else { 771 | //Mark this dependency as needing full exec if 772 | //the current module needs full exec. 773 | if (fullName in needFullExec) { 774 | needFullExec[depName] = true; 775 | //Reset state so fully executed code will get 776 | //picked up correctly. 777 | delete defined[depName]; 778 | urlFetched[depArg.url] = false; 779 | } 780 | 781 | //Either a resource that is not loaded yet, or a plugin 782 | //resource for either a plugin that has not 783 | //loaded yet. 784 | manager.depCount += 1; 785 | manager.depCallbacks[i] = makeArgCallback(manager, i); 786 | getManager(depArg, true).add(manager.depCallbacks[i]); 787 | } 788 | } 789 | } 790 | 791 | //Do not bother tracking the manager if it is all done. 792 | if (!manager.depCount) { 793 | //All done, execute! 794 | execManager(manager); 795 | } else { 796 | addWait(manager); 797 | } 798 | } 799 | 800 | /** 801 | * Convenience method to call main for a define call that was put on 802 | * hold in the defQueue. 803 | */ 804 | function callDefMain(args) { 805 | main.apply(null, args); 806 | } 807 | 808 | /** 809 | * jQuery 1.4.3+ supports ways to hold off calling 810 | * calling jQuery ready callbacks until all scripts are loaded. Be sure 811 | * to track it if the capability exists.. Also, since jQuery 1.4.3 does 812 | * not register as a module, need to do some global inference checking. 813 | * Even if it does register as a module, not guaranteed to be the precise 814 | * name of the global. If a jQuery is tracked for this context, then go 815 | * ahead and register it as a module too, if not already in process. 816 | */ 817 | jQueryCheck = function (jqCandidate) { 818 | if (!context.jQuery) { 819 | var $ = jqCandidate || (typeof jQuery !== "undefined" ? jQuery : null); 820 | 821 | if ($) { 822 | //If a specific version of jQuery is wanted, make sure to only 823 | //use this jQuery if it matches. 824 | if (config.jQuery && $.fn.jquery !== config.jQuery) { 825 | return; 826 | } 827 | 828 | if ("holdReady" in $ || "readyWait" in $) { 829 | context.jQuery = $; 830 | 831 | //Manually create a "jquery" module entry if not one already 832 | //or in process. Note this could trigger an attempt at 833 | //a second jQuery registration, but does no harm since 834 | //the first one wins, and it is the same value anyway. 835 | callDefMain(["jquery", [], function () { 836 | return jQuery; 837 | }]); 838 | 839 | //Ask jQuery to hold DOM ready callbacks. 840 | if (context.scriptCount) { 841 | jQueryHoldReady($, true); 842 | context.jQueryIncremented = true; 843 | } 844 | } 845 | } 846 | } 847 | }; 848 | 849 | function forceExec(manager, traced) { 850 | if (manager.isDone) { 851 | return undefined; 852 | } 853 | 854 | var fullName = manager.map.fullName, 855 | depArray = manager.depArray, 856 | i, depName, depManager, prefix, prefixManager, value; 857 | 858 | if (fullName) { 859 | if (traced[fullName]) { 860 | return defined[fullName]; 861 | } 862 | 863 | traced[fullName] = true; 864 | } 865 | 866 | //Trace through the dependencies. 867 | if (depArray) { 868 | for (i = 0; i < depArray.length; i++) { 869 | //Some array members may be null, like if a trailing comma 870 | //IE, so do the explicit [i] access and check if it has a value. 871 | depName = depArray[i]; 872 | if (depName) { 873 | //First, make sure if it is a plugin resource that the 874 | //plugin is not blocked. 875 | prefix = makeModuleMap(depName).prefix; 876 | if (prefix && (prefixManager = waiting[prefix])) { 877 | forceExec(prefixManager, traced); 878 | } 879 | depManager = waiting[depName]; 880 | if (depManager && !depManager.isDone && loaded[depName]) { 881 | value = forceExec(depManager, traced); 882 | manager.depCallbacks[i](value); 883 | } 884 | } 885 | } 886 | } 887 | 888 | return fullName ? defined[fullName] : undefined; 889 | } 890 | 891 | /** 892 | * Checks if all modules for a context are loaded, and if so, evaluates the 893 | * new ones in right dependency order. 894 | * 895 | * @private 896 | */ 897 | function checkLoaded() { 898 | var waitInterval = config.waitSeconds * 1000, 899 | //It is possible to disable the wait interval by using waitSeconds of 0. 900 | expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(), 901 | noLoads = "", hasLoadedProp = false, stillLoading = false, prop, 902 | err, manager; 903 | 904 | //If there are items still in the paused queue processing wait. 905 | //This is particularly important in the sync case where each paused 906 | //item is processed right away but there may be more waiting. 907 | if (context.pausedCount > 0) { 908 | return undefined; 909 | } 910 | 911 | //Determine if priority loading is done. If so clear the priority. If 912 | //not, then do not check 913 | if (config.priorityWait) { 914 | if (isPriorityDone()) { 915 | //Call resume, since it could have 916 | //some waiting dependencies to trace. 917 | resume(); 918 | } else { 919 | return undefined; 920 | } 921 | } 922 | 923 | //See if anything is still in flight. 924 | for (prop in loaded) { 925 | if (!(prop in empty)) { 926 | hasLoadedProp = true; 927 | if (!loaded[prop]) { 928 | if (expired) { 929 | noLoads += prop + " "; 930 | } else { 931 | stillLoading = true; 932 | break; 933 | } 934 | } 935 | } 936 | } 937 | 938 | //Check for exit conditions. 939 | if (!hasLoadedProp && !context.waitCount) { 940 | //If the loaded object had no items, then the rest of 941 | //the work below does not need to be done. 942 | return undefined; 943 | } 944 | if (expired && noLoads) { 945 | //If wait time expired, throw error of unloaded modules. 946 | err = makeError("timeout", "Load timeout for modules: " + noLoads); 947 | err.requireType = "timeout"; 948 | err.requireModules = noLoads; 949 | return req.onError(err); 950 | } 951 | if (stillLoading || context.scriptCount) { 952 | //Something is still waiting to load. Wait for it, but only 953 | //if a timeout is not already in effect. 954 | if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) { 955 | checkLoadedTimeoutId = setTimeout(function () { 956 | checkLoadedTimeoutId = 0; 957 | checkLoaded(); 958 | }, 50); 959 | } 960 | return undefined; 961 | } 962 | 963 | //If still have items in the waiting cue, but all modules have 964 | //been loaded, then it means there are some circular dependencies 965 | //that need to be broken. 966 | //However, as a waiting thing is fired, then it can add items to 967 | //the waiting cue, and those items should not be fired yet, so 968 | //make sure to redo the checkLoaded call after breaking a single 969 | //cycle, if nothing else loaded then this logic will pick it up 970 | //again. 971 | if (context.waitCount) { 972 | //Cycle through the waitAry, and call items in sequence. 973 | for (i = 0; (manager = waitAry[i]); i++) { 974 | forceExec(manager, {}); 975 | } 976 | 977 | //If anything got placed in the paused queue, run it down. 978 | if (context.paused.length) { 979 | resume(); 980 | } 981 | 982 | //Only allow this recursion to a certain depth. Only 983 | //triggered by errors in calling a module in which its 984 | //modules waiting on it cannot finish loading, or some circular 985 | //dependencies that then may add more dependencies. 986 | //The value of 5 is a bit arbitrary. Hopefully just one extra 987 | //pass, or two for the case of circular dependencies generating 988 | //more work that gets resolved in the sync node case. 989 | if (checkLoadedDepth < 5) { 990 | checkLoadedDepth += 1; 991 | checkLoaded(); 992 | } 993 | } 994 | 995 | checkLoadedDepth = 0; 996 | 997 | //Check for DOM ready, and nothing is waiting across contexts. 998 | req.checkReadyState(); 999 | 1000 | return undefined; 1001 | } 1002 | 1003 | /** 1004 | * Resumes tracing of dependencies and then checks if everything is loaded. 1005 | */ 1006 | resume = function () { 1007 | var manager, map, url, i, p, args, fullName; 1008 | 1009 | resumeDepth += 1; 1010 | 1011 | if (context.scriptCount <= 0) { 1012 | //Synchronous envs will push the number below zero with the 1013 | //decrement above, be sure to set it back to zero for good measure. 1014 | //require() calls that also do not end up loading scripts could 1015 | //push the number negative too. 1016 | context.scriptCount = 0; 1017 | } 1018 | 1019 | //Make sure any remaining defQueue items get properly processed. 1020 | while (defQueue.length) { 1021 | args = defQueue.shift(); 1022 | if (args[0] === null) { 1023 | return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1])); 1024 | } else { 1025 | callDefMain(args); 1026 | } 1027 | } 1028 | 1029 | //Skip the resume of paused dependencies 1030 | //if current context is in priority wait. 1031 | if (!config.priorityWait || isPriorityDone()) { 1032 | while (context.paused.length) { 1033 | p = context.paused; 1034 | context.pausedCount += p.length; 1035 | //Reset paused list 1036 | context.paused = []; 1037 | 1038 | for (i = 0; (manager = p[i]); i++) { 1039 | map = manager.map; 1040 | url = map.url; 1041 | fullName = map.fullName; 1042 | 1043 | //If the manager is for a plugin managed resource, 1044 | //ask the plugin to load it now. 1045 | if (map.prefix) { 1046 | callPlugin(map.prefix, manager); 1047 | } else { 1048 | //Regular dependency. 1049 | if (!urlFetched[url] && !loaded[fullName]) { 1050 | req.load(context, fullName, url); 1051 | urlFetched[url] = true; 1052 | } 1053 | } 1054 | } 1055 | 1056 | //Move the start time for timeout forward. 1057 | context.startTime = (new Date()).getTime(); 1058 | context.pausedCount -= p.length; 1059 | } 1060 | } 1061 | 1062 | //Only check if loaded when resume depth is 1. It is likely that 1063 | //it is only greater than 1 in sync environments where a factory 1064 | //function also then calls the callback-style require. In those 1065 | //cases, the checkLoaded should not occur until the resume 1066 | //depth is back at the top level. 1067 | if (resumeDepth === 1) { 1068 | checkLoaded(); 1069 | } 1070 | 1071 | resumeDepth -= 1; 1072 | 1073 | return undefined; 1074 | }; 1075 | 1076 | //Define the context object. Many of these fields are on here 1077 | //just to make debugging easier. 1078 | context = { 1079 | contextName: contextName, 1080 | config: config, 1081 | defQueue: defQueue, 1082 | waiting: waiting, 1083 | waitCount: 0, 1084 | specified: specified, 1085 | loaded: loaded, 1086 | urlMap: urlMap, 1087 | urlFetched: urlFetched, 1088 | scriptCount: 0, 1089 | defined: defined, 1090 | paused: [], 1091 | pausedCount: 0, 1092 | plugins: plugins, 1093 | needFullExec: needFullExec, 1094 | fake: {}, 1095 | fullExec: fullExec, 1096 | managerCallbacks: managerCallbacks, 1097 | makeModuleMap: makeModuleMap, 1098 | normalize: normalize, 1099 | /** 1100 | * Set a configuration for the context. 1101 | * @param {Object} cfg config object to integrate. 1102 | */ 1103 | configure: function (cfg) { 1104 | var paths, prop, packages, pkgs, packagePaths, requireWait; 1105 | 1106 | //Make sure the baseUrl ends in a slash. 1107 | if (cfg.baseUrl) { 1108 | if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== "/") { 1109 | cfg.baseUrl += "/"; 1110 | } 1111 | } 1112 | 1113 | //Save off the paths and packages since they require special processing, 1114 | //they are additive. 1115 | paths = config.paths; 1116 | packages = config.packages; 1117 | pkgs = config.pkgs; 1118 | 1119 | //Mix in the config values, favoring the new values over 1120 | //existing ones in context.config. 1121 | mixin(config, cfg, true); 1122 | 1123 | //Adjust paths if necessary. 1124 | if (cfg.paths) { 1125 | for (prop in cfg.paths) { 1126 | if (!(prop in empty)) { 1127 | paths[prop] = cfg.paths[prop]; 1128 | } 1129 | } 1130 | config.paths = paths; 1131 | } 1132 | 1133 | packagePaths = cfg.packagePaths; 1134 | if (packagePaths || cfg.packages) { 1135 | //Convert packagePaths into a packages config. 1136 | if (packagePaths) { 1137 | for (prop in packagePaths) { 1138 | if (!(prop in empty)) { 1139 | configurePackageDir(pkgs, packagePaths[prop], prop); 1140 | } 1141 | } 1142 | } 1143 | 1144 | //Adjust packages if necessary. 1145 | if (cfg.packages) { 1146 | configurePackageDir(pkgs, cfg.packages); 1147 | } 1148 | 1149 | //Done with modifications, assing packages back to context config 1150 | config.pkgs = pkgs; 1151 | } 1152 | 1153 | //If priority loading is in effect, trigger the loads now 1154 | if (cfg.priority) { 1155 | //Hold on to requireWait value, and reset it after done 1156 | requireWait = context.requireWait; 1157 | 1158 | //Allow tracing some require calls to allow the fetching 1159 | //of the priority config. 1160 | context.requireWait = false; 1161 | //But first, call resume to register any defined modules that may 1162 | //be in a data-main built file before the priority config 1163 | //call. Also grab any waiting define calls for this context. 1164 | context.takeGlobalQueue(); 1165 | resume(); 1166 | 1167 | context.require(cfg.priority); 1168 | 1169 | //Trigger a resume right away, for the case when 1170 | //the script with the priority load is done as part 1171 | //of a data-main call. In that case the normal resume 1172 | //call will not happen because the scriptCount will be 1173 | //at 1, since the script for data-main is being processed. 1174 | resume(); 1175 | 1176 | //Restore previous state. 1177 | context.requireWait = requireWait; 1178 | config.priorityWait = cfg.priority; 1179 | } 1180 | 1181 | //If a deps array or a config callback is specified, then call 1182 | //require with those args. This is useful when require is defined as a 1183 | //config object before require.js is loaded. 1184 | if (cfg.deps || cfg.callback) { 1185 | context.require(cfg.deps || [], cfg.callback); 1186 | } 1187 | }, 1188 | 1189 | requireDefined: function (moduleName, relModuleMap) { 1190 | return makeModuleMap(moduleName, relModuleMap).fullName in defined; 1191 | }, 1192 | 1193 | requireSpecified: function (moduleName, relModuleMap) { 1194 | return makeModuleMap(moduleName, relModuleMap).fullName in specified; 1195 | }, 1196 | 1197 | require: function (deps, callback, relModuleMap) { 1198 | var moduleName, fullName, moduleMap; 1199 | if (typeof deps === "string") { 1200 | if (isFunction(callback)) { 1201 | //Invalid call 1202 | return req.onError(makeError("requireargs", "Invalid require call")); 1203 | } 1204 | 1205 | //Synchronous access to one module. If require.get is 1206 | //available (as in the Node adapter), prefer that. 1207 | //In this case deps is the moduleName and callback is 1208 | //the relModuleMap 1209 | if (req.get) { 1210 | return req.get(context, deps, callback); 1211 | } 1212 | 1213 | //Just return the module wanted. In this scenario, the 1214 | //second arg (if passed) is just the relModuleMap. 1215 | moduleName = deps; 1216 | relModuleMap = callback; 1217 | 1218 | //Normalize module name, if it contains . or .. 1219 | moduleMap = makeModuleMap(moduleName, relModuleMap); 1220 | fullName = moduleMap.fullName; 1221 | 1222 | if (!(fullName in defined)) { 1223 | return req.onError(makeError("notloaded", "Module name '" + 1224 | moduleMap.fullName + 1225 | "' has not been loaded yet for context: " + 1226 | contextName)); 1227 | } 1228 | return defined[fullName]; 1229 | } 1230 | 1231 | //Call main but only if there are dependencies or 1232 | //a callback to call. 1233 | if (deps && deps.length || callback) { 1234 | main(null, deps, callback, relModuleMap); 1235 | } 1236 | 1237 | //If the require call does not trigger anything new to load, 1238 | //then resume the dependency processing. 1239 | if (!context.requireWait) { 1240 | while (!context.scriptCount && context.paused.length) { 1241 | //For built layers, there can be some defined 1242 | //modules waiting for intake into the context, 1243 | //in particular module plugins. Take them. 1244 | context.takeGlobalQueue(); 1245 | resume(); 1246 | } 1247 | } 1248 | return context.require; 1249 | }, 1250 | 1251 | /** 1252 | * Internal method to transfer globalQueue items to this context's 1253 | * defQueue. 1254 | */ 1255 | takeGlobalQueue: function () { 1256 | //Push all the globalDefQueue items into the context's defQueue 1257 | if (globalDefQueue.length) { 1258 | //Array splice in the values since the context code has a 1259 | //local var ref to defQueue, so cannot just reassign the one 1260 | //on context. 1261 | apsp.apply(context.defQueue, 1262 | [context.defQueue.length - 1, 0].concat(globalDefQueue)); 1263 | globalDefQueue = []; 1264 | } 1265 | }, 1266 | 1267 | /** 1268 | * Internal method used by environment adapters to complete a load event. 1269 | * A load event could be a script load or just a load pass from a synchronous 1270 | * load call. 1271 | * @param {String} moduleName the name of the module to potentially complete. 1272 | */ 1273 | completeLoad: function (moduleName) { 1274 | var args; 1275 | 1276 | context.takeGlobalQueue(); 1277 | 1278 | while (defQueue.length) { 1279 | args = defQueue.shift(); 1280 | 1281 | if (args[0] === null) { 1282 | args[0] = moduleName; 1283 | break; 1284 | } else if (args[0] === moduleName) { 1285 | //Found matching define call for this script! 1286 | break; 1287 | } else { 1288 | //Some other named define call, most likely the result 1289 | //of a build layer that included many define calls. 1290 | callDefMain(args); 1291 | args = null; 1292 | } 1293 | } 1294 | if (args) { 1295 | callDefMain(args); 1296 | } else { 1297 | //A script that does not call define(), so just simulate 1298 | //the call for it. Special exception for jQuery dynamic load. 1299 | callDefMain([moduleName, [], 1300 | moduleName === "jquery" && typeof jQuery !== "undefined" ? 1301 | function () { 1302 | return jQuery; 1303 | } : null]); 1304 | } 1305 | 1306 | //If a global jQuery is defined, check for it. Need to do it here 1307 | //instead of main() since stock jQuery does not register as 1308 | //a module via define. 1309 | jQueryCheck(); 1310 | 1311 | //Doing this scriptCount decrement branching because sync envs 1312 | //need to decrement after resume, otherwise it looks like 1313 | //loading is complete after the first dependency is fetched. 1314 | //For browsers, it works fine to decrement after, but it means 1315 | //the checkLoaded setTimeout 50 ms cost is taken. To avoid 1316 | //that cost, decrement beforehand. 1317 | if (req.isAsync) { 1318 | context.scriptCount -= 1; 1319 | } 1320 | resume(); 1321 | if (!req.isAsync) { 1322 | context.scriptCount -= 1; 1323 | } 1324 | }, 1325 | 1326 | /** 1327 | * Converts a module name + .extension into an URL path. 1328 | * *Requires* the use of a module name. It does not support using 1329 | * plain URLs like nameToUrl. 1330 | */ 1331 | toUrl: function (moduleNamePlusExt, relModuleMap) { 1332 | var index = moduleNamePlusExt.lastIndexOf("."), 1333 | ext = null; 1334 | 1335 | if (index !== -1) { 1336 | ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); 1337 | moduleNamePlusExt = moduleNamePlusExt.substring(0, index); 1338 | } 1339 | 1340 | return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap); 1341 | }, 1342 | 1343 | /** 1344 | * Converts a module name to a file path. Supports cases where 1345 | * moduleName may actually be just an URL. 1346 | */ 1347 | nameToUrl: function (moduleName, ext, relModuleMap) { 1348 | var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, 1349 | config = context.config; 1350 | 1351 | //Normalize module name if have a base relative module name to work from. 1352 | moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName); 1353 | 1354 | //If a colon is in the URL, it indicates a protocol is used and it is just 1355 | //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file. 1356 | //The slash is important for protocol-less URLs as well as full paths. 1357 | if (req.jsExtRegExp.test(moduleName)) { 1358 | //Just a plain path, not module name lookup, so just return it. 1359 | //Add extension if it is included. This is a bit wonky, only non-.js things pass 1360 | //an extension, this method probably needs to be reworked. 1361 | url = moduleName + (ext ? ext : ""); 1362 | } else { 1363 | //A module that needs to be converted to a path. 1364 | paths = config.paths; 1365 | pkgs = config.pkgs; 1366 | 1367 | syms = moduleName.split("/"); 1368 | //For each module name segment, see if there is a path 1369 | //registered for it. Start with most specific name 1370 | //and work up from it. 1371 | for (i = syms.length; i > 0; i--) { 1372 | parentModule = syms.slice(0, i).join("/"); 1373 | if (paths[parentModule]) { 1374 | syms.splice(0, i, paths[parentModule]); 1375 | break; 1376 | } else if ((pkg = pkgs[parentModule])) { 1377 | //If module name is just the package name, then looking 1378 | //for the main module. 1379 | if (moduleName === pkg.name) { 1380 | pkgPath = pkg.location + '/' + pkg.main; 1381 | } else { 1382 | pkgPath = pkg.location; 1383 | } 1384 | syms.splice(0, i, pkgPath); 1385 | break; 1386 | } 1387 | } 1388 | 1389 | //Join the path parts together, then figure out if baseUrl is needed. 1390 | url = syms.join("/") + (ext || ".js"); 1391 | url = (url.charAt(0) === '/' || url.match(/^\w+:/) ? "" : config.baseUrl) + url; 1392 | } 1393 | 1394 | return config.urlArgs ? url + 1395 | ((url.indexOf('?') === -1 ? '?' : '&') + 1396 | config.urlArgs) : url; 1397 | } 1398 | }; 1399 | 1400 | //Make these visible on the context so can be called at the very 1401 | //end of the file to bootstrap 1402 | context.jQueryCheck = jQueryCheck; 1403 | context.resume = resume; 1404 | 1405 | return context; 1406 | } 1407 | 1408 | /** 1409 | * Main entry point. 1410 | * 1411 | * If the only argument to require is a string, then the module that 1412 | * is represented by that string is fetched for the appropriate context. 1413 | * 1414 | * If the first argument is an array, then it will be treated as an array 1415 | * of dependency string names to fetch. An optional function callback can 1416 | * be specified to execute when all of those dependencies are available. 1417 | * 1418 | * Make a local req variable to help Caja compliance (it assumes things 1419 | * on a require that are not standardized), and to give a short 1420 | * name for minification/local scope use. 1421 | */ 1422 | req = requirejs = function (deps, callback) { 1423 | 1424 | //Find the right context, use default 1425 | var contextName = defContextName, 1426 | context, config; 1427 | 1428 | // Determine if have config object in the call. 1429 | if (!isArray(deps) && typeof deps !== "string") { 1430 | // deps is a config object 1431 | config = deps; 1432 | if (isArray(callback)) { 1433 | // Adjust args if there are dependencies 1434 | deps = callback; 1435 | callback = arguments[2]; 1436 | } else { 1437 | deps = []; 1438 | } 1439 | } 1440 | 1441 | if (config && config.context) { 1442 | contextName = config.context; 1443 | } 1444 | 1445 | context = contexts[contextName] || 1446 | (contexts[contextName] = newContext(contextName)); 1447 | 1448 | if (config) { 1449 | context.configure(config); 1450 | } 1451 | 1452 | return context.require(deps, callback); 1453 | }; 1454 | 1455 | /** 1456 | * Support require.config() to make it easier to cooperate with other 1457 | * AMD loaders on globally agreed names. 1458 | */ 1459 | req.config = function (config) { 1460 | return req(config); 1461 | }; 1462 | 1463 | /** 1464 | * Export require as a global, but only if it does not already exist. 1465 | */ 1466 | if (!require) { 1467 | require = req; 1468 | } 1469 | 1470 | /** 1471 | * Global require.toUrl(), to match global require, mostly useful 1472 | * for debugging/work in the global space. 1473 | */ 1474 | req.toUrl = function (moduleNamePlusExt) { 1475 | return contexts[defContextName].toUrl(moduleNamePlusExt); 1476 | }; 1477 | 1478 | req.version = version; 1479 | 1480 | //Used to filter out dependencies that are already paths. 1481 | req.jsExtRegExp = /^\/|:|\?|\.js$/; 1482 | s = req.s = { 1483 | contexts: contexts, 1484 | //Stores a list of URLs that should not get async script tag treatment. 1485 | skipAsync: {} 1486 | }; 1487 | 1488 | req.isAsync = req.isBrowser = isBrowser; 1489 | if (isBrowser) { 1490 | head = s.head = document.getElementsByTagName("head")[0]; 1491 | //If BASE tag is in play, using appendChild is a problem for IE6. 1492 | //When that browser dies, this can be removed. Details in this jQuery bug: 1493 | //http://dev.jquery.com/ticket/2709 1494 | baseElement = document.getElementsByTagName("base")[0]; 1495 | if (baseElement) { 1496 | head = s.head = baseElement.parentNode; 1497 | } 1498 | } 1499 | 1500 | /** 1501 | * Any errors that require explicitly generates will be passed to this 1502 | * function. Intercept/override it if you want custom error handling. 1503 | * @param {Error} err the error object. 1504 | */ 1505 | req.onError = function (err) { 1506 | throw err; 1507 | }; 1508 | 1509 | /** 1510 | * Does the request to load a module for the browser case. 1511 | * Make this a separate function to allow other environments 1512 | * to override it. 1513 | * 1514 | * @param {Object} context the require context to find state. 1515 | * @param {String} moduleName the name of the module. 1516 | * @param {Object} url the URL to the module. 1517 | */ 1518 | req.load = function (context, moduleName, url) { 1519 | req.resourcesReady(false); 1520 | 1521 | context.scriptCount += 1; 1522 | req.attach(url, context, moduleName); 1523 | 1524 | //If tracking a jQuery, then make sure its ready callbacks 1525 | //are put on hold to prevent its ready callbacks from 1526 | //triggering too soon. 1527 | if (context.jQuery && !context.jQueryIncremented) { 1528 | jQueryHoldReady(context.jQuery, true); 1529 | context.jQueryIncremented = true; 1530 | } 1531 | }; 1532 | 1533 | function getInteractiveScript() { 1534 | var scripts, i, script; 1535 | if (interactiveScript && interactiveScript.readyState === 'interactive') { 1536 | return interactiveScript; 1537 | } 1538 | 1539 | scripts = document.getElementsByTagName('script'); 1540 | for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) { 1541 | if (script.readyState === 'interactive') { 1542 | return (interactiveScript = script); 1543 | } 1544 | } 1545 | 1546 | return null; 1547 | } 1548 | 1549 | /** 1550 | * The function that handles definitions of modules. Differs from 1551 | * require() in that a string for the module should be the first argument, 1552 | * and the function to execute after dependencies are loaded should 1553 | * return a value to define the module corresponding to the first argument's 1554 | * name. 1555 | */ 1556 | define = function (name, deps, callback) { 1557 | var node, context; 1558 | 1559 | //Allow for anonymous functions 1560 | if (typeof name !== 'string') { 1561 | //Adjust args appropriately 1562 | callback = deps; 1563 | deps = name; 1564 | name = null; 1565 | } 1566 | 1567 | //This module may not have dependencies 1568 | if (!isArray(deps)) { 1569 | callback = deps; 1570 | deps = []; 1571 | } 1572 | 1573 | //If no name, and callback is a function, then figure out if it a 1574 | //CommonJS thing with dependencies. 1575 | if (!deps.length && isFunction(callback)) { 1576 | //Remove comments from the callback string, 1577 | //look for require calls, and pull them into the dependencies, 1578 | //but only if there are function args. 1579 | if (callback.length) { 1580 | callback 1581 | .toString() 1582 | .replace(commentRegExp, "") 1583 | .replace(cjsRequireRegExp, function (match, dep) { 1584 | deps.push(dep); 1585 | }); 1586 | 1587 | //May be a CommonJS thing even without require calls, but still 1588 | //could use exports, and module. Avoid doing exports and module 1589 | //work though if it just needs require. 1590 | //REQUIRES the function to expect the CommonJS variables in the 1591 | //order listed below. 1592 | deps = (callback.length === 1 ? ["require"] : ["require", "exports", "module"]).concat(deps); 1593 | } 1594 | } 1595 | 1596 | //If in IE 6-8 and hit an anonymous define() call, do the interactive 1597 | //work. 1598 | if (useInteractive) { 1599 | node = currentlyAddingScript || getInteractiveScript(); 1600 | if (node) { 1601 | if (!name) { 1602 | name = node.getAttribute("data-requiremodule"); 1603 | } 1604 | context = contexts[node.getAttribute("data-requirecontext")]; 1605 | } 1606 | } 1607 | 1608 | //Always save off evaluating the def call until the script onload handler. 1609 | //This allows multiple modules to be in a file without prematurely 1610 | //tracing dependencies, and allows for anonymous module support, 1611 | //where the module name is not known until the script onload event 1612 | //occurs. If no context, use the global queue, and get it processed 1613 | //in the onscript load callback. 1614 | (context ? context.defQueue : globalDefQueue).push([name, deps, callback]); 1615 | 1616 | return undefined; 1617 | }; 1618 | 1619 | define.amd = { 1620 | multiversion: true, 1621 | plugins: true, 1622 | jQuery: true 1623 | }; 1624 | 1625 | /** 1626 | * Executes the text. Normally just uses eval, but can be modified 1627 | * to use a more environment specific call. 1628 | * @param {String} text the text to execute/evaluate. 1629 | */ 1630 | req.exec = function (text) { 1631 | return eval(text); 1632 | }; 1633 | 1634 | /** 1635 | * Executes a module callack function. Broken out as a separate function 1636 | * solely to allow the build system to sequence the files in the built 1637 | * layer in the right sequence. 1638 | * 1639 | * @private 1640 | */ 1641 | req.execCb = function (name, callback, args, exports) { 1642 | return callback.apply(exports, args); 1643 | }; 1644 | 1645 | 1646 | /** 1647 | * Adds a node to the DOM. Public function since used by the order plugin. 1648 | * This method should not normally be called by outside code. 1649 | */ 1650 | req.addScriptToDom = function (node) { 1651 | //For some cache cases in IE 6-8, the script executes before the end 1652 | //of the appendChild execution, so to tie an anonymous define 1653 | //call to the module name (which is stored on the node), hold on 1654 | //to a reference to this node, but clear after the DOM insertion. 1655 | currentlyAddingScript = node; 1656 | if (baseElement) { 1657 | head.insertBefore(node, baseElement); 1658 | } else { 1659 | head.appendChild(node); 1660 | } 1661 | currentlyAddingScript = null; 1662 | }; 1663 | 1664 | /** 1665 | * callback for script loads, used to check status of loading. 1666 | * 1667 | * @param {Event} evt the event from the browser for the script 1668 | * that was loaded. 1669 | * 1670 | * @private 1671 | */ 1672 | req.onScriptLoad = function (evt) { 1673 | //Using currentTarget instead of target for Firefox 2.0's sake. Not 1674 | //all old browsers will be supported, but this one was easy enough 1675 | //to support and still makes sense. 1676 | var node = evt.currentTarget || evt.srcElement, contextName, moduleName, 1677 | context; 1678 | 1679 | if (evt.type === "load" || (node && readyRegExp.test(node.readyState))) { 1680 | //Reset interactive script so a script node is not held onto for 1681 | //to long. 1682 | interactiveScript = null; 1683 | 1684 | //Pull out the name of the module and the context. 1685 | contextName = node.getAttribute("data-requirecontext"); 1686 | moduleName = node.getAttribute("data-requiremodule"); 1687 | context = contexts[contextName]; 1688 | 1689 | contexts[contextName].completeLoad(moduleName); 1690 | 1691 | //Clean up script binding. Favor detachEvent because of IE9 1692 | //issue, see attachEvent/addEventListener comment elsewhere 1693 | //in this file. 1694 | if (node.detachEvent && !isOpera) { 1695 | //Probably IE. If not it will throw an error, which will be 1696 | //useful to know. 1697 | node.detachEvent("onreadystatechange", req.onScriptLoad); 1698 | } else { 1699 | node.removeEventListener("load", req.onScriptLoad, false); 1700 | } 1701 | } 1702 | }; 1703 | 1704 | /** 1705 | * Attaches the script represented by the URL to the current 1706 | * environment. Right now only supports browser loading, 1707 | * but can be redefined in other environments to do the right thing. 1708 | * @param {String} url the url of the script to attach. 1709 | * @param {Object} context the context that wants the script. 1710 | * @param {moduleName} the name of the module that is associated with the script. 1711 | * @param {Function} [callback] optional callback, defaults to require.onScriptLoad 1712 | * @param {String} [type] optional type, defaults to text/javascript 1713 | * @param {Function} [fetchOnlyFunction] optional function to indicate the script node 1714 | * should be set up to fetch the script but do not attach it to the DOM 1715 | * so that it can later be attached to execute it. This is a way for the 1716 | * order plugin to support ordered loading in IE. Once the script is fetched, 1717 | * but not executed, the fetchOnlyFunction will be called. 1718 | */ 1719 | req.attach = function (url, context, moduleName, callback, type, fetchOnlyFunction) { 1720 | var node; 1721 | if (isBrowser) { 1722 | //In the browser so use a script tag 1723 | callback = callback || req.onScriptLoad; 1724 | node = context && context.config && context.config.xhtml ? 1725 | document.createElementNS("http://www.w3.org/1999/xhtml", "html:script") : 1726 | document.createElement("script"); 1727 | node.type = type || "text/javascript"; 1728 | node.charset = "utf-8"; 1729 | //Use async so Gecko does not block on executing the script if something 1730 | //like a long-polling comet tag is being run first. Gecko likes 1731 | //to evaluate scripts in DOM order, even for dynamic scripts. 1732 | //It will fetch them async, but only evaluate the contents in DOM 1733 | //order, so a long-polling script tag can delay execution of scripts 1734 | //after it. But telling Gecko we expect async gets us the behavior 1735 | //we want -- execute it whenever it is finished downloading. Only 1736 | //Helps Firefox 3.6+ 1737 | //Allow some URLs to not be fetched async. Mostly helps the order! 1738 | //plugin 1739 | node.async = !s.skipAsync[url]; 1740 | 1741 | if (context) { 1742 | node.setAttribute("data-requirecontext", context.contextName); 1743 | } 1744 | node.setAttribute("data-requiremodule", moduleName); 1745 | 1746 | //Set up load listener. Test attachEvent first because IE9 has 1747 | //a subtle issue in its addEventListener and script onload firings 1748 | //that do not match the behavior of all other browsers with 1749 | //addEventListener support, which fire the onload event for a 1750 | //script right after the script execution. See: 1751 | //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution 1752 | //UNFORTUNATELY Opera implements attachEvent but does not follow the script 1753 | //script execution mode. 1754 | if (node.attachEvent && !isOpera) { 1755 | //Probably IE. IE (at least 6-8) do not fire 1756 | //script onload right after executing the script, so 1757 | //we cannot tie the anonymous define call to a name. 1758 | //However, IE reports the script as being in "interactive" 1759 | //readyState at the time of the define call. 1760 | useInteractive = true; 1761 | 1762 | 1763 | if (fetchOnlyFunction) { 1764 | //Need to use old school onreadystate here since 1765 | //when the event fires and the node is not attached 1766 | //to the DOM, the evt.srcElement is null, so use 1767 | //a closure to remember the node. 1768 | node.onreadystatechange = function (evt) { 1769 | //Script loaded but not executed. 1770 | //Clear loaded handler, set the real one that 1771 | //waits for script execution. 1772 | if (node.readyState === 'loaded') { 1773 | node.onreadystatechange = null; 1774 | node.attachEvent("onreadystatechange", callback); 1775 | fetchOnlyFunction(node); 1776 | } 1777 | }; 1778 | } else { 1779 | node.attachEvent("onreadystatechange", callback); 1780 | } 1781 | } else { 1782 | node.addEventListener("load", callback, false); 1783 | } 1784 | node.src = url; 1785 | 1786 | //Fetch only means waiting to attach to DOM after loaded. 1787 | if (!fetchOnlyFunction) { 1788 | req.addScriptToDom(node); 1789 | } 1790 | 1791 | return node; 1792 | } else if (isWebWorker) { 1793 | //In a web worker, use importScripts. This is not a very 1794 | //efficient use of importScripts, importScripts will block until 1795 | //its script is downloaded and evaluated. However, if web workers 1796 | //are in play, the expectation that a build has been done so that 1797 | //only one script needs to be loaded anyway. This may need to be 1798 | //reevaluated if other use cases become common. 1799 | importScripts(url); 1800 | 1801 | //Account for anonymous modules 1802 | context.completeLoad(moduleName); 1803 | } 1804 | return null; 1805 | }; 1806 | 1807 | //Look for a data-main script attribute, which could also adjust the baseUrl. 1808 | if (isBrowser) { 1809 | //Figure out baseUrl. Get it from the script tag with require.js in it. 1810 | scripts = document.getElementsByTagName("script"); 1811 | 1812 | for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) { 1813 | //Set the "head" where we can append children by 1814 | //using the script's parent. 1815 | if (!head) { 1816 | head = script.parentNode; 1817 | } 1818 | 1819 | //Look for a data-main attribute to set main script for the page 1820 | //to load. If it is there, the path to data main becomes the 1821 | //baseUrl, if it is not already set. 1822 | if ((dataMain = script.getAttribute('data-main'))) { 1823 | if (!cfg.baseUrl) { 1824 | //Pull off the directory of data-main for use as the 1825 | //baseUrl. 1826 | src = dataMain.split('/'); 1827 | mainScript = src.pop(); 1828 | subPath = src.length ? src.join('/') + '/' : './'; 1829 | 1830 | //Set final config. 1831 | cfg.baseUrl = subPath; 1832 | //Strip off any trailing .js since dataMain is now 1833 | //like a module name. 1834 | dataMain = mainScript.replace(jsSuffixRegExp, ''); 1835 | } 1836 | 1837 | //Put the data-main script in the files to load. 1838 | cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain]; 1839 | 1840 | break; 1841 | } 1842 | } 1843 | } 1844 | 1845 | //See if there is nothing waiting across contexts, and if not, trigger 1846 | //resourcesReady. 1847 | req.checkReadyState = function () { 1848 | var contexts = s.contexts, prop; 1849 | for (prop in contexts) { 1850 | if (!(prop in empty)) { 1851 | if (contexts[prop].waitCount) { 1852 | return; 1853 | } 1854 | } 1855 | } 1856 | req.resourcesReady(true); 1857 | }; 1858 | 1859 | /** 1860 | * Internal function that is triggered whenever all scripts/resources 1861 | * have been loaded by the loader. Can be overridden by other, for 1862 | * instance the domReady plugin, which wants to know when all resources 1863 | * are loaded. 1864 | */ 1865 | req.resourcesReady = function (isReady) { 1866 | var contexts, context, prop; 1867 | 1868 | //First, set the public variable indicating that resources are loading. 1869 | req.resourcesDone = isReady; 1870 | 1871 | if (req.resourcesDone) { 1872 | //If jQuery with DOM ready delayed, release it now. 1873 | contexts = s.contexts; 1874 | for (prop in contexts) { 1875 | if (!(prop in empty)) { 1876 | context = contexts[prop]; 1877 | if (context.jQueryIncremented) { 1878 | jQueryHoldReady(context.jQuery, false); 1879 | context.jQueryIncremented = false; 1880 | } 1881 | } 1882 | } 1883 | } 1884 | }; 1885 | 1886 | //FF < 3.6 readyState fix. Needed so that domReady plugin 1887 | //works well in that environment, since require.js is normally 1888 | //loaded via an HTML script tag so it will be there before window load, 1889 | //where the domReady plugin is more likely to be loaded after window load. 1890 | req.pageLoaded = function () { 1891 | if (document.readyState !== "complete") { 1892 | document.readyState = "complete"; 1893 | } 1894 | }; 1895 | if (isBrowser) { 1896 | if (document.addEventListener) { 1897 | if (!document.readyState) { 1898 | document.readyState = "loading"; 1899 | window.addEventListener("load", req.pageLoaded, false); 1900 | } 1901 | } 1902 | } 1903 | 1904 | //Set up default context. If require was a configuration object, use that as base config. 1905 | req(cfg); 1906 | 1907 | //If modules are built into require.js, then need to make sure dependencies are 1908 | //traced. Use a setTimeout in the browser world, to allow all the modules to register 1909 | //themselves. In a non-browser env, assume that modules are not built into require.js, 1910 | //which seems odd to do on the server. 1911 | if (req.isAsync && typeof setTimeout !== "undefined") { 1912 | ctx = s.contexts[(cfg.context || defContextName)]; 1913 | //Indicate that the script that includes require() is still loading, 1914 | //so that require()'d dependencies are not traced until the end of the 1915 | //file is parsed (approximated via the setTimeout call). 1916 | ctx.requireWait = true; 1917 | setTimeout(function () { 1918 | ctx.requireWait = false; 1919 | 1920 | //Any modules included with the require.js file will be in the 1921 | //global queue, assign them to this context. 1922 | ctx.takeGlobalQueue(); 1923 | 1924 | //Allow for jQuery to be loaded/already in the page, and if jQuery 1.4.3, 1925 | //make sure to hold onto it for readyWait triggering. 1926 | ctx.jQueryCheck(); 1927 | 1928 | if (!ctx.scriptCount) { 1929 | ctx.resume(); 1930 | } 1931 | req.checkReadyState(); 1932 | }, 0); 1933 | } 1934 | }()); -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |