weekly release 3.1dev
[moodle.git] / lib / requirejs / require.js
CommitLineData
adeb96d2 1/** vim: et:ts=4:sw=4:sts=4
a3620861 2 * @license RequireJS 2.1.20 Copyright (c) 2010-2015, The Dojo Foundation All Rights Reserved.
adeb96d2
DW
3 * Available via the MIT or new BSD license.
4 * see: http://github.com/jrburke/requirejs for details
5 */
6//Not using strict: uneven strict support in browsers, #392, and causes
7//problems with requirejs.exec()/transpiler plugins that may not be strict.
8/*jslint regexp: true, nomen: true, sloppy: true */
9/*global window, navigator, document, importScripts, setTimeout, opera */
10
11var requirejs, require, define;
12(function (global) {
13 var req, s, head, baseElement, dataMain, src,
14 interactiveScript, currentlyAddingScript, mainScript, subPath,
a3620861 15 version = '2.1.20',
adeb96d2
DW
16 commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
17 cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
18 jsSuffixRegExp = /\.js$/,
19 currDirRegExp = /^\.\//,
20 op = Object.prototype,
21 ostring = op.toString,
22 hasOwn = op.hasOwnProperty,
23 ap = Array.prototype,
adeb96d2
DW
24 isBrowser = !!(typeof window !== 'undefined' && typeof navigator !== 'undefined' && window.document),
25 isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
26 //PS3 indicates loaded and complete, but need to wait for complete
27 //specifically. Sequence is 'loading', 'loaded', execution,
28 // then 'complete'. The UA check is unfortunate, but not sure how
29 //to feature test w/o causing perf issues.
30 readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?
31 /^complete$/ : /^(complete|loaded)$/,
32 defContextName = '_',
33 //Oh the tragedy, detecting opera. See the usage of isOpera for reason.
34 isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',
35 contexts = {},
36 cfg = {},
37 globalDefQueue = [],
38 useInteractive = false;
39
40 function isFunction(it) {
41 return ostring.call(it) === '[object Function]';
42 }
43
44 function isArray(it) {
45 return ostring.call(it) === '[object Array]';
46 }
47
48 /**
49 * Helper function for iterating over an array. If the func returns
50 * a true value, it will break out of the loop.
51 */
52 function each(ary, func) {
53 if (ary) {
54 var i;
55 for (i = 0; i < ary.length; i += 1) {
56 if (ary[i] && func(ary[i], i, ary)) {
57 break;
58 }
59 }
60 }
61 }
62
63 /**
64 * Helper function for iterating over an array backwards. If the func
65 * returns a true value, it will break out of the loop.
66 */
67 function eachReverse(ary, func) {
68 if (ary) {
69 var i;
70 for (i = ary.length - 1; i > -1; i -= 1) {
71 if (ary[i] && func(ary[i], i, ary)) {
72 break;
73 }
74 }
75 }
76 }
77
78 function hasProp(obj, prop) {
79 return hasOwn.call(obj, prop);
80 }
81
82 function getOwn(obj, prop) {
83 return hasProp(obj, prop) && obj[prop];
84 }
85
86 /**
87 * Cycles over properties in an object and calls a function for each
88 * property value. If the function returns a truthy value, then the
89 * iteration is stopped.
90 */
91 function eachProp(obj, func) {
92 var prop;
93 for (prop in obj) {
94 if (hasProp(obj, prop)) {
95 if (func(obj[prop], prop)) {
96 break;
97 }
98 }
99 }
100 }
101
102 /**
103 * Simple function to mix in properties from source into target,
104 * but only if target does not already have a property of the same name.
105 */
106 function mixin(target, source, force, deepStringMixin) {
107 if (source) {
108 eachProp(source, function (value, prop) {
109 if (force || !hasProp(target, prop)) {
110 if (deepStringMixin && typeof value === 'object' && value &&
111 !isArray(value) && !isFunction(value) &&
112 !(value instanceof RegExp)) {
113
114 if (!target[prop]) {
115 target[prop] = {};
116 }
117 mixin(target[prop], value, force, deepStringMixin);
118 } else {
119 target[prop] = value;
120 }
121 }
122 });
123 }
124 return target;
125 }
126
127 //Similar to Function.prototype.bind, but the 'this' object is specified
128 //first, since it is easier to read/figure out what 'this' will be.
129 function bind(obj, fn) {
130 return function () {
131 return fn.apply(obj, arguments);
132 };
133 }
134
135 function scripts() {
136 return document.getElementsByTagName('script');
137 }
138
139 function defaultOnError(err) {
140 throw err;
141 }
142
143 //Allow getting a global that is expressed in
144 //dot notation, like 'a.b.c'.
145 function getGlobal(value) {
146 if (!value) {
147 return value;
148 }
149 var g = global;
150 each(value.split('.'), function (part) {
151 g = g[part];
152 });
153 return g;
154 }
155
156 /**
157 * Constructs an error with a pointer to an URL with more information.
158 * @param {String} id the error ID that maps to an ID on a web page.
159 * @param {String} message human readable error.
160 * @param {Error} [err] the original error, if there is one.
161 *
162 * @returns {Error}
163 */
164 function makeError(id, msg, err, requireModules) {
165 var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
166 e.requireType = id;
167 e.requireModules = requireModules;
168 if (err) {
169 e.originalError = err;
170 }
171 return e;
172 }
173
174 if (typeof define !== 'undefined') {
175 //If a define is already in play via another AMD loader,
176 //do not overwrite.
177 return;
178 }
179
180 if (typeof requirejs !== 'undefined') {
181 if (isFunction(requirejs)) {
182 //Do not overwrite an existing requirejs instance.
183 return;
184 }
185 cfg = requirejs;
186 requirejs = undefined;
187 }
188
189 //Allow for a require config object
190 if (typeof require !== 'undefined' && !isFunction(require)) {
191 //assume it is a config object.
192 cfg = require;
193 require = undefined;
194 }
195
196 function newContext(contextName) {
197 var inCheckLoaded, Module, context, handlers,
198 checkLoadedTimeoutId,
199 config = {
200 //Defaults. Do not set a default for map
201 //config to speed up normalize(), which
202 //will run faster if there is no default.
203 waitSeconds: 7,
204 baseUrl: './',
205 paths: {},
206 bundles: {},
207 pkgs: {},
208 shim: {},
209 config: {}
210 },
211 registry = {},
212 //registry of just enabled modules, to speed
213 //cycle breaking code when lots of modules
214 //are registered, but not activated.
215 enabledRegistry = {},
216 undefEvents = {},
217 defQueue = [],
218 defined = {},
219 urlFetched = {},
220 bundlesMap = {},
221 requireCounter = 1,
222 unnormalizedCounter = 1;
223
224 /**
225 * Trims the . and .. from an array of path segments.
226 * It will keep a leading path segment if a .. will become
227 * the first path segment, to help with module name lookups,
228 * which act like paths, but can be remapped. But the end result,
229 * all paths that use this function should look normalized.
230 * NOTE: this method MODIFIES the input array.
231 * @param {Array} ary the array of path segments.
232 */
233 function trimDots(ary) {
234 var i, part;
235 for (i = 0; i < ary.length; i++) {
236 part = ary[i];
237 if (part === '.') {
238 ary.splice(i, 1);
239 i -= 1;
240 } else if (part === '..') {
241 // If at the start, or previous value is still ..,
242 // keep them so that when converted to a path it may
243 // still work when converted to a path, even though
244 // as an ID it is less than ideal. In larger point
245 // releases, may be better to just kick out an error.
a3620861 246 if (i === 0 || (i === 1 && ary[2] === '..') || ary[i - 1] === '..') {
adeb96d2
DW
247 continue;
248 } else if (i > 0) {
249 ary.splice(i - 1, 2);
250 i -= 2;
251 }
252 }
253 }
254 }
255
256 /**
257 * Given a relative module name, like ./something, normalize it to
258 * a real name that can be mapped to a path.
259 * @param {String} name the relative name
260 * @param {String} baseName a real name that the name arg is relative
261 * to.
262 * @param {Boolean} applyMap apply the map config to the value. Should
263 * only be done if this normalization is for a dependency ID.
264 * @returns {String} normalized name
265 */
266 function normalize(name, baseName, applyMap) {
267 var pkgMain, mapValue, nameParts, i, j, nameSegment, lastIndex,
268 foundMap, foundI, foundStarMap, starI, normalizedBaseParts,
269 baseParts = (baseName && baseName.split('/')),
270 map = config.map,
271 starMap = map && map['*'];
272
273 //Adjust any relative paths.
274 if (name) {
275 name = name.split('/');
276 lastIndex = name.length - 1;
277
278 // If wanting node ID compatibility, strip .js from end
279 // of IDs. Have to do this here, and not in nameToUrl
280 // because node allows either .js or non .js to map
281 // to same file.
282 if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
283 name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
284 }
285
286 // Starts with a '.' so need the baseName
287 if (name[0].charAt(0) === '.' && baseParts) {
288 //Convert baseName to array, and lop off the last part,
289 //so that . matches that 'directory' and not name of the baseName's
290 //module. For instance, baseName of 'one/two/three', maps to
291 //'one/two/three.js', but we want the directory, 'one/two' for
292 //this normalization.
293 normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
294 name = normalizedBaseParts.concat(name);
295 }
296
297 trimDots(name);
298 name = name.join('/');
299 }
300
301 //Apply map config if available.
302 if (applyMap && map && (baseParts || starMap)) {
303 nameParts = name.split('/');
304
305 outerLoop: for (i = nameParts.length; i > 0; i -= 1) {
306 nameSegment = nameParts.slice(0, i).join('/');
307
308 if (baseParts) {
309 //Find the longest baseName segment match in the config.
310 //So, do joins on the biggest to smallest lengths of baseParts.
311 for (j = baseParts.length; j > 0; j -= 1) {
312 mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
313
314 //baseName segment has config, find if it has one for
315 //this name.
316 if (mapValue) {
317 mapValue = getOwn(mapValue, nameSegment);
318 if (mapValue) {
319 //Match, update name to the new value.
320 foundMap = mapValue;
321 foundI = i;
322 break outerLoop;
323 }
324 }
325 }
326 }
327
328 //Check for a star map match, but just hold on to it,
329 //if there is a shorter segment match later in a matching
330 //config, then favor over this star map.
331 if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
332 foundStarMap = getOwn(starMap, nameSegment);
333 starI = i;
334 }
335 }
336
337 if (!foundMap && foundStarMap) {
338 foundMap = foundStarMap;
339 foundI = starI;
340 }
341
342 if (foundMap) {
343 nameParts.splice(0, foundI, foundMap);
344 name = nameParts.join('/');
345 }
346 }
347
348 // If the name points to a package's name, use
349 // the package main instead.
350 pkgMain = getOwn(config.pkgs, name);
351
352 return pkgMain ? pkgMain : name;
353 }
354
355 function removeScript(name) {
356 if (isBrowser) {
357 each(scripts(), function (scriptNode) {
358 if (scriptNode.getAttribute('data-requiremodule') === name &&
359 scriptNode.getAttribute('data-requirecontext') === context.contextName) {
360 scriptNode.parentNode.removeChild(scriptNode);
361 return true;
362 }
363 });
364 }
365 }
366
367 function hasPathFallback(id) {
368 var pathConfig = getOwn(config.paths, id);
369 if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
370 //Pop off the first array value, since it failed, and
371 //retry
372 pathConfig.shift();
373 context.require.undef(id);
374
375 //Custom require that does not do map translation, since
376 //ID is "absolute", already mapped/resolved.
377 context.makeRequire(null, {
378 skipMap: true
379 })([id]);
380
381 return true;
382 }
383 }
384
385 //Turns a plugin!resource to [plugin, resource]
386 //with the plugin being undefined if the name
387 //did not have a plugin prefix.
388 function splitPrefix(name) {
389 var prefix,
390 index = name ? name.indexOf('!') : -1;
391 if (index > -1) {
392 prefix = name.substring(0, index);
393 name = name.substring(index + 1, name.length);
394 }
395 return [prefix, name];
396 }
397
398 /**
399 * Creates a module mapping that includes plugin prefix, module
400 * name, and path. If parentModuleMap is provided it will
401 * also normalize the name via require.normalize()
402 *
403 * @param {String} name the module name
404 * @param {String} [parentModuleMap] parent module map
405 * for the module name, used to resolve relative names.
406 * @param {Boolean} isNormalized: is the ID already normalized.
407 * This is true if this call is done for a define() module ID.
408 * @param {Boolean} applyMap: apply the map config to the ID.
409 * Should only be true if this map is for a dependency.
410 *
411 * @returns {Object}
412 */
413 function makeModuleMap(name, parentModuleMap, isNormalized, applyMap) {
414 var url, pluginModule, suffix, nameParts,
415 prefix = null,
416 parentName = parentModuleMap ? parentModuleMap.name : null,
417 originalName = name,
418 isDefine = true,
419 normalizedName = '';
420
421 //If no name, then it means it is a require call, generate an
422 //internal name.
423 if (!name) {
424 isDefine = false;
425 name = '_@r' + (requireCounter += 1);
426 }
427
428 nameParts = splitPrefix(name);
429 prefix = nameParts[0];
430 name = nameParts[1];
431
432 if (prefix) {
433 prefix = normalize(prefix, parentName, applyMap);
434 pluginModule = getOwn(defined, prefix);
435 }
436
437 //Account for relative paths if there is a base name.
438 if (name) {
439 if (prefix) {
440 if (pluginModule && pluginModule.normalize) {
441 //Plugin is loaded, use its normalize method.
442 normalizedName = pluginModule.normalize(name, function (name) {
443 return normalize(name, parentName, applyMap);
444 });
445 } else {
446 // If nested plugin references, then do not try to
447 // normalize, as it will not normalize correctly. This
448 // places a restriction on resourceIds, and the longer
449 // term solution is not to normalize until plugins are
450 // loaded and all normalizations to allow for async
451 // loading of a loader plugin. But for now, fixes the
452 // common uses. Details in #1131
453 normalizedName = name.indexOf('!') === -1 ?
454 normalize(name, parentName, applyMap) :
455 name;
456 }
457 } else {
458 //A regular module.
459 normalizedName = normalize(name, parentName, applyMap);
460
461 //Normalized name may be a plugin ID due to map config
462 //application in normalize. The map config values must
463 //already be normalized, so do not need to redo that part.
464 nameParts = splitPrefix(normalizedName);
465 prefix = nameParts[0];
466 normalizedName = nameParts[1];
467 isNormalized = true;
468
469 url = context.nameToUrl(normalizedName);
470 }
471 }
472
473 //If the id is a plugin id that cannot be determined if it needs
474 //normalization, stamp it with a unique ID so two matching relative
475 //ids that may conflict can be separate.
476 suffix = prefix && !pluginModule && !isNormalized ?
477 '_unnormalized' + (unnormalizedCounter += 1) :
478 '';
479
480 return {
481 prefix: prefix,
482 name: normalizedName,
483 parentMap: parentModuleMap,
484 unnormalized: !!suffix,
485 url: url,
486 originalName: originalName,
487 isDefine: isDefine,
488 id: (prefix ?
489 prefix + '!' + normalizedName :
490 normalizedName) + suffix
491 };
492 }
493
494 function getModule(depMap) {
495 var id = depMap.id,
496 mod = getOwn(registry, id);
497
498 if (!mod) {
499 mod = registry[id] = new context.Module(depMap);
500 }
501
502 return mod;
503 }
504
505 function on(depMap, name, fn) {
506 var id = depMap.id,
507 mod = getOwn(registry, id);
508
509 if (hasProp(defined, id) &&
510 (!mod || mod.defineEmitComplete)) {
511 if (name === 'defined') {
512 fn(defined[id]);
513 }
514 } else {
515 mod = getModule(depMap);
516 if (mod.error && name === 'error') {
517 fn(mod.error);
518 } else {
519 mod.on(name, fn);
520 }
521 }
522 }
523
524 function onError(err, errback) {
525 var ids = err.requireModules,
526 notified = false;
527
528 if (errback) {
529 errback(err);
530 } else {
531 each(ids, function (id) {
532 var mod = getOwn(registry, id);
533 if (mod) {
534 //Set error on module, so it skips timeout checks.
535 mod.error = err;
536 if (mod.events.error) {
537 notified = true;
538 mod.emit('error', err);
539 }
540 }
541 });
542
543 if (!notified) {
544 req.onError(err);
545 }
546 }
547 }
548
549 /**
550 * Internal method to transfer globalQueue items to this context's
551 * defQueue.
552 */
553 function takeGlobalQueue() {
554 //Push all the globalDefQueue items into the context's defQueue
555 if (globalDefQueue.length) {
a3620861
DW
556 each(globalDefQueue, function(queueItem) {
557 var id = queueItem[0];
558 if (typeof id === 'string') {
559 context.defQueueMap[id] = true;
560 }
561 defQueue.push(queueItem);
562 });
adeb96d2
DW
563 globalDefQueue = [];
564 }
565 }
566
567 handlers = {
568 'require': function (mod) {
569 if (mod.require) {
570 return mod.require;
571 } else {
572 return (mod.require = context.makeRequire(mod.map));
573 }
574 },
575 'exports': function (mod) {
576 mod.usingExports = true;
577 if (mod.map.isDefine) {
578 if (mod.exports) {
579 return (defined[mod.map.id] = mod.exports);
580 } else {
581 return (mod.exports = defined[mod.map.id] = {});
582 }
583 }
584 },
585 'module': function (mod) {
586 if (mod.module) {
587 return mod.module;
588 } else {
589 return (mod.module = {
590 id: mod.map.id,
591 uri: mod.map.url,
592 config: function () {
a3620861 593 return getOwn(config.config, mod.map.id) || {};
adeb96d2
DW
594 },
595 exports: mod.exports || (mod.exports = {})
596 });
597 }
598 }
599 };
600
601 function cleanRegistry(id) {
602 //Clean up machinery used for waiting modules.
603 delete registry[id];
604 delete enabledRegistry[id];
605 }
606
607 function breakCycle(mod, traced, processed) {
608 var id = mod.map.id;
609
610 if (mod.error) {
611 mod.emit('error', mod.error);
612 } else {
613 traced[id] = true;
614 each(mod.depMaps, function (depMap, i) {
615 var depId = depMap.id,
616 dep = getOwn(registry, depId);
617
618 //Only force things that have not completed
619 //being defined, so still in the registry,
620 //and only if it has not been matched up
621 //in the module already.
622 if (dep && !mod.depMatched[i] && !processed[depId]) {
623 if (getOwn(traced, depId)) {
624 mod.defineDep(i, defined[depId]);
625 mod.check(); //pass false?
626 } else {
627 breakCycle(dep, traced, processed);
628 }
629 }
630 });
631 processed[id] = true;
632 }
633 }
634
635 function checkLoaded() {
636 var err, usingPathFallback,
637 waitInterval = config.waitSeconds * 1000,
638 //It is possible to disable the wait interval by using waitSeconds of 0.
639 expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),
640 noLoads = [],
641 reqCalls = [],
642 stillLoading = false,
643 needCycleCheck = true;
644
645 //Do not bother if this call was a result of a cycle break.
646 if (inCheckLoaded) {
647 return;
648 }
649
650 inCheckLoaded = true;
651
652 //Figure out the state of all the modules.
653 eachProp(enabledRegistry, function (mod) {
654 var map = mod.map,
655 modId = map.id;
656
657 //Skip things that are not enabled or in error state.
658 if (!mod.enabled) {
659 return;
660 }
661
662 if (!map.isDefine) {
663 reqCalls.push(mod);
664 }
665
666 if (!mod.error) {
667 //If the module should be executed, and it has not
668 //been inited and time is up, remember it.
669 if (!mod.inited && expired) {
670 if (hasPathFallback(modId)) {
671 usingPathFallback = true;
672 stillLoading = true;
673 } else {
674 noLoads.push(modId);
675 removeScript(modId);
676 }
677 } else if (!mod.inited && mod.fetched && map.isDefine) {
678 stillLoading = true;
679 if (!map.prefix) {
680 //No reason to keep looking for unfinished
681 //loading. If the only stillLoading is a
682 //plugin resource though, keep going,
683 //because it may be that a plugin resource
684 //is waiting on a non-plugin cycle.
685 return (needCycleCheck = false);
686 }
687 }
688 }
689 });
690
691 if (expired && noLoads.length) {
692 //If wait time expired, throw error of unloaded modules.
693 err = makeError('timeout', 'Load timeout for modules: ' + noLoads, null, noLoads);
694 err.contextName = context.contextName;
695 return onError(err);
696 }
697
698 //Not expired, check for a cycle.
699 if (needCycleCheck) {
700 each(reqCalls, function (mod) {
701 breakCycle(mod, {}, {});
702 });
703 }
704
705 //If still waiting on loads, and the waiting load is something
706 //other than a plugin resource, or there are still outstanding
707 //scripts, then just try back later.
708 if ((!expired || usingPathFallback) && stillLoading) {
709 //Something is still waiting to load. Wait for it, but only
710 //if a timeout is not already in effect.
711 if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {
712 checkLoadedTimeoutId = setTimeout(function () {
713 checkLoadedTimeoutId = 0;
714 checkLoaded();
715 }, 50);
716 }
717 }
718
719 inCheckLoaded = false;
720 }
721
722 Module = function (map) {
723 this.events = getOwn(undefEvents, map.id) || {};
724 this.map = map;
725 this.shim = getOwn(config.shim, map.id);
726 this.depExports = [];
727 this.depMaps = [];
728 this.depMatched = [];
729 this.pluginMaps = {};
730 this.depCount = 0;
731
732 /* this.exports this.factory
733 this.depMaps = [],
734 this.enabled, this.fetched
735 */
736 };
737
738 Module.prototype = {
739 init: function (depMaps, factory, errback, options) {
740 options = options || {};
741
742 //Do not do more inits if already done. Can happen if there
743 //are multiple define calls for the same module. That is not
744 //a normal, common case, but it is also not unexpected.
745 if (this.inited) {
746 return;
747 }
748
749 this.factory = factory;
750
751 if (errback) {
752 //Register for errors on this module.
753 this.on('error', errback);
754 } else if (this.events.error) {
755 //If no errback already, but there are error listeners
756 //on this module, set up an errback to pass to the deps.
757 errback = bind(this, function (err) {
758 this.emit('error', err);
759 });
760 }
761
762 //Do a copy of the dependency array, so that
763 //source inputs are not modified. For example
764 //"shim" deps are passed in here directly, and
765 //doing a direct modification of the depMaps array
766 //would affect that config.
767 this.depMaps = depMaps && depMaps.slice(0);
768
769 this.errback = errback;
770
771 //Indicate this module has be initialized
772 this.inited = true;
773
774 this.ignore = options.ignore;
775
776 //Could have option to init this module in enabled mode,
777 //or could have been previously marked as enabled. However,
778 //the dependencies are not known until init is called. So
779 //if enabled previously, now trigger dependencies as enabled.
780 if (options.enabled || this.enabled) {
781 //Enable this module and dependencies.
782 //Will call this.check()
783 this.enable();
784 } else {
785 this.check();
786 }
787 },
788
789 defineDep: function (i, depExports) {
790 //Because of cycles, defined callback for a given
791 //export can be called more than once.
792 if (!this.depMatched[i]) {
793 this.depMatched[i] = true;
794 this.depCount -= 1;
795 this.depExports[i] = depExports;
796 }
797 },
798
799 fetch: function () {
800 if (this.fetched) {
801 return;
802 }
803 this.fetched = true;
804
805 context.startTime = (new Date()).getTime();
806
807 var map = this.map;
808
809 //If the manager is for a plugin managed resource,
810 //ask the plugin to load it now.
811 if (this.shim) {
812 context.makeRequire(this.map, {
813 enableBuildCallback: true
814 })(this.shim.deps || [], bind(this, function () {
815 return map.prefix ? this.callPlugin() : this.load();
816 }));
817 } else {
818 //Regular dependency.
819 return map.prefix ? this.callPlugin() : this.load();
820 }
821 },
822
823 load: function () {
824 var url = this.map.url;
825
826 //Regular dependency.
827 if (!urlFetched[url]) {
828 urlFetched[url] = true;
829 context.load(this.map.id, url);
830 }
831 },
832
833 /**
834 * Checks if the module is ready to define itself, and if so,
835 * define it.
836 */
837 check: function () {
838 if (!this.enabled || this.enabling) {
839 return;
840 }
841
842 var err, cjsModule,
843 id = this.map.id,
844 depExports = this.depExports,
845 exports = this.exports,
846 factory = this.factory;
847
848 if (!this.inited) {
a3620861
DW
849 // Only fetch if not already in the defQueue.
850 if (!hasProp(context.defQueueMap, id)) {
851 this.fetch();
852 }
adeb96d2
DW
853 } else if (this.error) {
854 this.emit('error', this.error);
855 } else if (!this.defining) {
856 //The factory could trigger another require call
857 //that would result in checking this module to
858 //define itself again. If already in the process
859 //of doing that, skip this work.
860 this.defining = true;
861
862 if (this.depCount < 1 && !this.defined) {
863 if (isFunction(factory)) {
864 //If there is an error listener, favor passing
865 //to that instead of throwing an error. However,
866 //only do it for define()'d modules. require
867 //errbacks should not be called for failures in
868 //their callbacks (#699). However if a global
869 //onError is set, use that.
870 if ((this.events.error && this.map.isDefine) ||
871 req.onError !== defaultOnError) {
872 try {
873 exports = context.execCb(id, factory, depExports, exports);
874 } catch (e) {
875 err = e;
876 }
877 } else {
878 exports = context.execCb(id, factory, depExports, exports);
879 }
880
881 // Favor return value over exports. If node/cjs in play,
882 // then will not have a return value anyway. Favor
883 // module.exports assignment over exports object.
884 if (this.map.isDefine && exports === undefined) {
885 cjsModule = this.module;
886 if (cjsModule) {
887 exports = cjsModule.exports;
888 } else if (this.usingExports) {
889 //exports already set the defined value.
890 exports = this.exports;
891 }
892 }
893
894 if (err) {
895 err.requireMap = this.map;
896 err.requireModules = this.map.isDefine ? [this.map.id] : null;
897 err.requireType = this.map.isDefine ? 'define' : 'require';
898 return onError((this.error = err));
899 }
900
901 } else {
902 //Just a literal value
903 exports = factory;
904 }
905
906 this.exports = exports;
907
908 if (this.map.isDefine && !this.ignore) {
909 defined[id] = exports;
910
911 if (req.onResourceLoad) {
912 req.onResourceLoad(context, this.map, this.depMaps);
913 }
914 }
915
916 //Clean up
917 cleanRegistry(id);
918
919 this.defined = true;
920 }
921
922 //Finished the define stage. Allow calling check again
923 //to allow define notifications below in the case of a
924 //cycle.
925 this.defining = false;
926
927 if (this.defined && !this.defineEmitted) {
928 this.defineEmitted = true;
929 this.emit('defined', this.exports);
930 this.defineEmitComplete = true;
931 }
932
933 }
934 },
935
936 callPlugin: function () {
937 var map = this.map,
938 id = map.id,
939 //Map already normalized the prefix.
940 pluginMap = makeModuleMap(map.prefix);
941
942 //Mark this as a dependency for this plugin, so it
943 //can be traced for cycles.
944 this.depMaps.push(pluginMap);
945
946 on(pluginMap, 'defined', bind(this, function (plugin) {
947 var load, normalizedMap, normalizedMod,
948 bundleId = getOwn(bundlesMap, this.map.id),
949 name = this.map.name,
950 parentName = this.map.parentMap ? this.map.parentMap.name : null,
951 localRequire = context.makeRequire(map.parentMap, {
952 enableBuildCallback: true
953 });
954
955 //If current map is not normalized, wait for that
956 //normalized name to load instead of continuing.
957 if (this.map.unnormalized) {
958 //Normalize the ID if the plugin allows it.
959 if (plugin.normalize) {
960 name = plugin.normalize(name, function (name) {
961 return normalize(name, parentName, true);
962 }) || '';
963 }
964
965 //prefix and name should already be normalized, no need
966 //for applying map config again either.
967 normalizedMap = makeModuleMap(map.prefix + '!' + name,
968 this.map.parentMap);
969 on(normalizedMap,
970 'defined', bind(this, function (value) {
971 this.init([], function () { return value; }, null, {
972 enabled: true,
973 ignore: true
974 });
975 }));
976
977 normalizedMod = getOwn(registry, normalizedMap.id);
978 if (normalizedMod) {
979 //Mark this as a dependency for this plugin, so it
980 //can be traced for cycles.
981 this.depMaps.push(normalizedMap);
982
983 if (this.events.error) {
984 normalizedMod.on('error', bind(this, function (err) {
985 this.emit('error', err);
986 }));
987 }
988 normalizedMod.enable();
989 }
990
991 return;
992 }
993
994 //If a paths config, then just load that file instead to
995 //resolve the plugin, as it is built into that paths layer.
996 if (bundleId) {
997 this.map.url = context.nameToUrl(bundleId);
998 this.load();
999 return;
1000 }
1001
1002 load = bind(this, function (value) {
1003 this.init([], function () { return value; }, null, {
1004 enabled: true
1005 });
1006 });
1007
1008 load.error = bind(this, function (err) {
1009 this.inited = true;
1010 this.error = err;
1011 err.requireModules = [id];
1012
1013 //Remove temp unnormalized modules for this module,
1014 //since they will never be resolved otherwise now.
1015 eachProp(registry, function (mod) {
1016 if (mod.map.id.indexOf(id + '_unnormalized') === 0) {
1017 cleanRegistry(mod.map.id);
1018 }
1019 });
1020
1021 onError(err);
1022 });
1023
1024 //Allow plugins to load other code without having to know the
1025 //context or how to 'complete' the load.
1026 load.fromText = bind(this, function (text, textAlt) {
1027 /*jslint evil: true */
1028 var moduleName = map.name,
1029 moduleMap = makeModuleMap(moduleName),
1030 hasInteractive = useInteractive;
1031
1032 //As of 2.1.0, support just passing the text, to reinforce
1033 //fromText only being called once per resource. Still
1034 //support old style of passing moduleName but discard
1035 //that moduleName in favor of the internal ref.
1036 if (textAlt) {
1037 text = textAlt;
1038 }
1039
1040 //Turn off interactive script matching for IE for any define
1041 //calls in the text, then turn it back on at the end.
1042 if (hasInteractive) {
1043 useInteractive = false;
1044 }
1045
1046 //Prime the system by creating a module instance for
1047 //it.
1048 getModule(moduleMap);
1049
1050 //Transfer any config to this other module.
1051 if (hasProp(config.config, id)) {
1052 config.config[moduleName] = config.config[id];
1053 }
1054
1055 try {
1056 req.exec(text);
1057 } catch (e) {
1058 return onError(makeError('fromtexteval',
1059 'fromText eval for ' + id +
1060 ' failed: ' + e,
1061 e,
1062 [id]));
1063 }
1064
1065 if (hasInteractive) {
1066 useInteractive = true;
1067 }
1068
1069 //Mark this as a dependency for the plugin
1070 //resource
1071 this.depMaps.push(moduleMap);
1072
1073 //Support anonymous modules.
1074 context.completeLoad(moduleName);
1075
1076 //Bind the value of that module to the value for this
1077 //resource ID.
1078 localRequire([moduleName], load);
1079 });
1080
1081 //Use parentName here since the plugin's name is not reliable,
1082 //could be some weird string with no path that actually wants to
1083 //reference the parentName's path.
1084 plugin.load(map.name, localRequire, load, config);
1085 }));
1086
1087 context.enable(pluginMap, this);
1088 this.pluginMaps[pluginMap.id] = pluginMap;
1089 },
1090
1091 enable: function () {
1092 enabledRegistry[this.map.id] = this;
1093 this.enabled = true;
1094
1095 //Set flag mentioning that the module is enabling,
1096 //so that immediate calls to the defined callbacks
1097 //for dependencies do not trigger inadvertent load
1098 //with the depCount still being zero.
1099 this.enabling = true;
1100
1101 //Enable each dependency
1102 each(this.depMaps, bind(this, function (depMap, i) {
1103 var id, mod, handler;
1104
1105 if (typeof depMap === 'string') {
1106 //Dependency needs to be converted to a depMap
1107 //and wired up to this module.
1108 depMap = makeModuleMap(depMap,
1109 (this.map.isDefine ? this.map : this.map.parentMap),
1110 false,
1111 !this.skipMap);
1112 this.depMaps[i] = depMap;
1113
1114 handler = getOwn(handlers, depMap.id);
1115
1116 if (handler) {
1117 this.depExports[i] = handler(this);
1118 return;
1119 }
1120
1121 this.depCount += 1;
1122
1123 on(depMap, 'defined', bind(this, function (depExports) {
a3620861
DW
1124 if (this.undefed) {
1125 return;
1126 }
adeb96d2
DW
1127 this.defineDep(i, depExports);
1128 this.check();
1129 }));
1130
1131 if (this.errback) {
1132 on(depMap, 'error', bind(this, this.errback));
a3620861
DW
1133 } else if (this.events.error) {
1134 // No direct errback on this module, but something
1135 // else is listening for errors, so be sure to
1136 // propagate the error correctly.
1137 on(depMap, 'error', bind(this, function(err) {
1138 this.emit('error', err);
1139 }));
adeb96d2
DW
1140 }
1141 }
1142
1143 id = depMap.id;
1144 mod = registry[id];
1145
1146 //Skip special modules like 'require', 'exports', 'module'
1147 //Also, don't call enable if it is already enabled,
1148 //important in circular dependency cases.
1149 if (!hasProp(handlers, id) && mod && !mod.enabled) {
1150 context.enable(depMap, this);
1151 }
1152 }));
1153
1154 //Enable each plugin that is used in
1155 //a dependency
1156 eachProp(this.pluginMaps, bind(this, function (pluginMap) {
1157 var mod = getOwn(registry, pluginMap.id);
1158 if (mod && !mod.enabled) {
1159 context.enable(pluginMap, this);
1160 }
1161 }));
1162
1163 this.enabling = false;
1164
1165 this.check();
1166 },
1167
1168 on: function (name, cb) {
1169 var cbs = this.events[name];
1170 if (!cbs) {
1171 cbs = this.events[name] = [];
1172 }
1173 cbs.push(cb);
1174 },
1175
1176 emit: function (name, evt) {
1177 each(this.events[name], function (cb) {
1178 cb(evt);
1179 });
1180 if (name === 'error') {
1181 //Now that the error handler was triggered, remove
1182 //the listeners, since this broken Module instance
1183 //can stay around for a while in the registry.
1184 delete this.events[name];
1185 }
1186 }
1187 };
1188
1189 function callGetModule(args) {
1190 //Skip modules already defined.
1191 if (!hasProp(defined, args[0])) {
1192 getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
1193 }
1194 }
1195
1196 function removeListener(node, func, name, ieName) {
1197 //Favor detachEvent because of IE9
1198 //issue, see attachEvent/addEventListener comment elsewhere
1199 //in this file.
1200 if (node.detachEvent && !isOpera) {
1201 //Probably IE. If not it will throw an error, which will be
1202 //useful to know.
1203 if (ieName) {
1204 node.detachEvent(ieName, func);
1205 }
1206 } else {
1207 node.removeEventListener(name, func, false);
1208 }
1209 }
1210
1211 /**
1212 * Given an event from a script node, get the requirejs info from it,
1213 * and then removes the event listeners on the node.
1214 * @param {Event} evt
1215 * @returns {Object}
1216 */
1217 function getScriptData(evt) {
1218 //Using currentTarget instead of target for Firefox 2.0's sake. Not
1219 //all old browsers will be supported, but this one was easy enough
1220 //to support and still makes sense.
1221 var node = evt.currentTarget || evt.srcElement;
1222
1223 //Remove the listeners once here.
1224 removeListener(node, context.onScriptLoad, 'load', 'onreadystatechange');
1225 removeListener(node, context.onScriptError, 'error');
1226
1227 return {
1228 node: node,
1229 id: node && node.getAttribute('data-requiremodule')
1230 };
1231 }
1232
1233 function intakeDefines() {
1234 var args;
1235
1236 //Any defined modules in the global queue, intake them now.
1237 takeGlobalQueue();
1238
1239 //Make sure any remaining defQueue items get properly processed.
1240 while (defQueue.length) {
1241 args = defQueue.shift();
1242 if (args[0] === null) {
a3620861
DW
1243 return onError(makeError('mismatch', 'Mismatched anonymous define() module: ' +
1244 args[args.length - 1]));
adeb96d2
DW
1245 } else {
1246 //args are id, deps, factory. Should be normalized by the
1247 //define() function.
1248 callGetModule(args);
1249 }
1250 }
a3620861 1251 context.defQueueMap = {};
adeb96d2
DW
1252 }
1253
1254 context = {
1255 config: config,
1256 contextName: contextName,
1257 registry: registry,
1258 defined: defined,
1259 urlFetched: urlFetched,
1260 defQueue: defQueue,
a3620861 1261 defQueueMap: {},
adeb96d2
DW
1262 Module: Module,
1263 makeModuleMap: makeModuleMap,
1264 nextTick: req.nextTick,
1265 onError: onError,
1266
1267 /**
1268 * Set a configuration for the context.
1269 * @param {Object} cfg config object to integrate.
1270 */
1271 configure: function (cfg) {
1272 //Make sure the baseUrl ends in a slash.
1273 if (cfg.baseUrl) {
1274 if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== '/') {
1275 cfg.baseUrl += '/';
1276 }
1277 }
1278
1279 //Save off the paths since they require special processing,
1280 //they are additive.
1281 var shim = config.shim,
1282 objs = {
1283 paths: true,
1284 bundles: true,
1285 config: true,
1286 map: true
1287 };
1288
1289 eachProp(cfg, function (value, prop) {
1290 if (objs[prop]) {
1291 if (!config[prop]) {
1292 config[prop] = {};
1293 }
1294 mixin(config[prop], value, true, true);
1295 } else {
1296 config[prop] = value;
1297 }
1298 });
1299
1300 //Reverse map the bundles
1301 if (cfg.bundles) {
1302 eachProp(cfg.bundles, function (value, prop) {
1303 each(value, function (v) {
1304 if (v !== prop) {
1305 bundlesMap[v] = prop;
1306 }
1307 });
1308 });
1309 }
1310
1311 //Merge shim
1312 if (cfg.shim) {
1313 eachProp(cfg.shim, function (value, id) {
1314 //Normalize the structure
1315 if (isArray(value)) {
1316 value = {
1317 deps: value
1318 };
1319 }
1320 if ((value.exports || value.init) && !value.exportsFn) {
1321 value.exportsFn = context.makeShimExports(value);
1322 }
1323 shim[id] = value;
1324 });
1325 config.shim = shim;
1326 }
1327
1328 //Adjust packages if necessary.
1329 if (cfg.packages) {
1330 each(cfg.packages, function (pkgObj) {
1331 var location, name;
1332
a3620861 1333 pkgObj = typeof pkgObj === 'string' ? {name: pkgObj} : pkgObj;
adeb96d2
DW
1334
1335 name = pkgObj.name;
1336 location = pkgObj.location;
1337 if (location) {
1338 config.paths[name] = pkgObj.location;
1339 }
1340
1341 //Save pointer to main module ID for pkg name.
1342 //Remove leading dot in main, so main paths are normalized,
1343 //and remove any trailing .js, since different package
1344 //envs have different conventions: some use a module name,
1345 //some use a file name.
1346 config.pkgs[name] = pkgObj.name + '/' + (pkgObj.main || 'main')
1347 .replace(currDirRegExp, '')
1348 .replace(jsSuffixRegExp, '');
1349 });
1350 }
1351
1352 //If there are any "waiting to execute" modules in the registry,
1353 //update the maps for them, since their info, like URLs to load,
1354 //may have changed.
1355 eachProp(registry, function (mod, id) {
1356 //If module already has init called, since it is too
1357 //late to modify them, and ignore unnormalized ones
1358 //since they are transient.
1359 if (!mod.inited && !mod.map.unnormalized) {
a3620861 1360 mod.map = makeModuleMap(id, null, true);
adeb96d2
DW
1361 }
1362 });
1363
1364 //If a deps array or a config callback is specified, then call
1365 //require with those args. This is useful when require is defined as a
1366 //config object before require.js is loaded.
1367 if (cfg.deps || cfg.callback) {
1368 context.require(cfg.deps || [], cfg.callback);
1369 }
1370 },
1371
1372 makeShimExports: function (value) {
1373 function fn() {
1374 var ret;
1375 if (value.init) {
1376 ret = value.init.apply(global, arguments);
1377 }
1378 return ret || (value.exports && getGlobal(value.exports));
1379 }
1380 return fn;
1381 },
1382
1383 makeRequire: function (relMap, options) {
1384 options = options || {};
1385
1386 function localRequire(deps, callback, errback) {
1387 var id, map, requireMod;
1388
1389 if (options.enableBuildCallback && callback && isFunction(callback)) {
1390 callback.__requireJsBuild = true;
1391 }
1392
1393 if (typeof deps === 'string') {
1394 if (isFunction(callback)) {
1395 //Invalid call
1396 return onError(makeError('requireargs', 'Invalid require call'), errback);
1397 }
1398
1399 //If require|exports|module are requested, get the
1400 //value for them from the special handlers. Caveat:
1401 //this only works while module is being defined.
1402 if (relMap && hasProp(handlers, deps)) {
1403 return handlers[deps](registry[relMap.id]);
1404 }
1405
1406 //Synchronous access to one module. If require.get is
1407 //available (as in the Node adapter), prefer that.
1408 if (req.get) {
1409 return req.get(context, deps, relMap, localRequire);
1410 }
1411
1412 //Normalize module name, if it contains . or ..
1413 map = makeModuleMap(deps, relMap, false, true);
1414 id = map.id;
1415
1416 if (!hasProp(defined, id)) {
1417 return onError(makeError('notloaded', 'Module name "' +
1418 id +
1419 '" has not been loaded yet for context: ' +
1420 contextName +
1421 (relMap ? '' : '. Use require([])')));
1422 }
1423 return defined[id];
1424 }
1425
1426 //Grab defines waiting in the global queue.
1427 intakeDefines();
1428
1429 //Mark all the dependencies as needing to be loaded.
1430 context.nextTick(function () {
1431 //Some defines could have been added since the
1432 //require call, collect them.
1433 intakeDefines();
1434
1435 requireMod = getModule(makeModuleMap(null, relMap));
1436
1437 //Store if map config should be applied to this require
1438 //call for dependencies.
1439 requireMod.skipMap = options.skipMap;
1440
1441 requireMod.init(deps, callback, errback, {
1442 enabled: true
1443 });
1444
1445 checkLoaded();
1446 });
1447
1448 return localRequire;
1449 }
1450
1451 mixin(localRequire, {
1452 isBrowser: isBrowser,
1453
1454 /**
1455 * Converts a module name + .extension into an URL path.
1456 * *Requires* the use of a module name. It does not support using
1457 * plain URLs like nameToUrl.
1458 */
1459 toUrl: function (moduleNamePlusExt) {
1460 var ext,
1461 index = moduleNamePlusExt.lastIndexOf('.'),
1462 segment = moduleNamePlusExt.split('/')[0],
1463 isRelative = segment === '.' || segment === '..';
1464
1465 //Have a file extension alias, and it is not the
1466 //dots from a relative path.
1467 if (index !== -1 && (!isRelative || index > 1)) {
1468 ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
1469 moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
1470 }
1471
1472 return context.nameToUrl(normalize(moduleNamePlusExt,
1473 relMap && relMap.id, true), ext, true);
1474 },
1475
1476 defined: function (id) {
1477 return hasProp(defined, makeModuleMap(id, relMap, false, true).id);
1478 },
1479
1480 specified: function (id) {
1481 id = makeModuleMap(id, relMap, false, true).id;
1482 return hasProp(defined, id) || hasProp(registry, id);
1483 }
1484 });
1485
1486 //Only allow undef on top level require calls
1487 if (!relMap) {
1488 localRequire.undef = function (id) {
1489 //Bind any waiting define() calls to this context,
1490 //fix for #408
1491 takeGlobalQueue();
1492
1493 var map = makeModuleMap(id, relMap, true),
1494 mod = getOwn(registry, id);
1495
a3620861 1496 mod.undefed = true;
adeb96d2
DW
1497 removeScript(id);
1498
1499 delete defined[id];
1500 delete urlFetched[map.url];
1501 delete undefEvents[id];
1502
1503 //Clean queued defines too. Go backwards
1504 //in array so that the splices do not
1505 //mess up the iteration.
1506 eachReverse(defQueue, function(args, i) {
a3620861 1507 if (args[0] === id) {
adeb96d2
DW
1508 defQueue.splice(i, 1);
1509 }
1510 });
a3620861 1511 delete context.defQueueMap[id];
adeb96d2
DW
1512
1513 if (mod) {
1514 //Hold on to listeners in case the
1515 //module will be attempted to be reloaded
1516 //using a different config.
1517 if (mod.events.defined) {
1518 undefEvents[id] = mod.events;
1519 }
1520
1521 cleanRegistry(id);
1522 }
1523 };
1524 }
1525
1526 return localRequire;
1527 },
1528
1529 /**
1530 * Called to enable a module if it is still in the registry
1531 * awaiting enablement. A second arg, parent, the parent module,
1532 * is passed in for context, when this method is overridden by
1533 * the optimizer. Not shown here to keep code compact.
1534 */
1535 enable: function (depMap) {
1536 var mod = getOwn(registry, depMap.id);
1537 if (mod) {
1538 getModule(depMap).enable();
1539 }
1540 },
1541
1542 /**
1543 * Internal method used by environment adapters to complete a load event.
1544 * A load event could be a script load or just a load pass from a synchronous
1545 * load call.
1546 * @param {String} moduleName the name of the module to potentially complete.
1547 */
1548 completeLoad: function (moduleName) {
1549 var found, args, mod,
1550 shim = getOwn(config.shim, moduleName) || {},
1551 shExports = shim.exports;
1552
1553 takeGlobalQueue();
1554
1555 while (defQueue.length) {
1556 args = defQueue.shift();
1557 if (args[0] === null) {
1558 args[0] = moduleName;
1559 //If already found an anonymous module and bound it
1560 //to this name, then this is some other anon module
1561 //waiting for its completeLoad to fire.
1562 if (found) {
1563 break;
1564 }
1565 found = true;
1566 } else if (args[0] === moduleName) {
1567 //Found matching define call for this script!
1568 found = true;
1569 }
1570
1571 callGetModule(args);
1572 }
a3620861 1573 context.defQueueMap = {};
adeb96d2
DW
1574
1575 //Do this after the cycle of callGetModule in case the result
1576 //of those calls/init calls changes the registry.
1577 mod = getOwn(registry, moduleName);
1578
1579 if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
1580 if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
1581 if (hasPathFallback(moduleName)) {
1582 return;
1583 } else {
1584 return onError(makeError('nodefine',
1585 'No define call for ' + moduleName,
1586 null,
1587 [moduleName]));
1588 }
1589 } else {
1590 //A script that does not call define(), so just simulate
1591 //the call for it.
1592 callGetModule([moduleName, (shim.deps || []), shim.exportsFn]);
1593 }
1594 }
1595
1596 checkLoaded();
1597 },
1598
1599 /**
1600 * Converts a module name to a file path. Supports cases where
1601 * moduleName may actually be just an URL.
1602 * Note that it **does not** call normalize on the moduleName,
1603 * it is assumed to have already been normalized. This is an
1604 * internal API, not a public one. Use toUrl for the public API.
1605 */
1606 nameToUrl: function (moduleName, ext, skipExt) {
1607 var paths, syms, i, parentModule, url,
1608 parentPath, bundleId,
1609 pkgMain = getOwn(config.pkgs, moduleName);
1610
1611 if (pkgMain) {
1612 moduleName = pkgMain;
1613 }
1614
1615 bundleId = getOwn(bundlesMap, moduleName);
1616
1617 if (bundleId) {
1618 return context.nameToUrl(bundleId, ext, skipExt);
1619 }
1620
1621 //If a colon is in the URL, it indicates a protocol is used and it is just
1622 //an URL to a file, or if it starts with a slash, contains a query arg (i.e. ?)
1623 //or ends with .js, then assume the user meant to use an url and not a module id.
1624 //The slash is important for protocol-less URLs as well as full paths.
1625 if (req.jsExtRegExp.test(moduleName)) {
1626 //Just a plain path, not module name lookup, so just return it.
1627 //Add extension if it is included. This is a bit wonky, only non-.js things pass
1628 //an extension, this method probably needs to be reworked.
1629 url = moduleName + (ext || '');
1630 } else {
1631 //A module that needs to be converted to a path.
1632 paths = config.paths;
1633
1634 syms = moduleName.split('/');
1635 //For each module name segment, see if there is a path
1636 //registered for it. Start with most specific name
1637 //and work up from it.
1638 for (i = syms.length; i > 0; i -= 1) {
1639 parentModule = syms.slice(0, i).join('/');
1640
1641 parentPath = getOwn(paths, parentModule);
1642 if (parentPath) {
1643 //If an array, it means there are a few choices,
1644 //Choose the one that is desired
1645 if (isArray(parentPath)) {
1646 parentPath = parentPath[0];
1647 }
1648 syms.splice(0, i, parentPath);
1649 break;
1650 }
1651 }
1652
1653 //Join the path parts together, then figure out if baseUrl is needed.
1654 url = syms.join('/');
1655 url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : '.js'));
1656 url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
1657 }
1658
1659 return config.urlArgs ? url +
1660 ((url.indexOf('?') === -1 ? '?' : '&') +
1661 config.urlArgs) : url;
1662 },
1663
1664 //Delegates to req.load. Broken out as a separate function to
1665 //allow overriding in the optimizer.
1666 load: function (id, url) {
1667 req.load(context, id, url);
1668 },
1669
1670 /**
1671 * Executes a module callback function. Broken out as a separate function
1672 * solely to allow the build system to sequence the files in the built
1673 * layer in the right sequence.
1674 *
1675 * @private
1676 */
1677 execCb: function (name, callback, args, exports) {
1678 return callback.apply(exports, args);
1679 },
1680
1681 /**
1682 * callback for script loads, used to check status of loading.
1683 *
1684 * @param {Event} evt the event from the browser for the script
1685 * that was loaded.
1686 */
1687 onScriptLoad: function (evt) {
1688 //Using currentTarget instead of target for Firefox 2.0's sake. Not
1689 //all old browsers will be supported, but this one was easy enough
1690 //to support and still makes sense.
1691 if (evt.type === 'load' ||
1692 (readyRegExp.test((evt.currentTarget || evt.srcElement).readyState))) {
1693 //Reset interactive script so a script node is not held onto for
1694 //to long.
1695 interactiveScript = null;
1696
1697 //Pull out the name of the module and the context.
1698 var data = getScriptData(evt);
1699 context.completeLoad(data.id);
1700 }
1701 },
1702
1703 /**
1704 * Callback for script errors.
1705 */
1706 onScriptError: function (evt) {
1707 var data = getScriptData(evt);
1708 if (!hasPathFallback(data.id)) {
1709 return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
1710 }
1711 }
1712 };
1713
1714 context.require = context.makeRequire();
1715 return context;
1716 }
1717
1718 /**
1719 * Main entry point.
1720 *
1721 * If the only argument to require is a string, then the module that
1722 * is represented by that string is fetched for the appropriate context.
1723 *
1724 * If the first argument is an array, then it will be treated as an array
1725 * of dependency string names to fetch. An optional function callback can
1726 * be specified to execute when all of those dependencies are available.
1727 *
1728 * Make a local req variable to help Caja compliance (it assumes things
1729 * on a require that are not standardized), and to give a short
1730 * name for minification/local scope use.
1731 */
1732 req = requirejs = function (deps, callback, errback, optional) {
1733
1734 //Find the right context, use default
1735 var context, config,
1736 contextName = defContextName;
1737
1738 // Determine if have config object in the call.
1739 if (!isArray(deps) && typeof deps !== 'string') {
1740 // deps is a config object
1741 config = deps;
1742 if (isArray(callback)) {
1743 // Adjust args if there are dependencies
1744 deps = callback;
1745 callback = errback;
1746 errback = optional;
1747 } else {
1748 deps = [];
1749 }
1750 }
1751
1752 if (config && config.context) {
1753 contextName = config.context;
1754 }
1755
1756 context = getOwn(contexts, contextName);
1757 if (!context) {
1758 context = contexts[contextName] = req.s.newContext(contextName);
1759 }
1760
1761 if (config) {
1762 context.configure(config);
1763 }
1764
1765 return context.require(deps, callback, errback);
1766 };
1767
1768 /**
1769 * Support require.config() to make it easier to cooperate with other
1770 * AMD loaders on globally agreed names.
1771 */
1772 req.config = function (config) {
1773 return req(config);
1774 };
1775
1776 /**
1777 * Execute something after the current tick
1778 * of the event loop. Override for other envs
1779 * that have a better solution than setTimeout.
1780 * @param {Function} fn function to execute later.
1781 */
1782 req.nextTick = typeof setTimeout !== 'undefined' ? function (fn) {
1783 setTimeout(fn, 4);
1784 } : function (fn) { fn(); };
1785
1786 /**
1787 * Export require as a global, but only if it does not already exist.
1788 */
1789 if (!require) {
1790 require = req;
1791 }
1792
1793 req.version = version;
1794
1795 //Used to filter out dependencies that are already paths.
1796 req.jsExtRegExp = /^\/|:|\?|\.js$/;
1797 req.isBrowser = isBrowser;
1798 s = req.s = {
1799 contexts: contexts,
1800 newContext: newContext
1801 };
1802
1803 //Create default context.
1804 req({});
1805
1806 //Exports some context-sensitive methods on global require.
1807 each([
1808 'toUrl',
1809 'undef',
1810 'defined',
1811 'specified'
1812 ], function (prop) {
1813 //Reference from contexts instead of early binding to default context,
1814 //so that during builds, the latest instance of the default context
1815 //with its config gets used.
1816 req[prop] = function () {
1817 var ctx = contexts[defContextName];
1818 return ctx.require[prop].apply(ctx, arguments);
1819 };
1820 });
1821
1822 if (isBrowser) {
1823 head = s.head = document.getElementsByTagName('head')[0];
1824 //If BASE tag is in play, using appendChild is a problem for IE6.
1825 //When that browser dies, this can be removed. Details in this jQuery bug:
1826 //http://dev.jquery.com/ticket/2709
1827 baseElement = document.getElementsByTagName('base')[0];
1828 if (baseElement) {
1829 head = s.head = baseElement.parentNode;
1830 }
1831 }
1832
1833 /**
1834 * Any errors that require explicitly generates will be passed to this
1835 * function. Intercept/override it if you want custom error handling.
1836 * @param {Error} err the error object.
1837 */
1838 req.onError = defaultOnError;
1839
1840 /**
1841 * Creates the node for the load command. Only used in browser envs.
1842 */
1843 req.createNode = function (config, moduleName, url) {
1844 var node = config.xhtml ?
1845 document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
1846 document.createElement('script');
1847 node.type = config.scriptType || 'text/javascript';
1848 node.charset = 'utf-8';
1849 node.async = true;
1850 return node;
1851 };
1852
1853 /**
1854 * Does the request to load a module for the browser case.
1855 * Make this a separate function to allow other environments
1856 * to override it.
1857 *
1858 * @param {Object} context the require context to find state.
1859 * @param {String} moduleName the name of the module.
1860 * @param {Object} url the URL to the module.
1861 */
1862 req.load = function (context, moduleName, url) {
1863 var config = (context && context.config) || {},
1864 node;
1865 if (isBrowser) {
1866 //In the browser so use a script tag
1867 node = req.createNode(config, moduleName, url);
a3620861
DW
1868 if (config.onNodeCreated) {
1869 config.onNodeCreated(node, config, moduleName, url);
1870 }
adeb96d2
DW
1871
1872 node.setAttribute('data-requirecontext', context.contextName);
1873 node.setAttribute('data-requiremodule', moduleName);
1874
1875 //Set up load listener. Test attachEvent first because IE9 has
1876 //a subtle issue in its addEventListener and script onload firings
1877 //that do not match the behavior of all other browsers with
1878 //addEventListener support, which fire the onload event for a
1879 //script right after the script execution. See:
1880 //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution
1881 //UNFORTUNATELY Opera implements attachEvent but does not follow the script
1882 //script execution mode.
1883 if (node.attachEvent &&
1884 //Check if node.attachEvent is artificially added by custom script or
1885 //natively supported by browser
1886 //read https://github.com/jrburke/requirejs/issues/187
1887 //if we can NOT find [native code] then it must NOT natively supported.
1888 //in IE8, node.attachEvent does not have toString()
1889 //Note the test for "[native code" with no closing brace, see:
1890 //https://github.com/jrburke/requirejs/issues/273
1891 !(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
1892 !isOpera) {
1893 //Probably IE. IE (at least 6-8) do not fire
1894 //script onload right after executing the script, so
1895 //we cannot tie the anonymous define call to a name.
1896 //However, IE reports the script as being in 'interactive'
1897 //readyState at the time of the define call.
1898 useInteractive = true;
1899
1900 node.attachEvent('onreadystatechange', context.onScriptLoad);
1901 //It would be great to add an error handler here to catch
1902 //404s in IE9+. However, onreadystatechange will fire before
1903 //the error handler, so that does not help. If addEventListener
1904 //is used, then IE will fire error before load, but we cannot
1905 //use that pathway given the connect.microsoft.com issue
1906 //mentioned above about not doing the 'script execute,
1907 //then fire the script load event listener before execute
1908 //next script' that other browsers do.
1909 //Best hope: IE10 fixes the issues,
1910 //and then destroys all installs of IE 6-9.
1911 //node.attachEvent('onerror', context.onScriptError);
1912 } else {
1913 node.addEventListener('load', context.onScriptLoad, false);
1914 node.addEventListener('error', context.onScriptError, false);
1915 }
1916 node.src = url;
1917
1918 //For some cache cases in IE 6-8, the script executes before the end
1919 //of the appendChild execution, so to tie an anonymous define
1920 //call to the module name (which is stored on the node), hold on
1921 //to a reference to this node, but clear after the DOM insertion.
1922 currentlyAddingScript = node;
1923 if (baseElement) {
1924 head.insertBefore(node, baseElement);
1925 } else {
1926 head.appendChild(node);
1927 }
1928 currentlyAddingScript = null;
1929
1930 return node;
1931 } else if (isWebWorker) {
1932 try {
1933 //In a web worker, use importScripts. This is not a very
1934 //efficient use of importScripts, importScripts will block until
1935 //its script is downloaded and evaluated. However, if web workers
1936 //are in play, the expectation that a build has been done so that
1937 //only one script needs to be loaded anyway. This may need to be
1938 //reevaluated if other use cases become common.
1939 importScripts(url);
1940
1941 //Account for anonymous modules
1942 context.completeLoad(moduleName);
1943 } catch (e) {
1944 context.onError(makeError('importscripts',
1945 'importScripts failed for ' +
1946 moduleName + ' at ' + url,
1947 e,
1948 [moduleName]));
1949 }
1950 }
1951 };
1952
1953 function getInteractiveScript() {
1954 if (interactiveScript && interactiveScript.readyState === 'interactive') {
1955 return interactiveScript;
1956 }
1957
1958 eachReverse(scripts(), function (script) {
1959 if (script.readyState === 'interactive') {
1960 return (interactiveScript = script);
1961 }
1962 });
1963 return interactiveScript;
1964 }
1965
1966 //Look for a data-main script attribute, which could also adjust the baseUrl.
1967 if (isBrowser && !cfg.skipDataMain) {
1968 //Figure out baseUrl. Get it from the script tag with require.js in it.
1969 eachReverse(scripts(), function (script) {
1970 //Set the 'head' where we can append children by
1971 //using the script's parent.
1972 if (!head) {
1973 head = script.parentNode;
1974 }
1975
1976 //Look for a data-main attribute to set main script for the page
1977 //to load. If it is there, the path to data main becomes the
1978 //baseUrl, if it is not already set.
1979 dataMain = script.getAttribute('data-main');
1980 if (dataMain) {
1981 //Preserve dataMain in case it is a path (i.e. contains '?')
1982 mainScript = dataMain;
1983
1984 //Set final baseUrl if there is not already an explicit one.
1985 if (!cfg.baseUrl) {
1986 //Pull off the directory of data-main for use as the
1987 //baseUrl.
1988 src = mainScript.split('/');
1989 mainScript = src.pop();
1990 subPath = src.length ? src.join('/') + '/' : './';
1991
1992 cfg.baseUrl = subPath;
1993 }
1994
1995 //Strip off any trailing .js since mainScript is now
1996 //like a module name.
1997 mainScript = mainScript.replace(jsSuffixRegExp, '');
1998
a3620861 1999 //If mainScript is still a path, fall back to dataMain
adeb96d2
DW
2000 if (req.jsExtRegExp.test(mainScript)) {
2001 mainScript = dataMain;
2002 }
2003
2004 //Put the data-main script in the files to load.
2005 cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
2006
2007 return true;
2008 }
2009 });
2010 }
2011
2012 /**
2013 * The function that handles definitions of modules. Differs from
2014 * require() in that a string for the module should be the first argument,
2015 * and the function to execute after dependencies are loaded should
2016 * return a value to define the module corresponding to the first argument's
2017 * name.
2018 */
2019 define = function (name, deps, callback) {
2020 var node, context;
2021
2022 //Allow for anonymous modules
2023 if (typeof name !== 'string') {
2024 //Adjust args appropriately
2025 callback = deps;
2026 deps = name;
2027 name = null;
2028 }
2029
2030 //This module may not have dependencies
2031 if (!isArray(deps)) {
2032 callback = deps;
2033 deps = null;
2034 }
2035
2036 //If no name, and callback is a function, then figure out if it a
2037 //CommonJS thing with dependencies.
2038 if (!deps && isFunction(callback)) {
2039 deps = [];
2040 //Remove comments from the callback string,
2041 //look for require calls, and pull them into the dependencies,
2042 //but only if there are function args.
2043 if (callback.length) {
2044 callback
2045 .toString()
2046 .replace(commentRegExp, '')
2047 .replace(cjsRequireRegExp, function (match, dep) {
2048 deps.push(dep);
2049 });
2050
2051 //May be a CommonJS thing even without require calls, but still
2052 //could use exports, and module. Avoid doing exports and module
2053 //work though if it just needs require.
2054 //REQUIRES the function to expect the CommonJS variables in the
2055 //order listed below.
2056 deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
2057 }
2058 }
2059
2060 //If in IE 6-8 and hit an anonymous define() call, do the interactive
2061 //work.
2062 if (useInteractive) {
2063 node = currentlyAddingScript || getInteractiveScript();
2064 if (node) {
2065 if (!name) {
2066 name = node.getAttribute('data-requiremodule');
2067 }
2068 context = contexts[node.getAttribute('data-requirecontext')];
2069 }
2070 }
2071
2072 //Always save off evaluating the def call until the script onload handler.
2073 //This allows multiple modules to be in a file without prematurely
2074 //tracing dependencies, and allows for anonymous module support,
2075 //where the module name is not known until the script onload event
2076 //occurs. If no context, use the global queue, and get it processed
2077 //in the onscript load callback.
a3620861
DW
2078 if (context) {
2079 context.defQueue.push([name, deps, callback]);
2080 context.defQueueMap[name] = true;
2081 } else {
2082 globalDefQueue.push([name, deps, callback]);
2083 }
adeb96d2
DW
2084 };
2085
2086 define.amd = {
2087 jQuery: true
2088 };
2089
adeb96d2
DW
2090 /**
2091 * Executes the text. Normally just uses eval, but can be modified
2092 * to use a better, environment-specific call. Only used for transpiling
2093 * loader plugins, not for plain JS modules.
2094 * @param {String} text the text to execute/evaluate.
2095 */
2096 req.exec = function (text) {
2097 /*jslint evil: true */
2098 return eval(text);
2099 };
2100
2101 //Set up with config info.
2102 req(cfg);
2103}(this));