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