1 | /**
|
2 | * @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
|
3 | * Available via the MIT or new BSD license.
|
4 | * see: http://github.com/jrburke/almond for details
|
5 | */
|
6 | //Going sloppy to avoid 'use strict' string cost, but strict practices should
|
7 | //be followed.
|
8 | /*jslint sloppy: true */
|
9 | /*global setTimeout: false */
|
10 |
|
11 | var requirejs, require, define;
|
12 | (function (undef) {
|
13 | var main, req, makeMap, handlers,
|
14 | defined = {},
|
15 | waiting = {},
|
16 | config = {},
|
17 | defining = {},
|
18 | hasOwn = Object.prototype.hasOwnProperty,
|
19 | aps = [].slice,
|
20 | jsSuffixRegExp = /\.js$/;
|
21 |
|
22 | function hasProp(obj, prop) {
|
23 | return hasOwn.call(obj, prop);
|
24 | }
|
25 |
|
26 | /**
|
27 | * Given a relative module name, like ./something, normalize it to
|
28 | * a real name that can be mapped to a path.
|
29 | * @param {String} name the relative name
|
30 | * @param {String} baseName a real name that the name arg is relative
|
31 | * to.
|
32 | * @returns {String} normalized name
|
33 | */
|
34 | function normalize(name, baseName) {
|
35 | var nameParts, nameSegment, mapValue, foundMap, lastIndex,
|
36 | foundI, foundStarMap, starI, i, j, part,
|
37 | baseParts = baseName && baseName.split("/"),
|
38 | map = config.map,
|
39 | starMap = (map && map['*']) || {};
|
40 |
|
41 | //Adjust any relative paths.
|
42 | if (name && name.charAt(0) === ".") {
|
43 | //If have a base name, try to normalize against it,
|
44 | //otherwise, assume it is a top-level require that will
|
45 | //be relative to baseUrl in the end.
|
46 | if (baseName) {
|
47 | //Convert baseName to array, and lop off the last part,
|
48 | //so that . matches that "directory" and not name of the baseName's
|
49 | //module. For instance, baseName of "one/two/three", maps to
|
50 | //"one/two/three.js", but we want the directory, "one/two" for
|
51 | //this normalization.
|
52 | baseParts = baseParts.slice(0, baseParts.length - 1);
|
53 | name = name.split('/');
|
54 | lastIndex = name.length - 1;
|
55 |
|
56 | // Node .js allowance:
|
57 | if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
|
58 | name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
|
59 | }
|
60 |
|
61 | name = baseParts.concat(name);
|
62 |
|
63 | //start trimDots
|
64 | for (i = 0; i < name.length; i += 1) {
|
65 | part = name[i];
|
66 | if (part === ".") {
|
67 | name.splice(i, 1);
|
68 | i -= 1;
|
69 | } else if (part === "..") {
|
70 | if (i === 1 && (name[2] === '..' || name[0] === '..')) {
|
71 | //End of the line. Keep at least one non-dot
|
72 | //path segment at the front so it can be mapped
|
73 | //correctly to disk. Otherwise, there is likely
|
74 | //no path mapping for a path starting with '..'.
|
75 | //This can still fail, but catches the most reasonable
|
76 | //uses of ..
|
77 | break;
|
78 | } else if (i > 0) {
|
79 | name.splice(i - 1, 2);
|
80 | i -= 2;
|
81 | }
|
82 | }
|
83 | }
|
84 | //end trimDots
|
85 |
|
86 | name = name.join("/");
|
87 | } else if (name.indexOf('./') === 0) {
|
88 | // No baseName, so this is ID is resolved relative
|
89 | // to baseUrl, pull off the leading dot.
|
90 | name = name.substring(2);
|
91 | }
|
92 | }
|
93 |
|
94 | //Apply map config if available.
|
95 | if ((baseParts || starMap) && map) {
|
96 | nameParts = name.split('/');
|
97 |
|
98 | for (i = nameParts.length; i > 0; i -= 1) {
|
99 | nameSegment = nameParts.slice(0, i).join("/");
|
100 |
|
101 | if (baseParts) {
|
102 | //Find the longest baseName segment match in the config.
|
103 | //So, do joins on the biggest to smallest lengths of baseParts.
|
104 | for (j = baseParts.length; j > 0; j -= 1) {
|
105 | mapValue = map[baseParts.slice(0, j).join('/')];
|
106 |
|
107 | //baseName segment has config, find if it has one for
|
108 | //this name.
|
109 | if (mapValue) {
|
110 | mapValue = mapValue[nameSegment];
|
111 | if (mapValue) {
|
112 | //Match, update name to the new value.
|
113 | foundMap = mapValue;
|
114 | foundI = i;
|
115 | break;
|
116 | }
|
117 | }
|
118 | }
|
119 | }
|
120 |
|
121 | if (foundMap) {
|
122 | break;
|
123 | }
|
124 |
|
125 | //Check for a star map match, but just hold on to it,
|
126 | //if there is a shorter segment match later in a matching
|
127 | //config, then favor over this star map.
|
128 | if (!foundStarMap && starMap && starMap[nameSegment]) {
|
129 | foundStarMap = starMap[nameSegment];
|
130 | starI = i;
|
131 | }
|
132 | }
|
133 |
|
134 | if (!foundMap && foundStarMap) {
|
135 | foundMap = foundStarMap;
|
136 | foundI = starI;
|
137 | }
|
138 |
|
139 | if (foundMap) {
|
140 | nameParts.splice(0, foundI, foundMap);
|
141 | name = nameParts.join('/');
|
142 | }
|
143 | }
|
144 |
|
145 | return name;
|
146 | }
|
147 |
|
148 | function makeRequire(relName, forceSync) {
|
149 | return function () {
|
150 | //A version of a require function that passes a moduleName
|
151 | //value for items that may need to
|
152 | //look up paths relative to the moduleName
|
153 | var args = aps.call(arguments, 0);
|
154 |
|
155 | //If first arg is not require('string'), and there is only
|
156 | //one arg, it is the array form without a callback. Insert
|
157 | //a null so that the following concat is correct.
|
158 | if (typeof args[0] !== 'string' && args.length === 1) {
|
159 | args.push(null);
|
160 | }
|
161 | return req.apply(undef, args.concat([relName, forceSync]));
|
162 | };
|
163 | }
|
164 |
|
165 | function makeNormalize(relName) {
|
166 | return function (name) {
|
167 | return normalize(name, relName);
|
168 | };
|
169 | }
|
170 |
|
171 | function makeLoad(depName) {
|
172 | return function (value) {
|
173 | defined[depName] = value;
|
174 | };
|
175 | }
|
176 |
|
177 | function callDep(name) {
|
178 | if (hasProp(waiting, name)) {
|
179 | var args = waiting[name];
|
180 | delete waiting[name];
|
181 | defining[name] = true;
|
182 | main.apply(undef, args);
|
183 | }
|
184 |
|
185 | if (!hasProp(defined, name) && !hasProp(defining, name)) {
|
186 | throw new Error('No ' + name);
|
187 | }
|
188 | return defined[name];
|
189 | }
|
190 |
|
191 | //Turns a plugin!resource to [plugin, resource]
|
192 | //with the plugin being undefined if the name
|
193 | //did not have a plugin prefix.
|
194 | function splitPrefix(name) {
|
195 | var prefix,
|
196 | index = name ? name.indexOf('!') : -1;
|
197 | if (index > -1) {
|
198 | prefix = name.substring(0, index);
|
199 | name = name.substring(index + 1, name.length);
|
200 | }
|
201 | return [prefix, name];
|
202 | }
|
203 |
|
204 | /**
|
205 | * Makes a name map, normalizing the name, and using a plugin
|
206 | * for normalization if necessary. Grabs a ref to plugin
|
207 | * too, as an optimization.
|
208 | */
|
209 | makeMap = function (name, relName) {
|
210 | var plugin,
|
211 | parts = splitPrefix(name),
|
212 | prefix = parts[0];
|
213 |
|
214 | name = parts[1];
|
215 |
|
216 | if (prefix) {
|
217 | prefix = normalize(prefix, relName);
|
218 | plugin = callDep(prefix);
|
219 | }
|
220 |
|
221 | //Normalize according
|
222 | if (prefix) {
|
223 | if (plugin && plugin.normalize) {
|
224 | name = plugin.normalize(name, makeNormalize(relName));
|
225 | } else {
|
226 | name = normalize(name, relName);
|
227 | }
|
228 | } else {
|
229 | name = normalize(name, relName);
|
230 | parts = splitPrefix(name);
|
231 | prefix = parts[0];
|
232 | name = parts[1];
|
233 | if (prefix) {
|
234 | plugin = callDep(prefix);
|
235 | }
|
236 | }
|
237 |
|
238 | //Using ridiculous property names for space reasons
|
239 | return {
|
240 | f: prefix ? prefix + '!' + name : name, //fullName
|
241 | n: name,
|
242 | pr: prefix,
|
243 | p: plugin
|
244 | };
|
245 | };
|
246 |
|
247 | function makeConfig(name) {
|
248 | return function () {
|
249 | return (config && config.config && config.config[name]) || {};
|
250 | };
|
251 | }
|
252 |
|
253 | handlers = {
|
254 | require: function (name) {
|
255 | return makeRequire(name);
|
256 | },
|
257 | exports: function (name) {
|
258 | var e = defined[name];
|
259 | if (typeof e !== 'undefined') {
|
260 | return e;
|
261 | } else {
|
262 | return (defined[name] = {});
|
263 | }
|
264 | },
|
265 | module: function (name) {
|
266 | return {
|
267 | id: name,
|
268 | uri: '',
|
269 | exports: defined[name],
|
270 | config: makeConfig(name)
|
271 | };
|
272 | }
|
273 | };
|
274 |
|
275 | main = function (name, deps, callback, relName) {
|
276 | var cjsModule, depName, ret, map, i,
|
277 | args = [],
|
278 | callbackType = typeof callback,
|
279 | usingExports;
|
280 |
|
281 | //Use name if no relName
|
282 | relName = relName || name;
|
283 |
|
284 | //Call the callback to define the module, if necessary.
|
285 | if (callbackType === 'undefined' || callbackType === 'function') {
|
286 | //Pull out the defined dependencies and pass the ordered
|
287 | //values to the callback.
|
288 | //Default to [require, exports, module] if no deps
|
289 | deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
|
290 | for (i = 0; i < deps.length; i += 1) {
|
291 | map = makeMap(deps[i], relName);
|
292 | depName = map.f;
|
293 |
|
294 | //Fast path CommonJS standard dependencies.
|
295 | if (depName === "require") {
|
296 | args[i] = handlers.require(name);
|
297 | } else if (depName === "exports") {
|
298 | //CommonJS module spec 1.1
|
299 | args[i] = handlers.exports(name);
|
300 | usingExports = true;
|
301 | } else if (depName === "module") {
|
302 | //CommonJS module spec 1.1
|
303 | cjsModule = args[i] = handlers.module(name);
|
304 | } else if (hasProp(defined, depName) ||
|
305 | hasProp(waiting, depName) ||
|
306 | hasProp(defining, depName)) {
|
307 | args[i] = callDep(depName);
|
308 | } else if (map.p) {
|
309 | map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
|
310 | args[i] = defined[depName];
|
311 | } else {
|
312 | throw new Error(name + ' missing ' + depName);
|
313 | }
|
314 | }
|
315 |
|
316 | ret = callback ? callback.apply(defined[name], args) : undefined;
|
317 |
|
318 | if (name) {
|
319 | //If setting exports via "module" is in play,
|
320 | //favor that over return value and exports. After that,
|
321 | //favor a non-undefined return value over exports use.
|
322 | if (cjsModule && cjsModule.exports !== undef &&
|
323 | cjsModule.exports !== defined[name]) {
|
324 | defined[name] = cjsModule.exports;
|
325 | } else if (ret !== undef || !usingExports) {
|
326 | //Use the return value from the function.
|
327 | defined[name] = ret;
|
328 | }
|
329 | }
|
330 | } else if (name) {
|
331 | //May just be an object definition for the module. Only
|
332 | //worry about defining if have a module name.
|
333 | defined[name] = callback;
|
334 | }
|
335 | };
|
336 |
|
337 | requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
|
338 | if (typeof deps === "string") {
|
339 | if (handlers[deps]) {
|
340 | //callback in this case is really relName
|
341 | return handlers[deps](callback);
|
342 | }
|
343 | //Just return the module wanted. In this scenario, the
|
344 | //deps arg is the module name, and second arg (if passed)
|
345 | //is just the relName.
|
346 | //Normalize module name, if it contains . or ..
|
347 | return callDep(makeMap(deps, callback).f);
|
348 | } else if (!deps.splice) {
|
349 | //deps is a config object, not an array.
|
350 | config = deps;
|
351 | if (config.deps) {
|
352 | req(config.deps, config.callback);
|
353 | }
|
354 | if (!callback) {
|
355 | return;
|
356 | }
|
357 |
|
358 | if (callback.splice) {
|
359 | //callback is an array, which means it is a dependency list.
|
360 | //Adjust args if there are dependencies
|
361 | deps = callback;
|
362 | callback = relName;
|
363 | relName = null;
|
364 | } else {
|
365 | deps = undef;
|
366 | }
|
367 | }
|
368 |
|
369 | //Support require(['a'])
|
370 | callback = callback || function () {};
|
371 |
|
372 | //If relName is a function, it is an errback handler,
|
373 | //so remove it.
|
374 | if (typeof relName === 'function') {
|
375 | relName = forceSync;
|
376 | forceSync = alt;
|
377 | }
|
378 |
|
379 | //Simulate async callback;
|
380 | if (forceSync) {
|
381 | main(undef, deps, callback, relName);
|
382 | } else {
|
383 | //Using a non-zero value because of concern for what old browsers
|
384 | //do, and latest browsers "upgrade" to 4 if lower value is used:
|
385 | //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
|
386 | //If want a value immediately, use require('id') instead -- something
|
387 | //that works in almond on the global level, but not guaranteed and
|
388 | //unlikely to work in other AMD implementations.
|
389 | setTimeout(function () {
|
390 | main(undef, deps, callback, relName);
|
391 | }, 4);
|
392 | }
|
393 |
|
394 | return req;
|
395 | };
|
396 |
|
397 | /**
|
398 | * Just drops the config on the floor, but returns req in case
|
399 | * the config return value is used.
|
400 | */
|
401 | req.config = function (cfg) {
|
402 | return req(cfg);
|
403 | };
|
404 |
|
405 | /**
|
406 | * Expose module registry for debugging and tooling
|
407 | */
|
408 | requirejs._defined = defined;
|
409 |
|
410 | define = function (name, deps, callback) {
|
411 |
|
412 | //This module may not have dependencies
|
413 | if (!deps.splice) {
|
414 | //deps is not an array, so probably means
|
415 | //an object literal or factory function for
|
416 | //the value. Adjust args.
|
417 | callback = deps;
|
418 | deps = [];
|
419 | }
|
420 |
|
421 | if (!hasProp(defined, name) && !hasProp(waiting, name)) {
|
422 | waiting[name] = [name, deps, callback];
|
423 | }
|
424 | };
|
425 |
|
426 | define.amd = {
|
427 | jQuery: true
|
428 | };
|
429 | }());
|