3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 * The YUI module contains the components required for building the YUI seed
9 * file. This includes the script loading mechanism, a simple queue, and
10 * the core utilities for the library.
15 if (typeof YUI != 'undefined') {
20 The YUI global namespace object. If YUI is already defined, the
21 existing YUI object will not be overwritten so that defined
22 namespaces are preserved. It is the constructor for the object
23 the end user interacts with. As indicated below, each instance
24 has full custom event support, but only if the event system
25 is available. This is a self-instantiable factory function. You
26 can invoke it directly like this:
28 YUI().use('*', function(Y) {
32 But it also works like this:
36 Configuring the YUI object:
41 }).use('node', function(Y) {
42 //Node is ready to use
45 See the API docs for the <a href="config.html">Config</a> class
46 for the complete list of supported configuration properties accepted
47 by the YUI constuctor.
53 @param [o]* {Object} 0..n optional configuration objects. these values
54 are store in Y.config. See <a href="config.html">Config</a> for the list of supported
59 var YUI = function() {
64 instanceOf = function(o, type) {
65 return (o && o.hasOwnProperty && (o instanceof type));
67 gconf = (typeof YUI_config !== 'undefined') && YUI_config;
69 if (!(instanceOf(Y, YUI))) {
72 // set up the core environment
76 YUI.GlobalConfig is a master configuration that might span
77 multiple contexts in a non-browser environment. It is applied
78 first to all instances in all contexts.
79 @property GlobalConfig
90 YUI().use('node', function(Y) {
91 //debug files used here
96 }).use('node', function(Y) {
101 if (YUI.GlobalConfig) {
102 Y.applyConfig(YUI.GlobalConfig);
106 YUI_config is a page-level config. It is applied to all
107 instances created on the page. This is applied after
108 YUI.GlobalConfig, and before the instance level configuration
116 //Single global var to include before YUI seed file
121 YUI().use('node', function(Y) {
122 //debug files used here
127 }).use('node', function(Y) {
128 //min files used here
132 Y.applyConfig(gconf);
135 // bind the specified additional modules for this instance
142 // Each instance can accept one or more configuration objects.
143 // These are applied after YUI.GlobalConfig and YUI_Config,
144 // overriding values set in those config files if there is a '
145 // matching property.
147 Y.applyConfig(args[i]);
153 Y.instanceOf = instanceOf;
163 BASE = 'http://yui.yahooapis.com/',
164 DOC_LABEL = 'yui3-js-enabled',
165 CSS_STAMP_EL = 'yui3-css-stamp',
166 NOOP = function() {},
167 SLICE = Array.prototype.slice,
168 APPLY_TO_AUTH = { 'io.xdrReady': 1, // the functions applyTo
169 'io.xdrResponse': 1, // can call. this should
170 'SWF.eventHandler': 1 }, // be done at build time
171 hasWin = (typeof window != 'undefined'),
172 win = (hasWin) ? window : null,
173 doc = (hasWin) ? win.document : null,
174 docEl = doc && doc.documentElement,
175 docClass = docEl && docEl.className,
177 time = new Date().getTime(),
178 add = function(el, type, fn, capture) {
179 if (el && el.addEventListener) {
180 el.addEventListener(type, fn, capture);
181 } else if (el && el.attachEvent) {
182 el.attachEvent('on' + type, fn);
185 remove = function(el, type, fn, capture) {
186 if (el && el.removeEventListener) {
187 // this can throw an uncaught exception in FF
189 el.removeEventListener(type, fn, capture);
191 } else if (el && el.detachEvent) {
192 el.detachEvent('on' + type, fn);
195 handleLoad = function() {
196 YUI.Env.windowLoaded = true;
197 YUI.Env.DOMReady = true;
199 remove(window, 'load', handleLoad);
202 getLoader = function(Y, o) {
203 var loader = Y.Env._loader;
205 //loader._config(Y.config);
206 loader.ignoreRegistered = false;
209 loader.required = [];
210 loader.loadType = null;
212 loader = new Y.Loader(Y.config);
213 Y.Env._loader = loader;
215 YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, [ 'loader-base', 'loader-rollup', 'loader-yui3' ]));
220 clobber = function(r, s) {
222 if (s.hasOwnProperty(i)) {
228 ALREADY_DONE = { success: true };
230 // Stamp the documentElement (HTML) with a class of "yui-loaded" to
231 // enable styles that need to key off of JS being enabled.
232 if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
236 docClass += DOC_LABEL;
237 docEl.className = docClass;
240 if (VERSION.indexOf('@') > -1) {
241 VERSION = '3.3.0'; // dev time hack for cdn test
246 * Applies a new configuration object to the YUI instance config.
247 * This will merge new group/module definitions, and will also
248 * update the loader cache if necessary. Updating Y.config directly
249 * will not update the cache.
250 * @method applyConfig
251 * @param {Object} o the configuration object.
254 applyConfig: function(o) {
261 config = this.config,
262 mods = config.modules,
263 groups = config.groups,
264 aliases = config.aliases,
265 loader = this.Env._loader;
268 if (o.hasOwnProperty(name)) {
270 if (mods && name == 'modules') {
272 } else if (aliases && name == 'aliases') {
273 clobber(aliases, attr);
274 } else if (groups && name == 'groups') {
275 clobber(groups, attr);
276 } else if (name == 'win') {
277 config[name] = (attr && attr.contentWindow) || attr;
278 config.doc = config[name] ? config[name].document : null;
279 } else if (name == '_yuid') {
293 * Old way to apply a config to the instance (calls `applyConfig` under the hood)
296 * @param {Object} o The config to apply
298 _config: function(o) {
303 * Initialize this YUI instance
315 * The version number of the YUI instance.
323 core: ['get','features','intl-base','yui-log', 'yui-log-nodejs', 'yui-later','loader-base', 'loader-rollup', 'loader-yui3'],
324 mods: {}, // flat module map
325 versions: {}, // version module map
327 cdn: BASE + VERSION + '/build/',
328 // bootstrapped: false,
339 // I'll start at the \b(simpleyui).
340 // 1. Look in the test string for "simpleyui" or "yui" or
341 // "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break. That is, it
342 // can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
343 // 2. After #1 must come a forward slash followed by the string matched in #1, so
344 // "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
345 // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
346 // so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
347 // 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
348 // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
349 // then capture the junk between the LAST "&" and the string in 1-4. So
350 // "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
351 // will capture "3.3.0/build/"
355 // (?:[^&]*&) followed by 0..n characters followed by an &
356 // * in fact, find as many sets of characters followed by a & as you can
357 // ([^&]*) capture the stuff after the last & in \1
358 // )? but it's ok if all this ?junk&more_junk stuff isn't even there
359 // \b(simpleyui| after a word break find either the string "simpleyui" or
360 // yui(?:-\w+)? the string "yui" optionally followed by a -, then more characters
361 // ) and store the simpleyui or yui-* string in \2
362 // \/\2 then comes a / followed by the simpleyui or yui-* string in \2
363 // (?:-(min|debug))? optionally followed by "-min" or "-debug"
364 // .js and ending in ".js"
365 _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
366 parseBasePath: function(src, pattern) {
367 var match = src.match(pattern),
371 path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
373 // this is to set up the path to the loader. The file
374 // filter for loader should match the yui include.
377 // extract correct path for mixed combo urls
378 // http://yuilibrary.com/projects/yui3/ticket/2528423
380 path += '?' + match[1];
389 getBase: G_ENV && G_ENV.getBase ||
391 var nodes = (doc && doc.getElementsByTagName('script')) || [],
392 path = Env.cdn, parsed,
395 for (i = 0, len = nodes.length; i < len; ++i) {
398 parsed = Y.Env.parseBasePath(src, pattern);
400 filter = parsed.filter;
415 Env._loaded[VERSION] = {};
417 if (G_ENV && Y !== YUI) {
418 Env._yidx = ++G_ENV._yidx;
419 Env._guidp = ('yui_' + VERSION + '_' +
420 Env._yidx + '_' + time).replace(/\./g, '_');
421 } else if (YUI._YUI) {
423 G_ENV = YUI._YUI.Env;
424 Env._yidx += G_ENV._yidx;
425 Env._uidx += G_ENV._uidx;
427 for (prop in G_ENV) {
428 if (!(prop in Env)) {
429 Env[prop] = G_ENV[prop];
443 // configuration defaults
444 Y.config = Y.config || {
451 useBrowserConsole: true,
456 //Register the CSS stamp element
457 if (doc && !doc.getElementById(CSS_STAMP_EL)) {
458 el = doc.createElement('div');
459 el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
460 YUI.Env.cssStampEl = el.firstChild;
461 docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
464 Y.config.lang = Y.config.lang || 'en-US';
466 Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
468 if (!filter || (!('mindebug').indexOf(filter))) {
471 filter = (filter) ? '-' + filter : filter;
472 Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
477 * Finishes the instance setup. Attaches whatever modules were defined
478 * when the yui modules was registered.
482 _setup: function(o) {
486 //extras = Y.config.core || ['get','features','intl-base','yui-log', 'yui-log-nodejs', 'yui-later','loader-base', 'loader-rollup', 'loader-yui3'];
487 extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
489 for (i = 0; i < extras.length; i++) {
490 if (mods[extras[i]]) {
491 core.push(extras[i]);
495 Y._attach(['yui-base']);
505 * Executes a method on a YUI instance with
506 * the specified id if the specified method is whitelisted.
508 * @param id {String} the YUI instance id.
509 * @param method {String} the name of the method to exectute.
511 * @param args {Array} the arguments to apply to the method.
512 * @return {Object} the return value from the applied method or null.
514 applyTo: function(id, method, args) {
515 if (!(method in APPLY_TO_AUTH)) {
516 this.log(method + ': applyTo not allowed', 'warn', 'yui');
520 var instance = instances[id], nest, m, i;
522 nest = method.split('.');
524 for (i = 0; i < nest.length; i = i + 1) {
527 this.log('applyTo not found: ' + method, 'warn', 'yui');
530 return m && m.apply(instance, args);
537 Registers a module with the YUI global. The easiest way to create a
538 first-class YUI module is to use the YUI component build tool.
540 http://yuilibrary.com/projects/builder
542 The build system will produce the `YUI.add` wrapper for you module, along
543 with any configuration info required for the module.
545 @param name {String} module name.
546 @param fn {Function} entry point into the module that is used to bind module to the YUI instance.
547 @param {YUI} fn.Y The YUI instance this module is executed in.
548 @param {String} fn.name The name of the module
549 @param version {String} version string.
550 @param details {Object} optional config data:
551 @param details.requires {Array} features that must be present before this module can be attached.
552 @param details.optional {Array} optional features that should be present if loadOptional
553 is defined. Note: modules are not often loaded this way in YUI 3,
554 but this field is still useful to inform the user that certain
555 features in the component will require additional dependencies.
556 @param details.use {Array} features that are included within this module which need to
557 be attached automatically when this module is attached. This
558 supports the YUI 3 rollup system -- a module with submodules
559 defined will need to have the submodules listed in the 'use'
560 config. The YUI component build tool does this for you.
561 @return {YUI} the YUI instance.
564 YUI.add('davglass', function(Y, name) {
565 Y.davglass = function() {
566 alert('Dav was here!');
568 }, '3.4.0', { requires: ['yui-base', 'harley-davidson', 'mt-dew'] });
571 add: function(name, fn, version, details) {
572 details = details || {};
581 i, versions = env.versions;
583 env.mods[name] = mod;
584 versions[version] = versions[version] || {};
585 versions[version][name] = mod;
587 for (i in instances) {
588 if (instances.hasOwnProperty(i)) {
589 loader = instances[i].Env._loader;
591 if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
592 loader.addModule(details, name);
602 * Executes the function associated with each required
603 * module, binding the module to the YUI instance.
604 * @param {Array} r The array of modules to attach
605 * @param {Boolean} [moot=false] Don't throw a warning if the module is not attached
609 _attach: function(r, moot) {
610 var i, name, mod, details, req, use, after,
612 aliases = YUI.Env.aliases,
614 loader = Y.Env._loader,
615 done = Y.Env._attached,
616 len = r.length, loader,
619 //Check for conditional modules (in a second+ instance) and add their requirements
620 //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
621 for (i = 0; i < len; i++) {
625 if (loader && loader.conditions[name]) {
626 Y.Object.each(loader.conditions[name], function(def) {
627 var go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
637 for (i = 0; i < len; i++) {
642 if (aliases && aliases[name]) {
643 Y._attach(aliases[name]);
647 if (loader && loader.moduleInfo[name]) {
648 mod = loader.moduleInfo[name];
653 //if (!loader || !loader.moduleInfo[name]) {
654 //if ((!loader || !loader.moduleInfo[name]) && !moot) {
656 if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
657 Y.Env._missed.push(name);
658 Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
659 Y.message('NOT loaded: ' + name, 'warn', 'yui');
664 //Don't like this, but in case a mod was asked for once, then we fetch it
665 //We need to remove it from the missed list ^davglass
666 for (j = 0; j < Y.Env._missed.length; j++) {
667 if (Y.Env._missed[j] === name) {
668 Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
669 Y.Env._missed.splice(j, 1);
672 details = mod.details;
673 req = details.requires;
675 after = details.after;
678 for (j = 0; j < req.length; j++) {
680 if (!Y._attach(req)) {
689 for (j = 0; j < after.length; j++) {
690 if (!done[after[j]]) {
691 if (!Y._attach(after, true)) {
703 Y.error('Attach error: ' + name, e, name);
709 for (j = 0; j < use.length; j++) {
711 if (!Y._attach(use)) {
729 * Attaches one or more modules to the YUI instance. When this
730 * is executed, the requirements are analyzed, and one of
731 * several things can happen:
733 * * All requirements are available on the page -- The modules
734 * are attached to the instance. If supplied, the use callback
735 * is executed synchronously.
737 * * Modules are missing, the Get utility is not available OR
738 * the 'bootstrap' config is false -- A warning is issued about
739 * the missing modules and all available modules are attached.
741 * * Modules are missing, the Loader is not available but the Get
742 * utility is and boostrap is not false -- The loader is bootstrapped
743 * before doing the following....
745 * * Modules are missing and the Loader is available -- The loader
746 * expands the dependency tree and fetches missing modules. When
747 * the loader is finshed the callback supplied to use is executed
751 * @param modules* {String|Array} 1-n modules to bind (uses arguments array).
752 * @param [callback] {Function} callback function executed when
753 * the instance has the required functionality. If included, it
754 * must be the last parameter.
755 * @param callback.Y {YUI} The `YUI` instance created for this sandbox
756 * @param callback.data {Object} Object data returned from `Loader`.
759 * // loads and attaches dd and its dependencies
760 * YUI().use('dd', function(Y) {});
762 * // loads and attaches dd and node as well as all of their dependencies (since 3.4.0)
763 * YUI().use(['dd', 'node'], function(Y) {});
765 * // attaches all modules that are available on the page
766 * YUI().use('*', function(Y) {});
768 * // intrinsic YUI gallery support (since 3.1.0)
769 * YUI().use('gallery-yql', function(Y) {});
771 * // intrinsic YUI 2in3 support (since 3.1.0)
772 * YUI().use('yui2-datatable', function(Y) {});
774 * @return {YUI} the YUI instance.
777 var args = SLICE.call(arguments, 0),
778 callback = args[args.length - 1],
786 // The last argument supplied to use can be a load complete callback
787 if (Y.Lang.isFunction(callback)) {
792 if (Y.Lang.isArray(args[0])) {
796 if (Y.config.cacheUse) {
797 while ((name = args[i++])) {
798 if (!Env._attached[name]) {
807 Y._notify(callback, ALREADY_DONE, args);
813 Y._useQueue = Y._useQueue || new Y.Queue();
814 Y._useQueue.add([args, callback]);
816 Y._use(args, function(Y, response) {
817 Y._notify(callback, response, args);
824 * Notify handler from Loader for attachment/load errors
826 * @param callback {Function} The callback to pass to the `Y.config.loadErrorFn`
827 * @param response {Object} The response returned from Loader
828 * @param args {Array} The aruments passed from Loader
831 _notify: function(callback, response, args) {
832 if (!response.success && this.config.loadErrorFn) {
833 this.config.loadErrorFn.call(this, this, callback, response, args);
834 } else if (callback) {
836 callback(this, response);
838 this.error('use callback error', e, args);
844 * This private method is called from the `use` method queue. To ensure that only one set of loading
845 * logic is performed at a time.
848 * @param args* {String} 1-n modules to bind (uses arguments array).
849 * @param *callback {Function} callback function executed when
850 * the instance has the required functionality. If included, it
851 * must be the last parameter.
853 _use: function(args, callback) {
856 this._attach(['yui-base']);
859 var len, loader, handleBoot, handleRLS,
865 aliases = G_ENV.aliases,
866 queue = G_ENV._loaderQueue,
870 boot = config.bootstrap,
874 fetchCSS = config.fetchCSS,
875 process = function(names, skip) {
884 for (i = 0; i < names.length; i++) {
885 if (aliases[names[i]]) {
886 a = [].concat(a, aliases[names[i]]);
894 YArray.each(names, function(name) {
896 // add this module to full list of things to attach
901 // only attach a module once
906 var m = mods[name], req, use;
910 req = m.details.requires;
913 // CSS files don't register themselves, see if it has
915 if (!G_ENV._loaded[VERSION][name]) {
918 used[name] = true; // probably css
922 // make sure requirements are attached
923 if (req && req.length) {
927 // make sure we grab the submodule dependencies too
928 if (use && use.length) {
934 handleLoader = function(fromLoader) {
935 var response = fromLoader || {
941 data = response.data;
946 origMissing = missing;
950 redo = missing.length;
952 if (missing.sort().join() ==
953 origMissing.sort().join()) {
961 Y._use(missing, function() {
962 if (Y._attach(data)) {
963 Y._notify(callback, response, data);
968 ret = Y._attach(data);
971 Y._notify(callback, response, args);
975 if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
976 Y._use.apply(Y, Y._useQueue.next());
982 // YUI().use('*'); // bind everything available
983 if (firstArg === '*') {
984 ret = Y._attach(Y.Object.keys(mods));
991 if (mods['loader'] && !Y.Loader) {
992 Y._attach(['loader']);
996 // use loader to expand dependencies and sort the
997 // requirements if it is available.
998 if (boot && Y.Loader && args.length) {
999 loader = getLoader(Y);
1000 loader.require(args);
1001 loader.ignoreRegistered = true;
1002 loader._boot = true;
1003 loader.calculate(null, (fetchCSS) ? null : 'js');
1004 args = loader.sorted;
1005 loader._boot = false;
1008 // process each requirement and any additional requirements
1009 // the module metadata specifies
1012 len = missing.length;
1015 missing = Y.Object.keys(YArray.hash(missing));
1016 len = missing.length;
1021 if (boot && len && Y.Loader) {
1023 loader = getLoader(Y);
1024 loader.onEnd = handleLoader;
1027 loader.ignoreRegistered = false;
1028 loader.require(args);
1029 loader.insert(null, (fetchCSS) ? null : 'js');
1031 } else if (boot && len && Y.Get && !Env.bootstrapped) {
1035 handleBoot = function() {
1037 queue.running = false;
1038 Env.bootstrapped = true;
1039 G_ENV._bootstrapping = false;
1040 if (Y._attach(['loader'])) {
1041 Y._use(args, callback);
1045 if (G_ENV._bootstrapping) {
1046 queue.add(handleBoot);
1048 G_ENV._bootstrapping = true;
1049 Y.Get.script(config.base + config.loaderPath, {
1055 ret = Y._attach(args);
1066 Adds a namespace object onto the YUI global if called statically.
1068 // creates YUI.your.namespace.here as nested objects
1069 YUI.namespace("your.namespace.here");
1071 If called as a method on a YUI <em>instance</em>, it creates the
1072 namespace on the instance.
1074 // creates Y.property.package
1075 Y.namespace("property.package");
1077 Dots in the input string cause `namespace` to create nested objects for
1078 each token. If any part of the requested namespace already exists, the
1079 current object will be left in place. This allows multiple calls to
1080 `namespace` to preserve existing namespaced properties.
1082 If the first token in the namespace string is "YAHOO", the token is
1085 Be careful with namespace tokens. Reserved words may work in some browsers
1086 and not others. For instance, the following will fail in some browsers
1087 because the supported version of JavaScript reserves the word "long":
1089 Y.namespace("really.long.nested.namespace");
1091 <em>Note: If you pass multiple arguments to create multiple namespaces, only
1092 the last one created is returned from this function.</em>
1095 @param {String} namespace* namespaces to create.
1096 @return {Object} A reference to the last namespace object created.
1098 namespace: function() {
1099 var a = arguments, o, i = 0, j, d, arg;
1101 for (; i < a.length; i++) {
1102 o = this; //Reset base object per argument or it will get reused from the last
1104 if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1105 d = arg.split(PERIOD);
1106 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1107 o[d[j]] = o[d[j]] || {};
1111 o[arg] = o[arg] || {};
1112 o = o[arg]; //Reset base object to the new object so it's returned
1118 // this is replaced if the log module is included
1121 // this is replaced if the dump module is included
1122 dump: function (o) { return ''+o; },
1125 * Report an error. The reporting mechanism is controlled by
1126 * the `throwFail` configuration attribute. If throwFail is
1127 * not specified, the message is written to the Logger, otherwise
1128 * a JS error is thrown. If an `errorFn` is specified in the config
1129 * it must return `true` to keep the error from being thrown.
1131 * @param msg {String} the error message.
1132 * @param e {Error|String} Optional JS error that was caught, or an error string.
1133 * @param src Optional additional info (passed to `Y.config.errorFn` and `Y.message`)
1134 * and `throwFail` is specified, this error will be re-thrown.
1135 * @return {YUI} this YUI instance.
1137 error: function(msg, e, src) {
1138 //TODO Add check for window.onerror here
1142 if (Y.config.errorFn) {
1143 ret = Y.config.errorFn.apply(Y, arguments);
1146 if (Y.config.throwFail && !ret) {
1147 throw (e || new Error(msg));
1149 Y.message(msg, 'error', ''+src); // don't scrub this one
1156 * Generate an id that is unique among all YUI instances
1158 * @param pre {String} optional guid prefix.
1159 * @return {String} the guid.
1161 guid: function(pre) {
1162 var id = this.Env._guidp + '_' + (++this.Env._uidx);
1163 return (pre) ? (pre + id) : id;
1167 * Returns a `guid` associated with an object. If the object
1168 * does not have one, a new one is created unless `readOnly`
1171 * @param o {Object} The object to stamp.
1172 * @param readOnly {Boolean} if `true`, a valid guid will only
1173 * be returned if the object has one assigned to it.
1174 * @return {String} The object's guid or null.
1176 stamp: function(o, readOnly) {
1182 // IE generates its own unique ID for dom nodes
1183 // The uniqueID property of a document node returns a new ID
1184 if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1187 uid = (typeof o === 'string') ? o : o._yuid;
1204 * Destroys the YUI instance
1208 destroy: function() {
1213 delete instances[Y.id];
1219 * instanceof check for objects that works around
1220 * memory leak in IE when the item tested is
1222 * @method instanceOf
1223 * @param o {Object} The object to check.
1224 * @param type {Object} The class to check against.
1229 YUI.prototype = proto;
1231 // inheritance utilities are not available yet
1232 for (prop in proto) {
1233 if (proto.hasOwnProperty(prop)) {
1234 YUI[prop] = proto[prop];
1239 Static method on the Global YUI object to apply a config to all YUI instances.
1240 It's main use case is "mashups" where several third party scripts are trying to write to
1241 a global YUI config at the same time. This way they can all call `YUI.applyConfig({})` instead of
1242 overwriting other scripts configs.
1246 @param {Object} o the configuration object.
1252 fullpath: './davglass.js'
1260 fullpath: './foo.js'
1265 YUI().use('davglass', function(Y) {
1266 //Module davglass will be available here..
1270 YUI.applyConfig = function(o) {
1274 //If there is a GlobalConfig, apply it first to set the defaults
1275 if (YUI.GlobalConfig) {
1276 this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1278 //Apply this config to it
1279 this.prototype.applyConfig.call(this, o);
1280 //Reset GlobalConfig to the combined config
1281 YUI.GlobalConfig = this.config;
1284 // set up the environment
1288 // add a window load event at load time so we can capture
1289 // the case where it fires before dynamic loading is
1291 add(window, 'load', handleLoad);
1297 YUI.Env.remove = remove;
1300 // Support the CommonJS method for exporting our single global
1301 if (typeof exports == 'object') {
1309 * The config object contains all of the configuration options for
1310 * the `YUI` instance. This object is supplied by the implementer
1311 * when instantiating a `YUI` instance. Some properties have default
1312 * values if they are not supplied by the implementer. This should
1313 * not be updated directly because some values are cached. Use
1314 * `applyConfig()` to update the config object on a YUI instance that
1315 * has already been configured.
1322 * Allows the YUI seed file to fetch the loader component and library
1323 * metadata to dynamically load additional dependencies.
1325 * @property bootstrap
1331 * Turns on writing Ylog messages to the browser console.
1339 * Log to the browser console if debug is on and the browser has a
1340 * supported console.
1342 * @property useBrowserConsole
1348 * A hash of log sources that should be logged. If specified, only
1349 * log messages from these sources will be logged.
1351 * @property logInclude
1356 * A hash of log sources that should be not be logged. If specified,
1357 * all sources are logged if not on this list.
1359 * @property logExclude
1364 * Set to true if the yui seed file was dynamically loaded in
1365 * order to bootstrap components relying on the window load event
1366 * and the `domready` custom event.
1368 * @property injected
1374 * If `throwFail` is set, `Y.error` will generate or re-throw a JS Error.
1375 * Otherwise the failure is logged.
1377 * @property throwFail
1383 * The window/frame that this instance should operate in.
1387 * @default the window hosting YUI
1391 * The document associated with the 'win' configuration.
1395 * @default the document hosting YUI
1399 * A list of modules that defines the YUI core (overrides the default list).
1403 * @default [ get,features,intl-base,yui-log,yui-later,loader-base, loader-rollup, loader-yui3 ]
1407 * A list of languages in order of preference. This list is matched against
1408 * the list of available languages in modules that the YUI instance uses to
1409 * determine the best possible localization of language sensitive modules.
1410 * Languages are represented using BCP 47 language tags, such as "en-GB" for
1411 * English as used in the United Kingdom, or "zh-Hans-CN" for simplified
1412 * Chinese as used in China. The list can be provided as a comma-separated
1413 * list or as an array.
1416 * @type string|string[]
1420 * The default date format
1421 * @property dateFormat
1423 * @deprecated use configuration in `DataType.Date.format()` instead.
1427 * The default locale
1430 * @deprecated use `config.lang` instead.
1434 * The default interval when polling in milliseconds.
1435 * @property pollInterval
1441 * The number of dynamic nodes to insert by default before
1442 * automatically removing them. This applies to script nodes
1443 * because removing the node will not make the evaluated script
1444 * unavailable. Dynamic CSS is not auto purged, because removing
1445 * a linked style sheet will also remove the style definitions.
1446 * @property purgethreshold
1452 * The default interval when polling in milliseconds.
1453 * @property windowResizeDelay
1459 * Base directory for dynamic loading
1465 * The secure base dir (not implemented)
1466 * For dynamic loading.
1467 * @property secureBase
1472 * The YUI combo service base dir. Ex: `http://yui.yahooapis.com/combo?`
1473 * For dynamic loading.
1474 * @property comboBase
1479 * The root path to prepend to module path for the combo service.
1480 * Ex: 3.0.0b1/build/
1481 * For dynamic loading.
1487 * A filter to apply to result urls. This filter will modify the default
1488 * path for all modules. The default path for the YUI library is the
1489 * minified version of the files (e.g., event-min.js). The filter property
1490 * can be a predefined filter or a custom filter. The valid predefined
1494 * <dd>Selects the debug versions of the library (e.g., event-debug.js).
1495 * This option will automatically include the Logger widget</dd>
1497 * <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
1499 * You can also define a custom filter, which must be an object literal
1500 * containing a search expression and a replace string:
1503 * 'searchExp': "-min\\.js",
1504 * 'replaceStr': "-debug.js"
1507 * For dynamic loading.
1510 * @type string|object
1514 * The `skin` config let's you configure application level skin
1515 * customizations. It contains the following attributes which
1516 * can be specified to override the defaults:
1518 * // The default skin, which is automatically applied if not
1519 * // overriden by a component-specific skin definition.
1520 * // Change this in to apply a different skin globally
1521 * defaultSkin: 'sam',
1523 * // This is combined with the loader base property to get
1524 * // the default root directory for a skin.
1525 * base: 'assets/skins/',
1527 * // Any component-specific overrides can be specified here,
1528 * // making it possible to load different skins for different
1529 * // components. It is possible to load more than one skin
1530 * // for a given component as well.
1532 * slider: ['capsule', 'round']
1535 * For dynamic loading.
1541 * Hash of per-component filter specification. If specified for a given
1542 * component, this overrides the filter config.
1544 * For dynamic loading.
1550 * Use the YUI combo service to reduce the number of http connections
1551 * required to load your dependencies. Turning this off will
1552 * disable combo handling for YUI and all module groups configured
1553 * with a combo service.
1555 * For dynamic loading.
1559 * @default true if 'base' is not supplied, false if it is.
1563 * A list of modules that should never be dynamically loaded
1570 * A list of modules that should always be loaded when required, even if already
1571 * present on the page.
1578 * Node or id for a node that should be used as the insertion point for new
1579 * nodes. For dynamic loading.
1581 * @property insertBefore
1586 * Object literal containing attributes to add to dynamically loaded script
1588 * @property jsAttributes
1593 * Object literal containing attributes to add to dynamically loaded link
1595 * @property cssAttributes
1600 * Number of milliseconds before a timeout occurs when dynamically
1601 * loading nodes. If not set, there is no timeout.
1607 * Callback for the 'CSSComplete' event. When dynamically loading YUI
1608 * components with CSS, this property fires when the CSS is finished
1609 * loading but script loading is still ongoing. This provides an
1610 * opportunity to enhance the presentation of a loading page a little
1611 * bit before the entire loading process is done.
1618 * A hash of module definitions to add to the list of YUI components.
1619 * These components can then be dynamically loaded side by side with
1620 * YUI via the `use()` method. This is a hash, the key is the module
1621 * name, and the value is an object literal specifying the metdata
1622 * for the module. See `Loader.addModule` for the supported module
1623 * metadata fields. Also see groups, which provides a way to
1624 * configure the base and combo spec for a set of modules.
1628 * requires: ['node'],
1629 * fullpath: '/mymod1/mymod1.js'
1632 * requires: ['mymod1'],
1633 * fullpath: '/mymod2/mymod2.js'
1635 * mymod3: '/js/mymod3.js',
1636 * mycssmod: '/css/mycssmod.css'
1645 * Aliases are dynamic groups of modules that can be used as
1650 * davglass: [ 'node', 'yql', 'dd' ],
1651 * mine: [ 'davglass', 'autocomplete']
1653 * }).use('mine', function(Y) {
1654 * //Node, YQL, DD & AutoComplete available here..
1662 * A hash of module group definitions. It for each group you
1663 * can specify a list of modules and the base path and
1664 * combo spec to use when dynamically loading the modules.
1668 * // specify whether or not this group has a combo service
1671 * // The comboSeperator to use with this group's combo handler
1674 * // The maxURLLength for this server
1675 * maxURLLength: 500,
1677 * // the base path for non-combo paths
1678 * base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1680 * // the path to the combo service
1681 * comboBase: 'http://yui.yahooapis.com/combo?',
1683 * // a fragment to prepend to the path attribute when
1684 * // when building combo urls
1685 * root: '2.8.0r4/build/',
1687 * // the module definitions
1690 * path: "yahoo-dom-event/yahoo-dom-event.js"
1693 * path: "animation/animation.js",
1694 * requires: ['yui2_yde']
1705 * The loader 'path' attribute to the loader itself. This is combined
1706 * with the 'base' attribute to dynamically load the loader component
1707 * when boostrapping with the get utility alone.
1709 * @property loaderPath
1711 * @default loader/loader-min.js
1715 * Specifies whether or not YUI().use(...) will attempt to load CSS
1716 * resources at all. Any truthy value will cause CSS dependencies
1717 * to load when fetching script. The special value 'force' will
1718 * cause CSS dependencies to be loaded even if no script is needed.
1720 * @property fetchCSS
1721 * @type boolean|string
1726 * The default gallery version to build gallery module urls
1733 * The default YUI 2 version to build yui2 module urls. This is for
1734 * intrinsic YUI 2 support via the 2in3 project. Also see the '2in3'
1735 * config for pulling different revisions of the wrapped YUI 2
1744 * The 2in3 project is a deployment of the various versions of YUI 2
1745 * deployed as first-class YUI 3 modules. Eventually, the wrapper
1746 * for the modules will change (but the underlying YUI 2 code will
1747 * be the same), and you can select a particular version of
1748 * the wrapper modules via this config.
1756 * Alternative console log function for use in environments without
1757 * a supported native console. The function is executed in the
1758 * YUI instance context.
1765 * A callback to execute when Y.error is called. It receives the
1766 * error message and an javascript error object if Y.error was
1767 * executed because a javascript error was caught. The function
1768 * is executed in the YUI instance context. Returning `true` from this
1769 * function will stop the Error from being thrown.
1777 * A callback to execute when the loader fails to load one or
1778 * more resource. This could be because of a script load
1779 * failure. It can also fail if a javascript module fails
1780 * to register itself, but only when the 'requireRegistration'
1781 * is true. If this function is defined, the use() callback will
1782 * only be called when the loader succeeds, otherwise it always
1783 * executes unless there was a javascript error when attaching
1787 * @property loadErrorFn
1792 * When set to true, the YUI loader will expect that all modules
1793 * it is responsible for loading will be first-class YUI modules
1794 * that register themselves with the YUI global. If this is
1795 * set to true, loader will fail if the module registration fails
1796 * to happen after the script is loaded.
1799 * @property requireRegistration
1805 * Cache serviced use() requests.
1807 * @property cacheUse
1810 * @deprecated no longer used
1814 * Whether or not YUI should use native ES5 functionality when available for
1815 * features like `Y.Array.each()`, `Y.Object()`, etc. When `false`, YUI will
1816 * always use its own fallback implementations instead of relying on ES5
1817 * functionality, even when it's available.
1819 * @method useNativeES5
1824 YUI.add('yui-base', function(Y) {
1829 * @submodule yui-base
1832 * The YUI module contains the components required for building the YUI
1833 * seed file. This includes the script loading mechanism, a simple queue,
1834 * and the core utilities for the library.
1836 * @submodule yui-base
1840 * Provides core language utilites and extensions used throughout YUI.
1846 var L = Y.Lang || (Y.Lang = {}),
1848 STRING_PROTO = String.prototype,
1849 TOSTRING = Object.prototype.toString,
1852 'undefined' : 'undefined',
1853 'number' : 'number',
1854 'boolean' : 'boolean',
1855 'string' : 'string',
1856 '[object Function]': 'function',
1857 '[object RegExp]' : 'regexp',
1858 '[object Array]' : 'array',
1859 '[object Date]' : 'date',
1860 '[object Error]' : 'error'
1863 SUBREGEX = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
1864 TRIMREGEX = /^\s+|\s+$/g,
1865 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i;
1867 // -- Protected Methods --------------------------------------------------------
1870 Returns `true` if the given function appears to be implemented in native code,
1871 `false` otherwise. Will always return `false` -- even in ES5-capable browsers --
1872 if the `useNativeES5` YUI config option is set to `false`.
1874 This isn't guaranteed to be 100% accurate and won't work for anything other than
1875 functions, but it can be useful for determining whether a function like
1876 `Array.prototype.forEach` is native or a JS shim provided by another library.
1878 There's a great article by @kangax discussing certain flaws with this technique:
1879 <http://perfectionkills.com/detecting-built-in-host-methods/>
1881 While his points are valid, it's still possible to benefit from this function
1882 as long as it's used carefully and sparingly, and in such a way that false
1883 negatives have minimal consequences. It's used internally to avoid using
1884 potentially broken non-native ES5 shims that have been added to the page by
1888 @param {Function} fn Function to test.
1889 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
1894 L._isNative = function (fn) {
1895 return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
1898 // -- Public Methods -----------------------------------------------------------
1901 * Determines whether or not the provided item is an array.
1903 * Returns `false` for array-like collections such as the function `arguments`
1904 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
1905 * test for an array-like collection.
1908 * @param o The object to test.
1909 * @return {boolean} true if o is an array.
1912 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
1913 return L.type(o) === 'array';
1917 * Determines whether or not the provided item is a boolean.
1920 * @param o The object to test.
1921 * @return {boolean} true if o is a boolean.
1923 L.isBoolean = function(o) {
1924 return typeof o === 'boolean';
1928 * Determines whether or not the supplied item is a date instance.
1931 * @param o The object to test.
1932 * @return {boolean} true if o is a date.
1934 L.isDate = function(o) {
1935 return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
1940 * Determines whether or not the provided item is a function.
1941 * Note: Internet Explorer thinks certain functions are objects:
1945 * var obj = document.createElement("object");
1946 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
1948 * var input = document.createElement("input"); // append to body
1949 * Y.Lang.isFunction(input.focus) // reports false in IE
1953 * You will have to implement additional tests if these functions
1957 * @method isFunction
1959 * @param o The object to test.
1960 * @return {boolean} true if o is a function.
1962 L.isFunction = function(o) {
1963 return L.type(o) === 'function';
1967 * Determines whether or not the provided item is null.
1970 * @param o The object to test.
1971 * @return {boolean} true if o is null.
1973 L.isNull = function(o) {
1978 * Determines whether or not the provided item is a legal number.
1981 * @param o The object to test.
1982 * @return {boolean} true if o is a number.
1984 L.isNumber = function(o) {
1985 return typeof o === 'number' && isFinite(o);
1989 * Determines whether or not the provided item is of type object
1990 * or function. Note that arrays are also objects, so
1991 * <code>Y.Lang.isObject([]) === true</code>.
1994 * @param o The object to test.
1995 * @param failfn {boolean} fail if the input is a function.
1996 * @return {boolean} true if o is an object.
1997 * @see isPlainObject
1999 L.isObject = function(o, failfn) {
2001 return (o && (t === 'object' ||
2002 (!failfn && (t === 'function' || L.isFunction(o))))) || false;
2006 * Determines whether or not the provided item is a string.
2009 * @param o The object to test.
2010 * @return {boolean} true if o is a string.
2012 L.isString = function(o) {
2013 return typeof o === 'string';
2017 * Determines whether or not the provided item is undefined.
2018 * @method isUndefined
2020 * @param o The object to test.
2021 * @return {boolean} true if o is undefined.
2023 L.isUndefined = function(o) {
2024 return typeof o === 'undefined';
2028 * A convenience method for detecting a legitimate non-null value.
2029 * Returns false for null/undefined/NaN, true for other values,
2030 * including 0/false/''
2033 * @param o The item to test.
2034 * @return {boolean} true if it is not null/undefined/NaN || false.
2036 L.isValue = function(o) {
2043 case 'null': // fallthru
2053 * Returns the current time in milliseconds.
2056 * @return {Number} Current time in milliseconds.
2060 L.now = Date.now || function () {
2061 return new Date().getTime();
2065 * Lightweight version of <code>Y.substitute</code>. Uses the same template
2066 * structure as <code>Y.substitute</code>, but doesn't support recursion,
2067 * auto-object coersion, or formats.
2069 * @param {string} s String to be modified.
2070 * @param {object} o Object containing replacement values.
2071 * @return {string} the substitute result.
2075 L.sub = function(s, o) {
2076 return s.replace ? s.replace(SUBREGEX, function (match, key) {
2077 return L.isUndefined(o[key]) ? match : o[key];
2082 * Returns a string without any leading or trailing whitespace. If
2083 * the input is not a string, the input will be returned untouched.
2086 * @param s {string} the string to trim.
2087 * @return {string} the trimmed string.
2089 L.trim = STRING_PROTO.trim ? function(s) {
2090 return s && s.trim ? s.trim() : s;
2093 return s.replace(TRIMREGEX, '');
2100 * Returns a string without any leading whitespace.
2103 * @param s {string} the string to trim.
2104 * @return {string} the trimmed string.
2106 L.trimLeft = STRING_PROTO.trimLeft ? function (s) {
2107 return s.trimLeft();
2109 return s.replace(/^\s+/, '');
2113 * Returns a string without any trailing whitespace.
2116 * @param s {string} the string to trim.
2117 * @return {string} the trimmed string.
2119 L.trimRight = STRING_PROTO.trimRight ? function (s) {
2120 return s.trimRight();
2122 return s.replace(/\s+$/, '');
2126 Returns one of the following strings, representing the type of the item passed
2143 * `typeof HTMLElementCollection` returns function in Safari, but
2144 `Y.Lang.type()` reports "object", which could be a good thing --
2145 but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2148 @param o the item to test.
2149 @return {string} the detected type.
2152 L.type = function(o) {
2153 return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2161 Native = Array.prototype,
2163 hasOwn = Object.prototype.hasOwnProperty;
2166 Provides utility methods for working with arrays. Additional array helpers can
2167 be found in the `collection` and `array-extras` modules.
2169 `Y.Array(thing)` returns a native array created from _thing_. Depending on
2170 _thing_'s type, one of the following will happen:
2172 * Arrays are returned unmodified unless a non-zero _startIndex_ is
2174 * Array-like collections (see `Array.test()`) are converted to arrays.
2175 * For everything else, a new array is created with _thing_ as the sole
2178 Note: elements that are also collections, such as `<form>` and `<select>`
2179 elements, are not automatically converted to arrays. To force a conversion,
2180 pass `true` as the value of the _force_ parameter.
2184 @param {Any} thing The thing to arrayify.
2185 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2186 collection, a subset of items starting at the specified index will be
2188 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2189 array-like collection no matter what.
2190 @return {Array} A native array created from _thing_, according to the rules
2193 function YArray(thing, startIndex, force) {
2196 startIndex || (startIndex = 0);
2198 if (force || YArray.test(thing)) {
2199 // IE throws when trying to slice HTMLElement collections.
2201 return Native.slice.call(thing, startIndex);
2205 for (len = thing.length; startIndex < len; ++startIndex) {
2206 result.push(thing[startIndex]);
2219 Dedupes an array of strings, returning an array that's guaranteed to contain
2220 only one copy of a given string.
2222 This method differs from `Array.unique()` in that it's optimized for use only
2223 with strings, whereas `unique` may be used with other types (but is slower).
2224 Using `dedupe()` with non-string values may result in unexpected behavior.
2227 @param {String[]} array Array of strings to dedupe.
2228 @return {Array} Deduped copy of _array_.
2232 YArray.dedupe = function (array) {
2237 for (i = 0, len = array.length; i < len; ++i) {
2240 if (!hasOwn.call(hash, item)) {
2250 Executes the supplied function on each item in the array. This method wraps
2251 the native ES5 `Array.forEach()` method if available.
2254 @param {Array} array Array to iterate.
2255 @param {Function} fn Function to execute on each item in the array. The function
2256 will receive the following arguments:
2257 @param {Any} fn.item Current array item.
2258 @param {Number} fn.index Current array index.
2259 @param {Array} fn.array Array being iterated.
2260 @param {Object} [thisObj] `this` object to use when calling _fn_.
2261 @return {YUI} The YUI instance.
2264 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2265 Native.forEach.call(array || [], fn, thisObj || Y);
2267 } : function (array, fn, thisObj) {
2268 for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2270 fn.call(thisObj || Y, array[i], i, array);
2285 Returns an object using the first array as keys and the second as values. If
2286 the second array is not provided, or if it doesn't contain the same number of
2287 values as the first array, then `true` will be used in place of the missing
2292 Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2293 // => {a: 'foo', b: 'bar', c: true}
2296 @param {String[]} keys Array of strings to use as keys.
2297 @param {Array} [values] Array to use as values.
2298 @return {Object} Hash using the first array as keys and the second as values.
2301 YArray.hash = function (keys, values) {
2303 vlen = (values && values.length) || 0,
2306 for (i = 0, len = keys.length; i < len; ++i) {
2308 hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2316 Returns the index of the first item in the array that's equal (using a strict
2317 equality check) to the specified _value_, or `-1` if the value isn't found.
2319 This method wraps the native ES5 `Array.indexOf()` method if available.
2322 @param {Array} array Array to search.
2323 @param {Any} value Value to search for.
2324 @param {Number} [from=0] The index at which to begin the search.
2325 @return {Number} Index of the item strictly equal to _value_, or `-1` if not
2329 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2330 return Native.indexOf.call(array, value, from);
2331 } : function (array, value, from) {
2332 // http://es5.github.com/#x15.4.4.14
2333 var len = array.length;
2336 from = (from > 0 || -1) * Math.floor(Math.abs(from));
2346 for (; from < len; ++from) {
2347 if (from in array && array[from] === value) {
2356 Numeric sort convenience function.
2358 The native `Array.prototype.sort()` function converts values to strings and
2359 sorts them in lexicographic order, which is unsuitable for sorting numeric
2360 values. Provide `Array.numericSort` as a custom sort function when you want
2361 to sort values in numeric order.
2365 [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2366 // => [4, 8, 15, 16, 23, 42]
2369 @param {Number} a First value to compare.
2370 @param {Number} b Second value to compare.
2371 @return {Number} Difference between _a_ and _b_.
2374 YArray.numericSort = function (a, b) {
2379 Executes the supplied function on each item in the array. Returning a truthy
2380 value from the function will stop the processing of remaining items.
2383 @param {Array} array Array to iterate over.
2384 @param {Function} fn Function to execute on each item. The function will receive
2385 the following arguments:
2386 @param {Any} fn.value Current array item.
2387 @param {Number} fn.index Current array index.
2388 @param {Array} fn.array Array being iterated over.
2389 @param {Object} [thisObj] `this` object to use when calling _fn_.
2390 @return {Boolean} `true` if the function returns a truthy value on any of the
2391 items in the array; `false` otherwise.
2394 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2395 return Native.some.call(array, fn, thisObj);
2396 } : function (array, fn, thisObj) {
2397 for (var i = 0, len = array.length; i < len; ++i) {
2398 if (i in array && fn.call(thisObj, array[i], i, array)) {
2407 Evaluates _obj_ to determine if it's an array, an array-like collection, or
2408 something else. This is useful when working with the function `arguments`
2409 collection and `HTMLElement` collections.
2411 Note: This implementation doesn't consider elements that are also
2412 collections, such as `<form>` and `<select>`, to be array-like.
2415 @param {Object} obj Object to test.
2416 @return {Number} A number indicating the results of the test:
2418 * 0: Neither an array nor an array-like collection.
2420 * 2: Array-like collection.
2424 YArray.test = function (obj) {
2427 if (Lang.isArray(obj)) {
2429 } else if (Lang.isObject(obj)) {
2431 // indexed, but no tagName (element) or alert (window),
2432 // or functions without apply/call (Safari
2433 // HTMLElementCollection bug).
2434 if ('length' in obj && !obj.tagName && !obj.alert && !obj.apply) {
2443 * The YUI module contains the components required for building the YUI
2444 * seed file. This includes the script loading mechanism, a simple queue,
2445 * and the core utilities for the library.
2447 * @submodule yui-base
2451 * A simple FIFO queue. Items are added to the Queue with add(1..n items) and
2452 * removed using next().
2456 * @param {MIXED} item* 0..n items to seed the queue.
2460 this.add.apply(this, arguments);
2465 * Initialize the queue
2472 * The collection of enqueued items
2482 * Get the next item in the queue. FIFO support
2485 * @return {MIXED} the next item in the queue.
2488 return this._q.shift();
2492 * Get the last in the queue. LIFO support.
2495 * @return {MIXED} the last item in the queue.
2498 return this._q.pop();
2502 * Add 0..n items to the end of the queue.
2505 * @param {MIXED} item* 0..n items.
2506 * @return {object} this queue.
2509 this._q.push.apply(this._q, arguments);
2515 * Returns the current number of queued items.
2518 * @return {Number} The size.
2521 return this._q.length;
2527 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2530 The YUI module contains the components required for building the YUI seed file.
2531 This includes the script loading mechanism, a simple queue, and the core
2532 utilities for the library.
2538 var CACHED_DELIMITER = '__',
2540 hasOwn = Object.prototype.hasOwnProperty,
2541 isObject = Y.Lang.isObject;
2544 Returns a wrapper for a function which caches the return value of that function,
2545 keyed off of the combined string representation of the argument values provided
2546 when the wrapper is called.
2548 Calling this function again with the same arguments will return the cached value
2549 rather than executing the wrapped function.
2551 Note that since the cache is keyed off of the string representation of arguments
2552 passed to the wrapper function, arguments that aren't strings and don't provide
2553 a meaningful `toString()` method may result in unexpected caching behavior. For
2554 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2555 string `[object Object]` when used as a cache key.
2558 @param {Function} source The function to memoize.
2559 @param {Object} [cache={}] Object in which to store cached values. You may seed
2560 this object with pre-existing cached values if desired.
2561 @param {any} [refetch] If supplied, this value is compared with the cached value
2562 using a `==` comparison. If the values are equal, the wrapped function is
2563 executed again even though a cached value exists.
2564 @return {Function} Wrapped function.
2567 Y.cached = function (source, cache, refetch) {
2568 cache || (cache = {});
2570 return function (arg) {
2571 var key = arguments.length > 1 ?
2572 Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2575 if (!(key in cache) || (refetch && cache[key] == refetch)) {
2576 cache[key] = source.apply(source, arguments);
2584 Returns the `location` object from the window/frame in which this YUI instance
2585 operates, or `undefined` when executing in a non-browser environment
2588 It is _not_ recommended to hold references to the `window.location` object
2589 outside of the scope of a function in which its properties are being accessed or
2590 its methods are being called. This is because of a nasty bug/issue that exists
2591 in both Safari and MobileSafari browsers:
2592 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2595 @return {location} The `location` object from the window/frame in which this YUI
2599 Y.getLocation = function () {
2600 // It is safer to look this up every time because yui-base is attached to a
2601 // YUI instance before a user's config is applied; i.e. `Y.config.win` does
2602 // not point the correct window object when this file is loaded.
2603 var win = Y.config.win;
2605 // It is not safe to hold a reference to the `location` object outside the
2606 // scope in which it is being used. The WebKit engine used in Safari and
2607 // MobileSafari will "disconnect" the `location` object from the `window`
2608 // when a page is restored from back/forward history cache.
2609 return win && win.location;
2613 Returns a new object containing all of the properties of all the supplied
2614 objects. The properties from later objects will overwrite those in earlier
2617 Passing in a single object will create a shallow copy of it. For a deep copy,
2621 @param {Object} objects* One or more objects to merge.
2622 @return {Object} A new merged object.
2624 Y.merge = function () {
2625 var args = arguments,
2630 for (; i < len; ++i) {
2631 Y.mix(result, args[i], true);
2638 Mixes _supplier_'s properties into _receiver_.
2640 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2641 shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2642 unless the _merge_ parameter is `true`.
2644 In the default mode (0), only properties the supplier owns are copied (prototype
2645 properties are not copied). The following copying modes are available:
2647 * `0`: _Default_. Object to object.
2648 * `1`: Prototype to prototype.
2649 * `2`: Prototype to prototype and object to object.
2650 * `3`: Prototype to object.
2651 * `4`: Object to prototype.
2654 @param {Function|Object} receiver The object or function to receive the mixed
2656 @param {Function|Object} supplier The object or function supplying the
2657 properties to be mixed.
2658 @param {Boolean} [overwrite=false] If `true`, properties that already exist
2659 on the receiver will be overwritten with properties from the supplier.
2660 @param {String[]} [whitelist] An array of property names to copy. If
2661 specified, only the whitelisted properties will be copied, and all others
2663 @param {Number} [mode=0] Mix mode to use. See above for available modes.
2664 @param {Boolean} [merge=false] If `true`, objects and arrays that already
2665 exist on the receiver will have the corresponding object/array from the
2666 supplier merged into them, rather than being skipped or overwritten. When
2667 both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
2668 @return {Function|Object|YUI} The receiver, or the YUI instance if the
2669 specified receiver is falsy.
2671 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
2672 var alwaysOverwrite, exists, from, i, key, len, to;
2674 // If no supplier is given, we return the receiver. If no receiver is given,
2675 // we return Y. Returning Y doesn't make much sense to me, but it's
2676 // grandfathered in for backcompat reasons.
2677 if (!receiver || !supplier) {
2678 return receiver || Y;
2682 // In mode 2 (prototype to prototype and object to object), we recurse
2683 // once to do the proto to proto mix. The object to object mix will be
2684 // handled later on.
2686 Y.mix(receiver.prototype, supplier.prototype, overwrite,
2687 whitelist, 0, merge);
2690 // Depending on which mode is specified, we may be copying from or to
2691 // the prototypes of the supplier and receiver.
2692 from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
2693 to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
2695 // If either the supplier or receiver doesn't actually have a
2696 // prototype property, then we could end up with an undefined `from`
2697 // or `to`. If that happens, we abort and return the receiver.
2706 // If `overwrite` is truthy and `merge` is falsy, then we can skip a
2707 // property existence check on each iteration and save some time.
2708 alwaysOverwrite = overwrite && !merge;
2711 for (i = 0, len = whitelist.length; i < len; ++i) {
2714 // We call `Object.prototype.hasOwnProperty` instead of calling
2715 // `hasOwnProperty` on the object itself, since the object's
2716 // `hasOwnProperty` method may have been overridden or removed.
2717 // Also, some native objects don't implement a `hasOwnProperty`
2719 if (!hasOwn.call(from, key)) {
2723 // The `key in to` check here is (sadly) intentional for backwards
2724 // compatibility reasons. It prevents undesired shadowing of
2725 // prototype members on `to`.
2726 exists = alwaysOverwrite ? false : key in to;
2728 if (merge && exists && isObject(to[key], true)
2729 && isObject(from[key], true)) {
2730 // If we're in merge mode, and the key is present on both
2731 // objects, and the value on both objects is either an object or
2732 // an array (but not a function), then we recurse to merge the
2733 // `from` value into the `to` value instead of overwriting it.
2735 // Note: It's intentional that the whitelist isn't passed to the
2736 // recursive call here. This is legacy behavior that lots of
2737 // code still depends on.
2738 Y.mix(to[key], from[key], overwrite, null, 0, merge);
2739 } else if (overwrite || !exists) {
2740 // We're not in merge mode, so we'll only copy the `from` value
2741 // to the `to` value if we're in overwrite mode or if the
2742 // current key doesn't exist on the `to` object.
2743 to[key] = from[key];
2748 // The code duplication here is for runtime performance reasons.
2749 // Combining whitelist and non-whitelist operations into a single
2750 // loop or breaking the shared logic out into a function both result
2751 // in worse performance, and Y.mix is critical enough that the byte
2752 // tradeoff is worth it.
2753 if (!hasOwn.call(from, key)) {
2757 // The `key in to` check here is (sadly) intentional for backwards
2758 // compatibility reasons. It prevents undesired shadowing of
2759 // prototype members on `to`.
2760 exists = alwaysOverwrite ? false : key in to;
2762 if (merge && exists && isObject(to[key], true)
2763 && isObject(from[key], true)) {
2764 Y.mix(to[key], from[key], overwrite, null, 0, merge);
2765 } else if (overwrite || !exists) {
2766 to[key] = from[key];
2770 // If this is an IE browser with the JScript enumeration bug, force
2771 // enumeration of the buggy properties by making a recursive call with
2772 // the buggy properties as the whitelist.
2773 if (Y.Object._hasEnumBug) {
2774 Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
2781 * The YUI module contains the components required for building the YUI
2782 * seed file. This includes the script loading mechanism, a simple queue,
2783 * and the core utilities for the library.
2785 * @submodule yui-base
2789 * Adds utilities to the YUI instance for working with objects.
2795 hasOwn = Object.prototype.hasOwnProperty,
2797 UNDEFINED, // <-- Note the comma. We're still declaring vars.
2800 * Returns a new object that uses _obj_ as its prototype. This method wraps the
2801 * native ES5 `Object.create()` method if available, but doesn't currently
2802 * pass through `Object.create()`'s second argument (properties) in order to
2803 * ensure compatibility with older browsers.
2806 * @param {Object} obj Prototype object.
2807 * @return {Object} New object using _obj_ as its prototype.
2810 O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
2811 // We currently wrap the native Object.create instead of simply aliasing it
2812 // to ensure consistency with our fallback shim, which currently doesn't
2813 // support Object.create()'s second argument (properties). Once we have a
2814 // safe fallback for the properties arg, we can stop wrapping
2816 return Object.create(obj);
2818 // Reusable constructor function for the Object.create() shim.
2822 return function (obj) {
2829 * Property names that IE doesn't enumerate in for..in loops, even when they
2830 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
2831 * manually enumerate these properties.
2833 * @property _forceEnum
2838 forceEnum = O._forceEnum = [
2841 'propertyIsEnumerable',
2848 * `true` if this browser has the JScript enumeration bug that prevents
2849 * enumeration of the properties named in the `_forceEnum` array, `false`
2853 * - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
2854 * - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
2856 * @property _hasEnumBug
2861 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
2864 * `true` if this browser incorrectly considers the `prototype` property of
2865 * functions to be enumerable. Currently known to affect Opera 11.50.
2867 * @property _hasProtoEnumBug
2872 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
2875 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
2876 * exists only on _obj_'s prototype. This is essentially a safer version of
2877 * `obj.hasOwnProperty()`.
2880 * @param {Object} obj Object to test.
2881 * @param {String} key Property name to look for.
2882 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2885 owns = O.owns = function (obj, key) {
2886 return !!obj && hasOwn.call(obj, key);
2887 }; // <-- End of var declarations.
2890 * Alias for `owns()`.
2893 * @param {Object} obj Object to test.
2894 * @param {String} key Property name to look for.
2895 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2901 * Returns an array containing the object's enumerable keys. Does not include
2902 * prototype keys or non-enumerable keys.
2904 * Note that keys are returned in enumeration order (that is, in the same order
2905 * that they would be enumerated by a `for-in` loop), which may not be the same
2906 * as the order in which they were defined.
2908 * This method is an alias for the native ES5 `Object.keys()` method if
2913 * Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
2914 * // => ['a', 'b', 'c']
2917 * @param {Object} obj An object.
2918 * @return {String[]} Array of keys.
2921 O.keys = Lang._isNative(Object.keys) ? Object.keys : function (obj) {
2922 if (!Lang.isObject(obj)) {
2923 throw new TypeError('Object.keys called on a non-object');
2929 if (hasProtoEnumBug && typeof obj === 'function') {
2931 if (owns(obj, key) && key !== 'prototype') {
2937 if (owns(obj, key)) {
2944 for (i = 0, len = forceEnum.length; i < len; ++i) {
2947 if (owns(obj, key)) {
2957 * Returns an array containing the values of the object's enumerable keys.
2959 * Note that values are returned in enumeration order (that is, in the same
2960 * order that they would be enumerated by a `for-in` loop), which may not be the
2961 * same as the order in which they were defined.
2965 * Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
2966 * // => ['foo', 'bar', 'baz']
2969 * @param {Object} obj An object.
2970 * @return {Array} Array of values.
2973 O.values = function (obj) {
2974 var keys = O.keys(obj),
2979 for (; i < len; ++i) {
2980 values.push(obj[keys[i]]);
2987 * Returns the number of enumerable keys owned by an object.
2990 * @param {Object} obj An object.
2991 * @return {Number} The object's size.
2994 O.size = function (obj) {
2996 return O.keys(obj).length;
2998 return 0; // Legacy behavior for non-objects.
3003 * Returns `true` if the object owns an enumerable property with the specified
3007 * @param {Object} obj An object.
3008 * @param {any} value The value to search for.
3009 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3012 O.hasValue = function (obj, value) {
3013 return Y.Array.indexOf(O.values(obj), value) > -1;
3017 * Executes a function on each enumerable property in _obj_. The function
3018 * receives the value, the key, and the object itself as parameters (in that
3021 * By default, only properties owned by _obj_ are enumerated. To include
3022 * prototype properties, set the _proto_ parameter to `true`.
3025 * @param {Object} obj Object to enumerate.
3026 * @param {Function} fn Function to execute on each enumerable property.
3027 * @param {mixed} fn.value Value of the current property.
3028 * @param {String} fn.key Key of the current property.
3029 * @param {Object} fn.obj Object being enumerated.
3030 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3031 * @param {Boolean} [proto=false] Include prototype properties.
3032 * @return {YUI} the YUI instance.
3036 O.each = function (obj, fn, thisObj, proto) {
3040 if (proto || owns(obj, key)) {
3041 fn.call(thisObj || Y, obj[key], key, obj);
3049 * Executes a function on each enumerable property in _obj_, but halts if the
3050 * function returns a truthy value. The function receives the value, the key,
3051 * and the object itself as paramters (in that order).
3053 * By default, only properties owned by _obj_ are enumerated. To include
3054 * prototype properties, set the _proto_ parameter to `true`.
3057 * @param {Object} obj Object to enumerate.
3058 * @param {Function} fn Function to execute on each enumerable property.
3059 * @param {mixed} fn.value Value of the current property.
3060 * @param {String} fn.key Key of the current property.
3061 * @param {Object} fn.obj Object being enumerated.
3062 * @param {Object} [thisObj] `this` object to use when calling _fn_.
3063 * @param {Boolean} [proto=false] Include prototype properties.
3064 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3065 * `false` otherwise.
3068 O.some = function (obj, fn, thisObj, proto) {
3072 if (proto || owns(obj, key)) {
3073 if (fn.call(thisObj || Y, obj[key], key, obj)) {
3083 * Retrieves the sub value at the provided path,
3084 * from the value object provided.
3088 * @param o The object from which to extract the property value.
3089 * @param path {Array} A path array, specifying the object traversal path
3090 * from which to obtain the sub value.
3091 * @return {Any} The value stored in the path, undefined if not found,
3092 * undefined if the source is not an object. Returns the source object
3093 * if an empty path is provided.
3095 O.getValue = function(o, path) {
3096 if (!Lang.isObject(o)) {
3104 for (i = 0; o !== UNDEFINED && i < l; i++) {
3112 * Sets the sub-attribute value at the provided path on the
3113 * value object. Returns the modified value object, or
3114 * undefined if the path is invalid.
3118 * @param o The object on which to set the sub value.
3119 * @param path {Array} A path array, specifying the object traversal path
3120 * at which to set the sub value.
3121 * @param val {Any} The new value for the sub-attribute.
3122 * @return {Object} The modified object, with the new sub value set, or
3123 * undefined, if the path was invalid.
3125 O.setValue = function(o, path, val) {
3128 leafIdx = p.length - 1,
3132 for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3136 if (ref !== UNDEFINED) {
3147 * Returns `true` if the object has no enumerable properties of its own.
3150 * @param {Object} obj An object.
3151 * @return {Boolean} `true` if the object is empty.
3155 O.isEmpty = function (obj) {
3156 return !O.keys(Object(obj)).length;
3159 * The YUI module contains the components required for building the YUI seed
3160 * file. This includes the script loading mechanism, a simple queue, and the
3161 * core utilities for the library.
3163 * @submodule yui-base
3167 * YUI user agent detection.
3168 * Do not fork for a browser if it can be avoided. Use feature detection when
3169 * you can. Use the user agent as a last resort. For all fields listed
3170 * as @type float, UA stores a version number for the browser engine,
3171 * 0 otherwise. This value may or may not map to the version number of
3172 * the browser using the engine. The value is presented as a float so
3173 * that it can easily be used for boolean evaluation as well as for
3174 * looking for a particular range of versions. Because of this,
3175 * some of the granularity of the version info may be lost. The fields that
3176 * are @type string default to null. The API docs list the values that
3177 * these fields can have.
3183 * Static method on `YUI.Env` for parsing a UA string. Called at instantiation
3184 * to populate `Y.UA`.
3188 * @param {String} [subUA=navigator.userAgent] UA string to parse
3189 * @return {Object} The Y.UA object
3191 YUI.Env.parseUA = function(subUA) {
3193 var numberify = function(s) {
3195 return parseFloat(s.replace(/\./g, function() {
3196 return (c++ == 1) ? '' : '.';
3202 nav = win && win.navigator,
3207 * Internet Explorer version number or 0. Example: 6
3215 * Opera version number or 0. Example: 9.2
3223 * Gecko engine revision number. Will evaluate to 1 if Gecko
3224 * is detected but the revision could not be found. Other browsers
3225 * will be 0. Example: 1.8
3227 * Firefox 1.0.0.4: 1.7.8 <-- Reports 1.7
3228 * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3229 * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3230 * Firefox 3.0 <-- 1.9
3231 * Firefox 3.5 <-- 1.91
3240 * AppleWebKit version. KHTML browsers that are not WebKit browsers
3241 * will evaluate to 1, other browsers 0. Example: 418.9
3243 * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3244 * latest available for Mac OSX 10.3.
3245 * Safari 2.0.2: 416 <-- hasOwnProperty introduced
3246 * Safari 2.0.4: 418 <-- preventDefault fixed
3247 * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3248 * different versions of webkit
3249 * Safari 2.0.4 (419.3): 419 <-- Tiger installations that have been
3250 * updated, but not updated
3251 * to the latest patch.
3252 * Webkit 212 nightly: 522+ <-- Safari 3.0 precursor (with native
3253 * SVG and many major issues fixed).
3254 * Safari 3.0.4 (523.12) 523.12 <-- First Tiger release - automatic
3255 * update from 2.x via the 10.4.11 OS patch.
3256 * Webkit nightly 1/2008:525+ <-- Supports DOMContentLoaded event.
3257 * yahoo.com user agent hack removed.
3259 * http://en.wikipedia.org/wiki/Safari_version_history
3267 * Safari will be detected as webkit, but this property will also
3268 * be populated with the Safari version number
3276 * Chrome will be detected as webkit, but this property will also
3277 * be populated with the Chrome version number
3285 * The mobile property will be set to a string containing any relevant
3286 * user agent information when a modern mobile browser is detected.
3287 * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3288 * devices with the WebKit-based browser, and Opera Mini.
3297 * Adobe AIR version number or 0. Only populated if webkit is detected.
3304 * Detects Apple iPad's OS version
3311 * Detects Apple iPhone's OS version
3318 * Detects Apples iPod's OS version
3325 * General truthy check for iPad, iPhone or iPod
3333 * Detects Googles Android OS version
3340 * Detects Kindle Silk
3347 * Detects Kindle Silk Acceleration
3354 * Detects Palms WebOS version
3362 * Google Caja version number or 0.
3366 caja: nav && nav.cajaVersion,
3369 * Set to true if the page appears to be in SSL
3377 * The operating system. Currently only detecting windows or macintosh
3386 * The Nodejs Version
3395 ua = subUA || nav && nav.userAgent,
3397 loc = win && win.location,
3399 href = loc && loc.href,
3404 * The User Agent string that was parsed
3405 * @property userAgent
3412 o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3416 if ((/windows|win32/i).test(ua)) {
3418 } else if ((/macintosh|mac_powerpc/i).test(ua)) {
3420 } else if ((/android/i).test(ua)) {
3422 } else if ((/symbos/i).test(ua)) {
3424 } else if ((/linux/i).test(ua)) {
3426 } else if ((/rhino/i).test(ua)) {
3430 // Modern KHTML browsers should qualify as Safari X-Grade
3431 if ((/KHTML/).test(ua)) {
3434 if ((/IEMobile|XBLWP7/).test(ua)) {
3435 o.mobile = 'windows';
3437 if ((/Fennec/).test(ua)) {
3440 // Modern WebKit browsers are at least X-Grade
3441 m = ua.match(/AppleWebKit\/([^\s]*)/);
3443 o.webkit = numberify(m[1]);
3444 o.safari = o.webkit;
3446 // Mobile browser check
3447 if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3448 o.mobile = 'Apple'; // iPhone or iPod Touch
3450 m = ua.match(/OS ([^\s]*)/);
3452 m = numberify(m[1].replace('_', '.'));
3456 o.ipad = o.ipod = o.iphone = 0;
3458 m = ua.match(/iPad|iPod|iPhone/);
3460 o[m[0].toLowerCase()] = o.ios;
3463 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3465 // Nokia N-series, webOS, ex: NokiaN95
3468 if (/webOS/.test(ua)) {
3470 m = ua.match(/webOS\/([^\s]*);/);
3472 o.webos = numberify(m[1]);
3475 if (/ Android/.test(ua)) {
3476 if (/Mobile/.test(ua)) {
3477 o.mobile = 'Android';
3479 m = ua.match(/Android ([^\s]*);/);
3481 o.android = numberify(m[1]);
3485 if (/Silk/.test(ua)) {
3486 m = ua.match(/Silk\/([^\s]*)\)/);
3488 o.silk = numberify(m[1]);
3491 o.android = 2.34; //Hack for desktop mode in Kindle
3494 if (/Accelerated=true/.test(ua)) {
3500 m = ua.match(/(Chrome|CrMo)\/([^\s]*)/);
3501 if (m && m[1] && m[2]) {
3502 o.chrome = numberify(m[2]); // Chrome
3503 o.safari = 0; //Reset safari back to 0
3504 if (m[1] === 'CrMo') {
3505 o.mobile = 'chrome';
3508 m = ua.match(/AdobeAIR\/([^\s]*)/);
3510 o.air = m[0]; // Adobe AIR 1.0 or better
3515 if (!o.webkit) { // not webkit
3516 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3517 if (/Opera/.test(ua)) {
3518 m = ua.match(/Opera[\s\/]([^\s]*)/);
3520 o.opera = numberify(m[1]);
3522 m = ua.match(/Version\/([^\s]*)/);
3524 o.opera = numberify(m[1]); // opera 10+
3527 if (/Opera Mobi/.test(ua)) {
3529 m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3531 o.opera = numberify(m[1]);
3534 m = ua.match(/Opera Mini[^;]*/);
3537 o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3539 } else { // not opera or webkit
3540 m = ua.match(/MSIE\s([^;]*)/);
3542 o.ie = numberify(m[1]);
3543 } else { // not opera, webkit, or ie
3544 m = ua.match(/Gecko\/([^\s]*)/);
3546 o.gecko = 1; // Gecko detected, look for revision
3547 m = ua.match(/rv:([^\s\)]*)/);
3549 o.gecko = numberify(m[1]);
3557 //It was a parsed UA, do not assign the global value.
3560 if (typeof process == 'object') {
3562 if (process.versions && process.versions.node) {
3564 o.os = process.platform;
3565 o.nodejs = process.versions.node;
3577 Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3580 Performs a simple comparison between two version numbers, accounting for
3581 standard versioning logic such as the fact that "535.8" is a lower version than
3582 "535.24", even though a simple numerical comparison would indicate that it's
3583 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3584 considered equivalent.
3586 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3587 1 if _a_ is higher than _b_.
3589 Versions may be numbers or strings containing numbers and dots. For example,
3590 both `535` and `"535.8.10"` are acceptable. A version string containing
3591 non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3593 @method compareVersions
3594 @param {Number|String} a First version number to compare.
3595 @param {Number|String} b Second version number to compare.
3596 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3599 Y.UA.compareVersions = function (a, b) {
3600 var aPart, aParts, bPart, bParts, i, len;
3606 aParts = (a + '').split('.');
3607 bParts = (b + '').split('.');
3609 for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3610 aPart = parseInt(aParts[i], 10);
3611 bPart = parseInt(bParts[i], 10);
3613 isNaN(aPart) && (aPart = 0);
3614 isNaN(bPart) && (bPart = 0);
3616 if (aPart < bPart) {
3620 if (aPart > bPart) {
3628 "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
3629 "app": ["app-base","app-transitions","model","model-list","router","view"],
3630 "attribute": ["attribute-base","attribute-complex"],
3631 "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
3632 "base": ["base-base","base-pluginhost","base-build"],
3633 "cache": ["cache-base","cache-offline","cache-plugin"],
3634 "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
3635 "controller": ["router"],
3636 "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
3637 "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
3638 "datatable": ["datatable-core","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
3639 "datatable-deprecated": ["datatable-base-deprecated","datatable-datasource-deprecated","datatable-sort-deprecated","datatable-scroll-deprecated"],
3640 "datatype": ["datatype-number","datatype-date","datatype-xml"],
3641 "datatype-date": ["datatype-date-parse","datatype-date-format"],
3642 "datatype-number": ["datatype-number-parse","datatype-number-format"],
3643 "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
3644 "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
3645 "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
3646 "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
3647 "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange"],
3648 "event-custom": ["event-custom-base","event-custom-complex"],
3649 "event-gestures": ["event-flick","event-move"],
3650 "handlebars": ["handlebars-compiler"],
3651 "highlight": ["highlight-base","highlight-accentfold"],
3652 "history": ["history-base","history-hash","history-hash-ie","history-html5"],
3653 "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
3654 "json": ["json-parse","json-stringify"],
3655 "loader": ["loader-base","loader-rollup","loader-yui3"],
3656 "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
3657 "pluginhost": ["pluginhost-base","pluginhost-config"],
3658 "querystring": ["querystring-parse","querystring-stringify"],
3659 "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
3660 "resize": ["resize-base","resize-proxy","resize-constrain"],
3661 "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
3662 "text": ["text-accentfold","text-wordbreak"],
3663 "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
3668 YUI.add('get', function(Y) {
3671 * NodeJS specific Get module used to load remote resources. It contains the same signature as the default Get module so there is no code change needed.
3672 * @module get-nodejs
3676 var path = require('path'),
3679 request = require('request');
3682 Y.Get = function() {
3685 //Setup the default config base path
3686 Y.config.base = path.join(__dirname, '../');
3688 YUI.require = require;
3689 YUI.process = process;
3692 * Escape the path for Windows, they need to be double encoded when used as `__dirname` or `__filename`
3693 * @method escapeWinPath
3695 * @param {String} p The path to modify
3696 * @return {String} The encoded path
3698 var escapeWinPath = function(p) {
3699 return p.replace(/\\/g, '\\\\');
3703 * Takes the raw JS files and wraps them to be executed in the YUI context so they can be loaded
3704 * into the YUI object
3707 * @param {String} data The JS to execute
3708 * @param {String} url The path to the file that was parsed
3709 * @param {Callback} cb The callback to execute when this is completed
3710 * @param {Error} cb.err=null Error object
3711 * @param {String} cb.url The URL that was just parsed
3714 Y.Get._exec = function(data, url, cb) {
3715 var dirName = escapeWinPath(path.dirname(url));
3716 var fileName = escapeWinPath(url);
3718 if (dirName.match(/^https?:\/\//)) {
3720 fileName = 'remoteResource';
3723 var mod = "(function(YUI) { var __dirname = '" + dirName + "'; "+
3724 "var __filename = '" + fileName + "'; " +
3725 "var process = YUI.process;" +
3726 "var require = function(file) {" +
3727 " if (file.indexOf('./') === 0) {" +
3728 " file = __dirname + file.replace('./', '/'); }" +
3729 " return YUI.require(file); }; " +
3730 data + " ;return YUI; })";
3732 //var mod = "(function(YUI) { " + data + ";return YUI; })";
3733 var script = vm.createScript(mod, url);
3734 var fn = script.runInThisContext(mod);
3740 * Fetches the content from a remote URL or a file from disc and passes the content
3741 * off to `_exec` for parsing
3744 * @param {String} url The URL/File path to fetch the content from
3745 * @param {Callback} cb The callback to fire once the content has been executed via `_exec`
3747 Y.Get._include = function(url, cb) {
3750 if (url.match(/^https?:\/\//)) {
3753 timeout: self.timeout
3755 request(cfg, function (err, response, body) {
3759 Y.Get._exec(body, url, cb);
3763 if (Y.config.useSync) {
3764 //Needs to be in useSync
3765 if (path.existsSync(url)) {
3766 var mod = fs.readFileSync(url,'utf8');
3767 Y.Get._exec(mod, url, cb);
3769 cb('Path does not exist: ' + url, url);
3772 fs.readFile(url, 'utf8', function(err, mod) {
3776 Y.Get._exec(mod, url, cb);
3785 var end = function(cb, msg, result) {
3786 if (Y.Lang.isFunction(cb.onEnd)) {
3787 cb.onEnd.call(Y, msg, result);
3789 }, pass = function(cb) {
3790 if (Y.Lang.isFunction(cb.onSuccess)) {
3791 cb.onSuccess.call(Y, cb);
3793 end(cb, 'success', 'success');
3794 }, fail = function(cb, er) {
3795 if (Y.Lang.isFunction(cb.onFailure)) {
3796 cb.onFailure.call(Y, er, cb);
3798 end(cb, er, 'fail');
3803 * Override for Get.script for loading local or remote YUI modules.
3805 * @param {Array|String} s The URL's to load into this context
3806 * @param {Object} options Transaction options
3808 Y.Get.js = function(s, options) {
3811 urls = A(s), url, i, l = urls.length, c= 0,
3812 check = function() {
3820 for (i=0; i<l; i++) {
3822 if (Y.Lang.isObject(url)) {
3826 url = url.replace(/'/g, '%27');
3827 Y.Get._include(url, function(err, url) {
3833 if (options.onProgress) {
3834 options.onProgress.call(options.context || Y, url);
3847 * Alias for `Y.Get.js`
3850 Y.Get.script = Y.Get.js;
3852 //Place holder for SS Dom access
3853 Y.Get.css = function(s, cb) {
3859 }, '3.5.1' ,{requires:['yui-base']});
3860 YUI.add('features', function(Y) {
3862 var feature_tests = {};
3865 Contains the core of YUI's feature test architecture.
3875 Y.mix(Y.namespace('Features'), {
3878 * Object hash of all registered feature tests
3882 tests: feature_tests,
3885 * Add a test to the system
3888 * Y.Features.add("load", "1", {});
3892 * @param {String} cat The category, right now only 'load' is supported
3893 * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
3894 * @param {Object} o Object containing test properties
3895 * @param {String} o.name The name of the test
3896 * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
3897 * @param {String} o.trigger The module that triggers this test.
3899 add: function(cat, name, o) {
3900 feature_tests[cat] = feature_tests[cat] || {};
3901 feature_tests[cat][name] = o;
3904 * Execute all tests of a given category and return the serialized results
3910 * @param {String} cat The category to execute
3911 * @param {Array} args The arguments to pass to the test function
3912 * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
3914 all: function(cat, args) {
3915 var cat_o = feature_tests[cat],
3919 Y.Object.each(cat_o, function(v, k) {
3920 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
3924 return (result.length) ? result.join(';') : '';
3927 * Run a sepecific test and return a Boolean response.
3930 * Y.Features.test("load", "1");
3934 * @param {String} cat The category of the test to run
3935 * @param {String} name The name of the test to run
3936 * @param {Array} args The arguments to pass to the test function
3937 * @return {Boolean} True or false if the test passed/failed.
3939 test: function(cat, name, args) {
3941 var result, ua, test,
3942 cat_o = feature_tests[cat],
3943 feature = cat_o && cat_o[name];
3948 result = feature.result;
3950 if (Y.Lang.isUndefined(result)) {
3954 result = (Y.UA[ua]);
3957 test = feature.test;
3958 if (test && ((!ua) || result)) {
3959 result = test.apply(Y, args);
3962 feature.result = result;
3970 // Y.Features.add("load", "1", {});
3971 // Y.Features.test("load", "1");
3972 // caps=1:1;2:0;3:1;
3974 /* This file is auto-generated by src/loader/scripts/meta_join.py */
3975 var add = Y.Features.add;
3978 "name": "io-nodejs",
3979 "trigger": "io-base",
3982 // graphics-canvas-default
3984 "name": "graphics-canvas-default",
3985 "test": function(Y) {
3986 var DOCUMENT = Y.config.doc,
3987 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
3988 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
3989 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
3990 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
3992 "trigger": "graphics"
3994 // autocomplete-list-keys
3996 "name": "autocomplete-list-keys",
3997 "test": function (Y) {
3998 // Only add keyboard support to autocomplete-list if this doesn't appear to
3999 // be an iOS or Android-based mobile device.
4001 // There's currently no feasible way to actually detect whether a device has
4002 // a hardware keyboard, so this sniff will have to do. It can easily be
4003 // overridden by manually loading the autocomplete-list-keys module.
4005 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
4006 // doesn't fire the keyboard events used by AutoCompleteList, so there's
4007 // no point loading the -keys module even when a bluetooth keyboard may be
4009 return !(Y.UA.ios || Y.UA.android);
4011 "trigger": "autocomplete-list"
4015 "name": "graphics-svg",
4016 "test": function(Y) {
4017 var DOCUMENT = Y.config.doc,
4018 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
4019 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
4020 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
4022 return svg && (useSVG || !canvas);
4024 "trigger": "graphics"
4028 "name": "editor-para-ie",
4029 "trigger": "editor-para",
4033 // graphics-vml-default
4035 "name": "graphics-vml-default",
4036 "test": function(Y) {
4037 var DOCUMENT = Y.config.doc,
4038 canvas = DOCUMENT && DOCUMENT.createElement("canvas");
4039 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
4041 "trigger": "graphics"
4043 // graphics-svg-default
4045 "name": "graphics-svg-default",
4046 "test": function(Y) {
4047 var DOCUMENT = Y.config.doc,
4048 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
4049 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
4050 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
4052 return svg && (useSVG || !canvas);
4054 "trigger": "graphics"
4058 "name": "history-hash-ie",
4059 "test": function (Y) {
4060 var docMode = Y.config.doc && Y.config.doc.documentMode;
4062 return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
4063 !docMode || docMode < 8);
4065 "trigger": "history-hash"
4069 "name": "transition-timer",
4070 "test": function (Y) {
4071 var DOCUMENT = Y.config.doc,
4072 node = (DOCUMENT) ? DOCUMENT.documentElement: null,
4075 if (node && node.style) {
4076 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style);
4081 "trigger": "transition"
4085 "name": "dom-style-ie",
4086 "test": function (Y) {
4088 var testFeature = Y.Features.test,
4089 addFeature = Y.Features.add,
4090 WINDOW = Y.config.win,
4091 DOCUMENT = Y.config.doc,
4092 DOCUMENT_ELEMENT = 'documentElement',
4095 addFeature('style', 'computedStyle', {
4097 return WINDOW && 'getComputedStyle' in WINDOW;
4101 addFeature('style', 'opacity', {
4103 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
4107 ret = (!testFeature('style', 'opacity') &&
4108 !testFeature('style', 'computedStyle'));
4112 "trigger": "dom-style"
4116 "name": "selector-css2",
4117 "test": function (Y) {
4118 var DOCUMENT = Y.config.doc,
4119 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
4123 "trigger": "selector"
4127 "name": "widget-base-ie",
4128 "trigger": "widget-base",
4133 "name": "event-base-ie",
4134 "test": function(Y) {
4135 var imp = Y.config.doc && Y.config.doc.implementation;
4136 return (imp && (!imp.hasFeature('Events', '2.0')));
4138 "trigger": "node-base"
4142 "name": "dd-gestures",
4143 "test": function(Y) {
4144 return ((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.chrome && Y.UA.chrome < 6));
4146 "trigger": "dd-drag"
4148 // scrollview-base-ie
4150 "name": "scrollview-base-ie",
4151 "trigger": "scrollview-base",
4154 // app-transitions-native
4156 "name": "app-transitions-native",
4157 "test": function (Y) {
4158 var doc = Y.config.doc,
4159 node = doc ? doc.documentElement : null;
4161 if (node && node.style) {
4162 return ('MozTransition' in node.style || 'WebkitTransition' in node.style);
4167 "trigger": "app-transitions"
4171 "name": "graphics-canvas",
4172 "test": function(Y) {
4173 var DOCUMENT = Y.config.doc,
4174 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
4175 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
4176 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
4177 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
4179 "trigger": "graphics"
4183 "name": "graphics-vml",
4184 "test": function(Y) {
4185 var DOCUMENT = Y.config.doc,
4186 canvas = DOCUMENT && DOCUMENT.createElement("canvas");
4187 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
4189 "trigger": "graphics"
4193 }, '3.5.1' ,{requires:['yui-base']});
4194 YUI.add('intl-base', function(Y) {
4197 * The Intl utility provides a central location for managing sets of
4198 * localized resources (strings and formatting patterns).
4205 var SPLIT_REGEX = /[, ]/;
4207 Y.mix(Y.namespace('Intl'), {
4210 * Returns the language among those available that
4211 * best matches the preferred language list, using the Lookup
4212 * algorithm of BCP 47.
4213 * If none of the available languages meets the user's preferences,
4214 * then "" is returned.
4215 * Extended language ranges are not supported.
4217 * @method lookupBestLang
4218 * @param {String[] | String} preferredLanguages The list of preferred
4219 * languages in descending preference order, represented as BCP 47
4220 * language tags. A string array or a comma-separated list.
4221 * @param {String[]} availableLanguages The list of languages
4222 * that the application supports, represented as BCP 47 language
4225 * @return {String} The available language that best matches the
4226 * preferred language list, or "".
4229 lookupBestLang: function(preferredLanguages, availableLanguages) {
4231 var i, language, result, index;
4233 // check whether the list of available languages contains language;
4235 function scan(language) {
4237 for (i = 0; i < availableLanguages.length; i += 1) {
4238 if (language.toLowerCase() ===
4239 availableLanguages[i].toLowerCase()) {
4240 return availableLanguages[i];
4245 if (Y.Lang.isString(preferredLanguages)) {
4246 preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
4249 for (i = 0; i < preferredLanguages.length; i += 1) {
4250 language = preferredLanguages[i];
4251 if (!language || language === '*') {
4254 // check the fallback sequence for one language
4255 while (language.length > 0) {
4256 result = scan(language);
4260 index = language.lastIndexOf('-');
4262 language = language.substring(0, index);
4263 // one-character subtags get cut along with the
4265 if (index >= 2 && language.charAt(index - 2) === '-') {
4266 language = language.substring(0, index - 2);
4269 // nothing available for this language
4281 }, '3.5.1' ,{requires:['yui-base']});
4282 YUI.add('yui-log', function(Y) {
4285 * Provides console log capability and exposes a custom event for
4286 * console implementations. This module is a `core` YUI module, <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
4289 * @submodule yui-log
4293 LOGEVENT = 'yui:log',
4294 UNDEFINED = 'undefined',
4295 LEVELS = { debug: 1,
4301 * If the 'debug' config is true, a 'yui:log' event will be
4302 * dispatched, which the Console widget and anything else
4303 * can consume. If the 'useBrowserConsole' config is true, it will
4304 * write to the browser console if available. YUI-specific log
4305 * messages will only be present in the -debug versions of the
4306 * JS files. The build system is supposed to remove log statements
4307 * from the raw and minified versions of the files.
4311 * @param {String} msg The message to log.
4312 * @param {String} cat The log category for the message. Default
4313 * categories are "info", "warn", "error", time".
4314 * Custom categories can be used as well. (opt).
4315 * @param {String} src The source of the the message (opt).
4316 * @param {boolean} silent If true, the log event won't fire.
4317 * @return {YUI} YUI instance.
4319 INSTANCE.log = function(msg, cat, src, silent) {
4320 var bail, excl, incl, m, f,
4323 publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
4324 // suppress log message if the config is off or the event stack
4325 // or the event call stack contains a consumer of the yui:log event
4327 // apply source filters
4329 excl = c.logExclude;
4330 incl = c.logInclude;
4331 if (incl && !(src in incl)) {
4333 } else if (incl && (src in incl)) {
4335 } else if (excl && (src in excl)) {
4340 if (c.useBrowserConsole) {
4341 m = (src) ? src + ': ' + msg : msg;
4342 if (Y.Lang.isFunction(c.logFn)) {
4343 c.logFn.call(Y, msg, cat, src);
4344 } else if (typeof console != UNDEFINED && console.log) {
4345 f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
4347 } else if (typeof opera != UNDEFINED) {
4352 if (publisher && !silent) {
4354 if (publisher == Y && (!publisher.getEvent(LOGEVENT))) {
4355 publisher.publish(LOGEVENT, {
4360 publisher.fire(LOGEVENT, {
4373 * Write a system message. This message will be preserved in the
4374 * minified and raw versions of the YUI files, unlike log statements.
4377 * @param {String} msg The message to log.
4378 * @param {String} cat The log category for the message. Default
4379 * categories are "info", "warn", "error", time".
4380 * Custom categories can be used as well. (opt).
4381 * @param {String} src The source of the the message (opt).
4382 * @param {boolean} silent If true, the log event won't fire.
4383 * @return {YUI} YUI instance.
4385 INSTANCE.message = function() {
4386 return INSTANCE.log.apply(INSTANCE, arguments);
4390 }, '3.5.1' ,{requires:['yui-base']});
4391 YUI.add('yui-log-nodejs', function(Y) {
4393 var sys = require(process.binding('natives').util ? 'util' : 'sys'),
4397 var stdio = require("stdio");
4398 hasColor = stdio.isStderrATTY();
4403 Y.config.useColor = hasColor;
4405 Y.consoleColor = function(str, num) {
4406 if (!this.config.useColor) {
4412 return "\033[" + num +"m" + str + "\033[0m"
4416 var logFn = function(str, t, m) {
4419 id = '[' + this.id + ']:';
4422 m = (m) ? this.consoleColor(' (' + m.toLowerCase() + '):', 35) : '';
4428 if ((typeof str === 'object') || str instanceof Array) {
4430 //Should we use this?
4431 if (str.tagName || str._yuid || str._query) {
4432 str = str.toString();
4434 str = sys.inspect(str);
4441 var lvl = '37;40', mLvl = ((str) ? '' : 31);
4442 t = t+''; //Force to a string..
4443 switch (t.toLowerCase()) {
4454 if (typeof str === 'string') {
4455 if (str && str.indexOf("\n") !== -1) {
4460 // output log messages to stderr
4461 sys.error(this.consoleColor(t.toLowerCase() + ':', lvl) + m + ' ' + this.consoleColor(str, mLvl));
4464 if (!Y.config.logFn) {
4465 Y.config.logFn = logFn;
4470 }, '3.5.1' ,{requires:['yui-log']});
4471 YUI.add('yui-later', function(Y) {
4474 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module, <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
4477 * @submodule yui-later
4483 * Executes the supplied function in the context of the supplied
4484 * object 'when' milliseconds later. Executes the function a
4485 * single time unless periodic is set to true.
4488 * @param when {int} the number of milliseconds to wait until the fn
4490 * @param o the context object.
4491 * @param fn {Function|String} the function to execute or the name of
4492 * the method in the 'o' object to execute.
4493 * @param data [Array] data that is provided to the function. This
4494 * accepts either a single item or an array. If an array is provided,
4495 * the function is executed with one parameter for each array item.
4496 * If you need to pass a single array parameter, it needs to be wrapped
4497 * in an array [myarray].
4499 * Note: native methods in IE may not have the call and apply methods.
4500 * In this case, it will work, but you are limited to four arguments.
4502 * @param periodic {boolean} if true, executes continuously at supplied
4503 * interval until canceled.
4504 * @return {object} a timer object. Call the cancel() method on this
4505 * object to stop the timer.
4507 Y.later = function(when, o, fn, data, periodic) {
4509 data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
4510 o = o || Y.config.win || Y;
4512 var cancelled = false,
4513 method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
4514 wrapper = function() {
4515 // IE 8- may execute a setInterval callback one last time
4516 // after clearInterval was called, so in order to preserve
4517 // the cancel() === no more runny-run, we have to jump through
4520 if (!method.apply) {
4521 method(data[0], data[1], data[2], data[3]);
4523 method.apply(o, data || NO_ARGS);
4527 id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
4532 cancel: function() {
4534 if (this.interval) {
4543 Y.Lang.later = Y.later;
4547 }, '3.5.1' ,{requires:['yui-base']});
4548 YUI.add('loader-base', function(Y) {
4551 * The YUI loader core
4553 * @submodule loader-base
4556 if (!YUI.Env[Y.version]) {
4559 var VERSION = Y.version,
4561 ROOT = VERSION + BUILD,
4562 CDN_BASE = Y.Env.base,
4563 GALLERY_VERSION = '${loader.gallery}',
4565 TNT_VERSION = '${loader.tnt}',
4566 YUI2_VERSION = '${loader.yui2}',
4567 COMBO_BASE = CDN_BASE + 'combo?',
4568 META = { version: VERSION,
4571 comboBase: COMBO_BASE,
4572 skin: { defaultSkin: 'sam',
4573 base: 'assets/skins/',
4580 'cssfonts-context']},
4583 groups = META.groups,
4584 yui2Update = function(tnt, yui2, config) {
4586 var root = TNT + '.' +
4587 (tnt || TNT_VERSION) + '/' +
4588 (yui2 || YUI2_VERSION) + BUILD,
4589 base = (config && config.base) ? config.base : CDN_BASE,
4590 combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
4592 groups.yui2.base = base + root;
4593 groups.yui2.root = root;
4594 groups.yui2.comboBase = combo;
4596 galleryUpdate = function(tag, config) {
4597 var root = (tag || GALLERY_VERSION) + BUILD,
4598 base = (config && config.base) ? config.base : CDN_BASE,
4599 combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
4601 groups.gallery.base = base + root;
4602 groups.gallery.root = root;
4603 groups.gallery.comboBase = combo;
4607 groups[VERSION] = {};
4612 comboBase: COMBO_BASE,
4613 update: galleryUpdate,
4614 patterns: { 'gallery-': { },
4615 'lang/gallery-': {},
4616 'gallerycss-': { type: 'css' } }
4622 comboBase: COMBO_BASE,
4626 configFn: function(me) {
4627 if (/-skin|reset|fonts|grids|base/.test(me.name)) {
4629 me.path = me.path.replace(/\.js/, '.css');
4630 // this makes skins in builds earlier than
4631 // 2.6.0 work as long as combine is false
4632 me.path = me.path.replace(/\/yui2-skin/,
4633 '/assets/skins/sam/yui2-skin');
4643 YUI.Env[VERSION] = META;
4649 * Loader dynamically loads script and css files. It includes the dependency
4650 * information for the version of the library in use, and will automatically pull in
4651 * dependencies for the modules requested. It can also load the
4652 * files from the Yahoo! CDN, and it can utilize the combo service provided on
4653 * this network to reduce the number of http connections required to download
4658 * @submodule loader-base
4662 NO_REQUIREMENTS = [],
4663 MAX_URL_LENGTH = 1024,
4664 GLOBAL_ENV = YUI.Env,
4665 GLOBAL_LOADED = GLOBAL_ENV._loaded,
4669 VERSION = Y.version,
4672 oeach = YObject.each,
4674 _queue = GLOBAL_ENV._loaderQueue,
4675 META = GLOBAL_ENV[VERSION],
4676 SKIN_PREFIX = 'skin-',
4678 ON_PAGE = GLOBAL_ENV.mods,
4681 _path = function(dir, file, type, nomin) {
4682 var path = dir + '/' + file;
4686 path += '.' + (type || CSS);
4692 * The component metadata is stored in Y.Env.meta.
4693 * Part of the loader module.
4700 * Loader dynamically loads script and css files. It includes the dependency
4701 * info for the version of the library in use, and will automatically pull in
4702 * dependencies for the modules requested. It can load the
4703 * files from the Yahoo! CDN, and it can utilize the combo service provided on
4704 * this network to reduce the number of http connections required to download
4705 * YUI files. You can also specify an external, custom combo service to host
4706 * your modules as well.
4709 var loader = new Y.Loader({
4714 require: ['node', 'dd', 'console']
4716 var out = loader.resolve(true);
4720 * @param {Object} config an optional set of configuration options.
4721 * @param {String} config.base The base dir which to fetch this module from
4722 * @param {String} config.comboBase The Combo service base path. Ex: `http://yui.yahooapis.com/combo?`
4723 * @param {String} config.root The root path to prepend to module names for the combo service. Ex: `2.5.2/build/`
4724 * @param {String|Object} config.filter A filter to apply to result urls. <a href="#property_filter">See filter property</a>
4725 * @param {Object} config.filters Per-component filter specification. If specified for a given component, this overrides the filter config.
4726 * @param {Boolean} config.combine Use a combo service to reduce the number of http connections required to load your dependencies
4727 * @param {Array} config.ignore: A list of modules that should never be dynamically loaded
4728 * @param {Array} config.force A list of modules that should always be loaded when required, even if already present on the page
4729 * @param {HTMLElement|String} config.insertBefore Node or id for a node that should be used as the insertion point for new nodes
4730 * @param {Object} config.jsAttributes Object literal containing attributes to add to script nodes
4731 * @param {Object} config.cssAttributes Object literal containing attributes to add to link nodes
4732 * @param {Number} config.timeout The number of milliseconds before a timeout occurs when dynamically loading nodes. If not set, there is no timeout
4733 * @param {Object} config.context Execution context for all callbacks
4734 * @param {Function} config.onSuccess Callback for the 'success' event
4735 * @param {Function} config.onFailure Callback for the 'failure' event
4736 * @param {Function} config.onCSS Callback for the 'CSSComplete' event. When loading YUI components with CSS the CSS is loaded first, then the script. This provides a moment you can tie into to improve the presentation of the page while the script is loading.
4737 * @param {Function} config.onTimeout Callback for the 'timeout' event
4738 * @param {Function} config.onProgress Callback executed each time a script or css file is loaded
4739 * @param {Object} config.modules A list of module definitions. See <a href="#method_addModule">Loader.addModule</a> for the supported module metadata
4740 * @param {Object} config.groups A list of group definitions. Each group can contain specific definitions for `base`, `comboBase`, `combine`, and accepts a list of `modules`.
4741 * @param {String} config.2in3 The version of the YUI 2 in 3 wrapper to use. The intrinsic support for YUI 2 modules in YUI 3 relies on versions of the YUI 2 components inside YUI 3 module wrappers. These wrappers change over time to accomodate the issues that arise from running YUI 2 in a YUI 3 sandbox.
4742 * @param {String} config.yui2 When using the 2in3 project, you can select the version of YUI 2 to use. Valid values are `2.2.2`, `2.3.1`, `2.4.1`, `2.5.2`, `2.6.0`, `2.7.0`, `2.8.0`, `2.8.1` and `2.9.0` [default] -- plus all versions of YUI 2 going forward.
4744 Y.Loader = function(o) {
4746 var defaults = META.modules,
4749 //Catch no config passed.
4752 modulekey = META.md5;
4755 * Internal callback to handle multiple internal insert() calls
4756 * so that css is inserted prior to js
4757 * @property _internalCallback
4760 // self._internalCallback = null;
4763 * Callback that will be executed when the loader is finished
4768 // self.onSuccess = null;
4771 * Callback that will be executed if there is a failure
4775 // self.onFailure = null;
4778 * Callback for the 'CSSComplete' event. When loading YUI components
4779 * with CSS the CSS is loaded first, then the script. This provides
4780 * a moment you can tie into to improve the presentation of the page
4781 * while the script is loading.
4785 // self.onCSS = null;
4788 * Callback executed each time a script or css file is loaded
4789 * @method onProgress
4792 // self.onProgress = null;
4795 * Callback that will be executed if a timeout occurs
4799 // self.onTimeout = null;
4802 * The execution context for all callbacks
4804 * @default {YUI} the YUI instance
4809 * Data that is passed to all callbacks
4812 // self.data = null;
4815 * Node reference or id where new nodes should be inserted before
4816 * @property insertBefore
4817 * @type string|HTMLElement
4819 // self.insertBefore = null;
4822 * The charset attribute for inserted nodes
4825 * @deprecated , use cssAttributes or jsAttributes.
4827 // self.charset = null;
4830 * An object literal containing attributes to add to link nodes
4831 * @property cssAttributes
4834 // self.cssAttributes = null;
4837 * An object literal containing attributes to add to script nodes
4838 * @property jsAttributes
4841 // self.jsAttributes = null;
4844 * The base directory.
4847 * @default http://yui.yahooapis.com/[YUI VERSION]/build/
4849 self.base = Y.Env.meta.base + Y.Env.meta.root;
4852 * Base path for the combo service
4853 * @property comboBase
4855 * @default http://yui.yahooapis.com/combo?
4857 self.comboBase = Y.Env.meta.comboBase;
4860 * Base path for language packs.
4862 // self.langBase = Y.Env.meta.langBase;
4866 * If configured, the loader will attempt to use the combo
4867 * service for YUI resources and configured external resources.
4870 * @default true if a base dir isn't in the config
4872 self.combine = o.base &&
4873 (o.base.indexOf(self.comboBase.substr(0, 20)) > -1);
4876 * The default seperator to use between files in a combo URL
4877 * @property comboSep
4879 * @default Ampersand
4881 self.comboSep = '&';
4883 * Max url length for combo urls. The default is 2048. This is the URL
4884 * limit for the Yahoo! hosted combo servers. If consuming
4885 * a different combo service that has a different URL limit
4886 * it is possible to override this default by supplying
4887 * the maxURLLength config option. The config option will
4888 * only take effect if lower than the default.
4890 * @property maxURLLength
4893 self.maxURLLength = MAX_URL_LENGTH;
4896 * Ignore modules registered on the YUI global
4897 * @property ignoreRegistered
4900 //self.ignoreRegistered = false;
4903 * Root path to prepend to module path for the combo
4907 * @default [YUI VERSION]/build/
4909 self.root = Y.Env.meta.root;
4912 * Timeout value in milliseconds. If set, self value will be used by
4913 * the get utility. the timeout event will fire if
4921 * A list of modules that should not be loaded, even if
4922 * they turn up in the dependency tree
4926 // self.ignore = null;
4929 * A list of modules that should always be loaded, even
4930 * if they have already been inserted into the page.
4934 // self.force = null;
4939 * Should we allow rollups
4940 * @property allowRollup
4944 self.allowRollup = false;
4947 * A filter to apply to result urls. This filter will modify the default
4948 * path for all modules. The default path for the YUI library is the
4949 * minified version of the files (e.g., event-min.js). The filter property
4950 * can be a predefined filter or a custom filter. The valid predefined
4954 * <dd>Selects the debug versions of the library (e.g., event-debug.js).
4955 * This option will automatically include the Logger widget</dd>
4957 * <dd>Selects the non-minified version of the library (e.g., event.js).
4960 * You can also define a custom filter, which must be an object literal
4961 * containing a search expression and a replace string:
4964 * 'searchExp': "-min\\.js",
4965 * 'replaceStr': "-debug.js"
4969 * @type string| {searchExp: string, replaceStr: string}
4971 // self.filter = null;
4974 * per-component filter specification. If specified for a given
4975 * component, this overrides the filter config.
4982 * The list of requested modules
4983 * @property required
4984 * @type {string: boolean}
4989 * If a module name is predefined when requested, it is checked againsts
4990 * the patterns provided in this property. If there is a match, the
4991 * module is added with the default configuration.
4993 * At the moment only supporting module prefixes, but anticipate
4994 * supporting at least regular expressions.
4995 * @property patterns
4998 // self.patterns = Y.merge(Y.Env.meta.patterns);
5002 * The library metadata
5003 * @property moduleInfo
5005 // self.moduleInfo = Y.merge(Y.Env.meta.moduleInfo);
5006 self.moduleInfo = {};
5008 self.groups = Y.merge(Y.Env.meta.groups);
5011 * Provides the information used to skin the skinnable components.
5012 * The following skin definition would result in 'skin1' and 'skin2'
5013 * being loaded for calendar (if calendar was requested), and
5014 * 'sam' for all other skinnable components:
5017 * // The default skin, which is automatically applied if not
5018 * // overriden by a component-specific skin definition.
5019 * // Change this in to apply a different skin globally
5020 * defaultSkin: 'sam',
5022 * // This is combined with the loader base property to get
5023 * // the default root directory for a skin. ex:
5024 * // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
5025 * base: 'assets/skins/',
5027 * // Any component-specific overrides can be specified here,
5028 * // making it possible to load different skins for different
5029 * // components. It is possible to load more than one skin
5030 * // for a given component as well.
5032 * calendar: ['skin1', 'skin2']
5038 self.skin = Y.merge(Y.Env.meta.skin);
5041 * Map of conditional modules
5044 self.conditions = {};
5046 // map of modules with a hash of modules that meet the requirement
5047 // self.provides = {};
5050 self._internal = true;
5053 cache = GLOBAL_ENV._renderedMods;
5056 oeach(cache, function modCache(v, k) {
5057 self.moduleInfo[k] = Y.merge(v);
5060 cache = GLOBAL_ENV._conditions;
5062 oeach(cache, function condCache(v, k) {
5063 self.conditions[k] = Y.merge(v);
5067 oeach(defaults, self.addModule, self);
5072 * Set when beginning to compute the dependency tree.
5073 * Composed of what YUI reports to be loaded combined
5074 * with what has been loaded by any instance on the page
5075 * with the version number specified in the metadata.
5077 * @type {string: boolean}
5079 self.loaded = GLOBAL_LOADED[VERSION];
5082 self._inspectPage();
5084 self._internal = false;
5088 self.forceMap = (self.force) ? Y.Array.hash(self.force) : {};
5090 self.testresults = null;
5092 if (Y.config.tests) {
5093 self.testresults = Y.config.tests;
5097 * List of rollup files found in the library metadata
5100 // self.rollups = null;
5103 * Whether or not to load optional dependencies for
5104 * the requested modules
5105 * @property loadOptional
5109 // self.loadOptional = false;
5112 * All of the derived dependencies in sorted order, which
5113 * will be populated when either calculate() or insert()
5121 * A list of modules to attach to the YUI instance when complete.
5122 * If not supplied, the sorted list of dependencies are applied.
5123 * @property attaching
5125 // self.attaching = null;
5128 * Flag to indicate the dependency tree needs to be recomputed
5129 * if insert is called again.
5137 * List of modules inserted by the utility
5138 * @property inserted
5139 * @type {string: boolean}
5144 * List of skipped modules during insert() because the module
5150 // Y.on('yui:load', self.loadNext, self);
5155 * Cached sorted calculate results
5159 //self.results = {};
5163 Y.Loader.prototype = {
5165 Regex that matches a CSS URL. Used to guess the file type when it's not
5174 REGEX_CSS: /\.css(?:[?;].*)?$/i,
5177 * Default filters for raw and debug
5178 * @property FILTER_DEFS
5185 'searchExp': '-min\\.js',
5189 'searchExp': '-min\\.js',
5190 'replaceStr': '-debug.js'
5194 * Check the pages meta-data and cache the result.
5195 * @method _inspectPage
5198 _inspectPage: function() {
5200 //Inspect the page for CSS only modules and mark them as loaded.
5201 oeach(this.moduleInfo, function(v, k) {
5202 if (v.type && v.type === CSS) {
5203 if (this.isCSSLoaded(v.name)) {
5204 this.loaded[k] = true;
5209 oeach(ON_PAGE, function(v, k) {
5211 var m = this.moduleInfo[k],
5212 req = v.details.requires,
5213 mr = m && m.requires;
5215 if (!m._inspected && req && mr.length != req.length) {
5216 // console.log('deleting ' + m.name);
5220 m = this.addModule(v.details, k);
5222 m._inspected = true;
5227 * returns true if b is not loaded, and is required directly or by means of modules it supersedes.
5230 * @param {String} mod1 The first module to compare
5231 * @param {String} mod2 The second module to compare
5233 _requires: function(mod1, mod2) {
5235 var i, rm, after_map, s,
5236 info = this.moduleInfo,
5244 rm = m.expanded_map;
5245 after_map = m.after_map;
5247 // check if this module should be sorted after the other
5248 // do this first to short circut circular deps
5249 if (after_map && (mod2 in after_map)) {
5253 after_map = other.after_map;
5256 if (after_map && (mod1 in after_map)) {
5260 // check if this module requires one the other supersedes
5261 s = info[mod2] && info[mod2].supersedes;
5263 for (i = 0; i < s.length; i++) {
5264 if (this._requires(mod1, s[i])) {
5270 s = info[mod1] && info[mod1].supersedes;
5272 for (i = 0; i < s.length; i++) {
5273 if (this._requires(mod2, s[i])) {
5279 // check if this module requires the other directly
5280 // if (r && YArray.indexOf(r, mod2) > -1) {
5281 if (rm && (mod2 in rm)) {
5285 // external css files should be sorted below yui css
5286 if (m.ext && m.type == CSS && !other.ext && other.type == CSS) {
5293 * Apply a new config to the Loader instance
5296 * @param {Object} o The new configuration
5298 _config: function(o) {
5299 var i, j, val, f, group, groupName, self = this;
5300 // apply config values
5303 if (o.hasOwnProperty(i)) {
5305 if (i == 'require') {
5307 } else if (i == 'skin') {
5308 //If the config.skin is a string, format to the expected object
5309 if (typeof val === 'string') {
5310 self.skin.defaultSkin = o.skin;
5316 Y.mix(self.skin, val, true);
5317 } else if (i == 'groups') {
5319 if (val.hasOwnProperty(j)) {
5322 self.addGroup(group, groupName);
5323 if (group.aliases) {
5324 oeach(group.aliases, self.addAlias, self);
5329 } else if (i == 'modules') {
5330 // add a hash of module definitions
5331 oeach(val, self.addModule, self);
5332 } else if (i === 'aliases') {
5333 oeach(val, self.addAlias, self);
5334 } else if (i == 'gallery') {
5335 this.groups.gallery.update(val, o);
5336 } else if (i == 'yui2' || i == '2in3') {
5337 this.groups.yui2.update(o['2in3'], o.yui2, o);
5348 if (L.isString(f)) {
5349 f = f.toUpperCase();
5350 self.filterName = f;
5351 self.filter = self.FILTER_DEFS[f];
5353 self.require('yui-log', 'dump');
5359 //Removed this so that when Loader is invoked
5360 //it doesn't request what it doesn't need.
5361 //self.require('intl-base', 'intl');
5367 * Returns the skin module name for the specified skin name. If a
5368 * module name is supplied, the returned skin module name is
5369 * specific to the module passed in.
5370 * @method formatSkin
5371 * @param {string} skin the name of the skin.
5372 * @param {string} mod optional: the name of a module to skin.
5373 * @return {string} the full skin module name.
5375 formatSkin: function(skin, mod) {
5376 var s = SKIN_PREFIX + skin;
5385 * Adds the skin def to the module info
5387 * @param {string} skin the name of the skin.
5388 * @param {string} mod the name of the module.
5389 * @param {string} parent parent module if this is a skin of a
5390 * submodule or plugin.
5391 * @return {string} the module name for the skin.
5394 _addSkin: function(skin, mod, parent) {
5395 var mdef, pkg, name, nmod,
5396 info = this.moduleInfo,
5398 ext = info[mod] && info[mod].ext;
5400 // Add a module definition for the module-specific skin css
5402 name = this.formatSkin(skin, mod);
5405 pkg = mdef.pkg || mod;
5411 path: (parent || pkg) + '/' + sinf.base + skin +
5416 nmod.base = mdef.base;
5418 if (mdef.configFn) {
5419 nmod.configFn = mdef.configFn;
5421 this.addModule(nmod, name);
5429 * Adds an alias module to the system
5431 * @param {Array} use An array of modules that makes up this alias
5432 * @param {String} name The name of the alias
5434 * var loader = new Y.Loader({});
5435 * loader.addAlias([ 'node', 'yql' ], 'davglass');
5436 * loader.require(['davglass']);
5437 * var out = loader.resolve(true);
5439 * //out.js will contain Node and YQL modules
5441 addAlias: function(use, name) {
5442 YUI.Env.aliases[name] = use;
5449 * Add a new module group
5451 * @param {Object} config An object containing the group configuration data
5452 * @param {String} config.name required, the group name
5453 * @param {String} config.base The base directory for this module group
5454 * @param {String} config.root The root path to add to each combo resource path
5455 * @param {Boolean} config.combine Should the request be combined
5456 * @param {String} config.comboBase Combo service base path
5457 * @param {Object} config.modules The group of modules
5458 * @param {String} name the group name.
5460 * var loader = new Y.Loader({});
5464 * comboBase: '/combo?',
5467 * //Module List here
5471 addGroup: function(o, name) {
5472 var mods = o.modules,
5474 name = name || o.name;
5476 self.groups[name] = o;
5479 oeach(o.patterns, function(v, k) {
5481 self.patterns[k] = v;
5486 oeach(mods, function(v, k) {
5487 if (typeof v === 'string') {
5488 v = { name: k, fullpath: v };
5491 self.addModule(v, k);
5497 * Add a new module to the component metadata.
5499 * @param {Object} config An object containing the module data.
5500 * @param {String} config.name Required, the component name
5501 * @param {String} config.type Required, the component type (js or css)
5502 * @param {String} config.path Required, the path to the script from `base`
5503 * @param {Array} config.requires Array of modules required by this component
5504 * @param {Array} [config.optional] Array of optional modules for this component
5505 * @param {Array} [config.supersedes] Array of the modules this component replaces
5506 * @param {Array} [config.after] Array of modules the components which, if present, should be sorted above this one
5507 * @param {Object} [config.after_map] Faster alternative to 'after' -- supply a hash instead of an array
5508 * @param {Number} [config.rollup] The number of superseded modules required for automatic rollup
5509 * @param {String} [config.fullpath] If `fullpath` is specified, this is used instead of the configured `base + path`
5510 * @param {Boolean} [config.skinnable] Flag to determine if skin assets should automatically be pulled in
5511 * @param {Object} [config.submodules] Hash of submodules
5512 * @param {String} [config.group] The group the module belongs to -- this is set automatically when it is added as part of a group configuration.
5513 * @param {Array} [config.lang] Array of BCP 47 language tags of languages for which this module has localized resource bundles, e.g., `["en-GB", "zh-Hans-CN"]`
5514 * @param {Object} [config.condition] Specifies that the module should be loaded automatically if a condition is met. This is an object with up to three fields:
5515 * @param {String} [config.condition.trigger] The name of a module that can trigger the auto-load
5516 * @param {Function} [config.condition.test] A function that returns true when the module is to be loaded.
5517 * @param {String} [config.condition.when] Specifies the load order of the conditional module
5518 * with regard to the position of the trigger module.
5519 * This should be one of three values: `before`, `after`, or `instead`. The default is `after`.
5520 * @param {Object} [config.testresults] A hash of test results from `Y.Features.all()`
5521 * @param {Function} [config.configFn] A function to exectute when configuring this module
5522 * @param {Object} config.configFn.mod The module config, modifying this object will modify it's config. Returning false will delete the module's config.
5523 * @param {String} [name] The module name, required if not in the module data.
5524 * @return {Object} the module definition or null if the object passed in did not provide all required attributes.
5526 addModule: function(o, name) {
5527 name = name || o.name;
5529 if (typeof o === 'string') {
5530 o = { name: name, fullpath: o };
5533 //Only merge this data if the temp flag is set
5534 //from an earlier pass from a pattern or else
5535 //an override module (YUI_config) can not be used to
5536 //replace a default module.
5537 if (this.moduleInfo[name] && this.moduleInfo[name].temp) {
5538 //This catches temp modules loaded via a pattern
5539 // The module will be added twice, once from the pattern and
5540 // Once from the actual add call, this ensures that properties
5541 // that were added to the module the first time around (group: gallery)
5542 // are also added the second time around too.
5543 o = Y.merge(this.moduleInfo[name], o);
5548 if (!o || !o.name) {
5553 //Always assume it's javascript unless the CSS pattern is matched.
5555 var p = o.path || o.fullpath;
5556 if (p && this.REGEX_CSS.test(p)) {
5561 if (!o.path && !o.fullpath) {
5562 o.path = _path(name, name, o.type);
5564 o.supersedes = o.supersedes || o.use;
5566 o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true;
5568 // Handle submodule logic
5569 var subs = o.submodules, i, l, t, sup, s, smod, plugins, plug,
5570 j, langs, packName, supName, flatSup, flatLang, lang, ret,
5571 overrides, skinname, when,
5572 conditions = this.conditions, trigger;
5573 // , existing = this.moduleInfo[name], newr;
5575 this.moduleInfo[name] = o;
5577 o.requires = o.requires || [];
5580 skinname = this._addSkin(this.skin.defaultSkin, name);
5581 o.requires.unshift(skinname);
5584 o.requires = this.filterRequires(o.requires) || [];
5586 if (!o.langPack && o.lang) {
5587 langs = YArray(o.lang);
5588 for (j = 0; j < langs.length; j++) {
5590 packName = this.getLangPackName(lang, name);
5591 smod = this.moduleInfo[packName];
5593 smod = this._addLangPack(lang, o, packName);
5600 sup = o.supersedes || [];
5604 if (subs.hasOwnProperty(i)) {
5607 s.path = s.path || _path(name, i, o.type);
5612 sup = sup.concat(s.supersedes);
5615 smod = this.addModule(s, i);
5618 if (smod.skinnable) {
5620 overrides = this.skin.overrides;
5621 if (overrides && overrides[i]) {
5622 for (j = 0; j < overrides[i].length; j++) {
5623 skinname = this._addSkin(overrides[i][j],
5628 skinname = this._addSkin(this.skin.defaultSkin,
5633 // looks like we are expected to work out the metadata
5634 // for the parent module language packs from what is
5635 // specified in the child modules.
5636 if (s.lang && s.lang.length) {
5638 langs = YArray(s.lang);
5639 for (j = 0; j < langs.length; j++) {
5641 packName = this.getLangPackName(lang, name);
5642 supName = this.getLangPackName(lang, i);
5643 smod = this.moduleInfo[packName];
5646 smod = this._addLangPack(lang, o, packName);
5649 flatSup = flatSup || YArray.hash(smod.supersedes);
5651 if (!(supName in flatSup)) {
5652 smod.supersedes.push(supName);
5655 o.lang = o.lang || [];
5657 flatLang = flatLang || YArray.hash(o.lang);
5659 if (!(lang in flatLang)) {
5663 // Add rollup file, need to add to supersedes list too
5666 packName = this.getLangPackName(ROOT_LANG, name);
5667 supName = this.getLangPackName(ROOT_LANG, i);
5669 smod = this.moduleInfo[packName];
5672 smod = this._addLangPack(lang, o, packName);
5675 if (!(supName in flatSup)) {
5676 smod.supersedes.push(supName);
5679 // Add rollup file, need to add to supersedes list too
5687 //o.supersedes = YObject.keys(YArray.hash(sup));
5688 o.supersedes = YArray.dedupe(sup);
5689 if (this.allowRollup) {
5690 o.rollup = (l < 4) ? l : Math.min(l - 1, 4);
5694 plugins = o.plugins;
5696 for (i in plugins) {
5697 if (plugins.hasOwnProperty(i)) {
5700 plug.path = plug.path || _path(name, i, o.type);
5701 plug.requires = plug.requires || [];
5702 plug.group = o.group;
5703 this.addModule(plug, i);
5705 this._addSkin(this.skin.defaultSkin, i, name);
5713 t = o.condition.trigger;
5714 if (YUI.Env.aliases[t]) {
5715 t = YUI.Env.aliases[t];
5717 if (!Y.Lang.isArray(t)) {
5721 for (i = 0; i < t.length; i++) {
5723 when = o.condition.when;
5724 conditions[trigger] = conditions[trigger] || {};
5725 conditions[trigger][name] = o.condition;
5726 // the 'when' attribute can be 'before', 'after', or 'instead'
5727 // the default is after.
5728 if (when && when != 'after') {
5729 if (when == 'instead') { // replace the trigger
5730 o.supersedes = o.supersedes || [];
5731 o.supersedes.push(trigger);
5732 } else { // before the trigger
5733 // the trigger requires the conditional mod,
5734 // so it should appear before the conditional
5735 // mod if we do not intersede.
5737 } else { // after the trigger
5738 o.after = o.after || [];
5739 o.after.push(trigger);
5745 o.supersedes = this.filterRequires(o.supersedes);
5749 o.after = this.filterRequires(o.after);
5750 o.after_map = YArray.hash(o.after);
5753 // this.dirty = true;
5756 ret = o.configFn(o);
5757 if (ret === false) {
5758 delete this.moduleInfo[name];
5759 delete GLOBAL_ENV._renderedMods[name];
5763 //Add to global cache
5765 if (!GLOBAL_ENV._renderedMods) {
5766 GLOBAL_ENV._renderedMods = {};
5768 GLOBAL_ENV._renderedMods[name] = Y.merge(o);
5769 GLOBAL_ENV._conditions = conditions;
5776 * Add a requirement for one or more module
5778 * @param {string[] | string*} what the modules to load.
5780 require: function(what) {
5781 var a = (typeof what === 'string') ? YArray(arguments) : what;
5783 this.required = Y.merge(this.required, YArray.hash(this.filterRequires(a)));
5785 this._explodeRollups();
5788 * Grab all the items that were asked for, check to see if the Loader
5789 * meta-data contains a "use" array. If it doesm remove the asked item and replace it with
5790 * the content of the "use".
5791 * This will make asking for: "dd"
5792 * Actually ask for: "dd-ddm-base,dd-ddm,dd-ddm-drop,dd-drag,dd-proxy,dd-constrain,dd-drop,dd-scroll,dd-drop-plugin"
5794 * @method _explodeRollups
5796 _explodeRollups: function() {
5799 if (!self.allowRollup) {
5800 oeach(r, function(v, name) {
5801 m = self.getModule(name);
5804 YArray.each(m.use, function(v) {
5805 m = self.getModule(v);
5808 YArray.each(m.use, function(v) {
5822 * Explodes the required array to remove aliases and replace them with real modules
5823 * @method filterRequires
5824 * @param {Array} r The original requires array
5825 * @return {Array} The new array of exploded requirements
5827 filterRequires: function(r) {
5829 if (!Y.Lang.isArray(r)) {
5833 var c = [], i, mod, o, m;
5835 for (i = 0; i < r.length; i++) {
5836 mod = this.getModule(r[i]);
5837 if (mod && mod.use) {
5838 for (o = 0; o < mod.use.length; o++) {
5839 //Must walk the other modules in case a module is a rollup of rollups (datatype)
5840 m = this.getModule(mod.use[o]);
5842 c = Y.Array.dedupe([].concat(c, this.filterRequires(m.use)));
5856 * Returns an object containing properties for all modules required
5857 * in order to load the requested module
5858 * @method getRequires
5859 * @param {object} mod The module definition from moduleInfo.
5860 * @return {array} the expanded requirement list.
5862 getRequires: function(mod) {
5865 //console.log('returning no reqs for ' + mod.name);
5866 return NO_REQUIREMENTS;
5870 //console.log('returning requires for ' + mod.name, mod.requires);
5871 return mod.expanded || NO_REQUIREMENTS;
5874 //TODO add modue cache here out of scope..
5876 var i, m, j, add, packName, lang, testresults = this.testresults,
5877 name = mod.name, cond,
5878 adddef = ON_PAGE[name] && ON_PAGE[name].details,
5881 o, skinmod, skindef, skinpar, skinname,
5882 intl = mod.lang || mod.intl,
5883 info = this.moduleInfo,
5884 ftests = Y.Features && Y.Features.tests.load,
5887 // console.log(name);
5889 // pattern match leaves module stub that needs to be filled out
5890 if (mod.temp && adddef) {
5892 mod = this.addModule(adddef, name);
5893 mod.group = old_mod.group;
5894 mod.pkg = old_mod.pkg;
5895 delete mod.expanded;
5898 // console.log('cache: ' + mod.langCache + ' == ' + this.lang);
5900 // if (mod.expanded && (!mod.langCache || mod.langCache == this.lang)) {
5901 if (mod.expanded && (!this.lang || mod.langCache === this.lang)) {
5902 return mod.expanded;
5908 r = this.filterRequires(mod.requires);
5910 //If a module has a lang attribute, auto add the intl requirement.
5915 o = this.filterRequires(mod.optional);
5919 mod.langCache = this.lang;
5921 for (i = 0; i < r.length; i++) {
5925 m = this.getModule(r[i]);
5927 add = this.getRequires(m);
5928 intl = intl || (m.expanded_map &&
5929 (INTL in m.expanded_map));
5930 for (j = 0; j < add.length; j++) {
5937 // get the requirements from superseded modules, if any
5938 r = this.filterRequires(mod.supersedes);
5940 for (i = 0; i < r.length; i++) {
5942 // if this module has submodules, the requirements list is
5943 // expanded to include the submodules. This is so we can
5944 // prevent dups when a submodule is already loaded and the
5945 // parent is requested.
5946 if (mod.submodules) {
5951 m = this.getModule(r[i]);
5954 add = this.getRequires(m);
5955 intl = intl || (m.expanded_map &&
5956 (INTL in m.expanded_map));
5957 for (j = 0; j < add.length; j++) {
5965 if (o && this.loadOptional) {
5966 for (i = 0; i < o.length; i++) {
5972 add = this.getRequires(m);
5973 intl = intl || (m.expanded_map &&
5974 (INTL in m.expanded_map));
5975 for (j = 0; j < add.length; j++) {
5983 cond = this.conditions[name];
5986 //Set the module to not parsed since we have conditionals and this could change the dependency tree.
5987 mod._parsed = false;
5988 if (testresults && ftests) {
5989 oeach(testresults, function(result, id) {
5990 var condmod = ftests[id].name;
5991 if (!hash[condmod] && ftests[id].trigger == name) {
5992 if (result && ftests[id]) {
5993 hash[condmod] = true;
5999 oeach(cond, function(def, condmod) {
6000 if (!hash[condmod]) {
6001 //first see if they've specfied a ua check
6002 //then see if they've got a test fn & if it returns true
6003 //otherwise just having a condition block is enough
6004 var go = def && ((!def.ua && !def.test) || (def.ua && Y.UA[def.ua]) ||
6005 (def.test && def.test(Y, r)));
6008 hash[condmod] = true;
6010 m = this.getModule(condmod);
6012 add = this.getRequires(m);
6013 for (j = 0; j < add.length; j++) {
6024 // Create skin modules
6025 if (mod.skinnable) {
6026 skindef = this.skin.overrides;
6027 oeach(YUI.Env.aliases, function(o, n) {
6028 if (Y.Array.indexOf(o, name) > -1) {
6032 if (skindef && (skindef[name] || (skinpar && skindef[skinpar]))) {
6034 if (skindef[skinpar]) {
6037 for (i = 0; i < skindef[skinname].length; i++) {
6038 skinmod = this._addSkin(skindef[skinname][i], name);
6039 if (!this.isCSSLoaded(skinmod, this._boot)) {
6044 skinmod = this._addSkin(this.skin.defaultSkin, name);
6045 if (!this.isCSSLoaded(skinmod, this._boot)) {
6051 mod._parsed = false;
6055 if (mod.lang && !mod.langPack && Y.Intl) {
6056 lang = Y.Intl.lookupBestLang(this.lang || ROOT_LANG, mod.lang);
6057 packName = this.getLangPackName(lang, name);
6059 d.unshift(packName);
6065 mod.expanded_map = YArray.hash(d);
6067 mod.expanded = YObject.keys(mod.expanded_map);
6069 return mod.expanded;
6072 * Check to see if named css module is already loaded on the page
6073 * @method isCSSLoaded
6074 * @param {String} name The name of the css file
6077 isCSSLoaded: function(name, skip) {
6078 //TODO - Make this call a batching call with name being an array
6079 if (!name || !YUI.Env.cssStampEl || (!skip && this.ignoreRegistered)) {
6083 var el = YUI.Env.cssStampEl,
6085 style = el.currentStyle; //IE
6087 //Add the classname to the element
6088 el.className = name;
6091 style = Y.config.doc.defaultView.getComputedStyle(el, null);
6094 if (style && style['display'] === 'none') {
6099 el.className = ''; //Reset the classname to ''
6104 * Returns a hash of module names the supplied module satisfies.
6105 * @method getProvides
6106 * @param {string} name The name of the module.
6107 * @return {object} what this module provides.
6109 getProvides: function(name) {
6110 var m = this.getModule(name), o, s;
6111 // supmap = this.provides;
6117 if (m && !m.provides) {
6122 YArray.each(s, function(v) {
6123 Y.mix(o, this.getProvides(v));
6136 * Calculates the dependency tree, the result is stored in the sorted
6139 * @param {object} o optional options object.
6140 * @param {string} type optional argument to prune modules.
6142 calculate: function(o, type) {
6143 if (o || type || this.dirty) {
6155 if (this.allowRollup) {
6158 this._explodeRollups();
6165 * Creates a "psuedo" package for languages provided in the lang array
6166 * @method _addLangPack
6168 * @param {String} lang The language to create
6169 * @param {Object} m The module definition to create the language pack around
6170 * @param {String} packName The name of the package (e.g: lang/datatype-date-en-US)
6171 * @return {Object} The module definition
6173 _addLangPack: function(lang, m, packName) {
6176 existing = this.moduleInfo[packName];
6180 packPath = _path((m.pkg || name), packName, JS, true);
6192 conf.configFn = m.configFn;
6195 this.addModule(conf, packName);
6198 Y.Env.lang = Y.Env.lang || {};
6199 Y.Env.lang[lang] = Y.Env.lang[lang] || {};
6200 Y.Env.lang[lang][name] = true;
6204 return this.moduleInfo[packName];
6208 * Investigates the current YUI configuration on the page. By default,
6209 * modules already detected will not be loaded again unless a force
6210 * option is encountered. Called by calculate()
6214 _setup: function() {
6215 var info = this.moduleInfo, name, i, j, m, l,
6218 for (name in info) {
6219 if (info.hasOwnProperty(name)) {
6224 //m.requires = YObject.keys(YArray.hash(m.requires));
6225 m.requires = YArray.dedupe(m.requires);
6227 // Create lang pack modules
6228 if (m.lang && m.lang.length) {
6229 // Setup root package if the module has lang defined,
6230 // it needs to provide a root language pack
6231 packName = this.getLangPackName(ROOT_LANG, name);
6232 this._addLangPack(null, m, packName);
6240 //l = Y.merge(this.inserted);
6243 // available modules
6244 if (!this.ignoreRegistered) {
6245 Y.mix(l, GLOBAL_ENV.mods);
6248 // add the ignore list to the list of loaded packages
6250 Y.mix(l, YArray.hash(this.ignore));
6253 // expand the list to include superseded modules
6255 if (l.hasOwnProperty(j)) {
6256 Y.mix(l, this.getProvides(j));
6260 // remove modules on the force list from the loaded list
6262 for (i = 0; i < this.force.length; i++) {
6263 if (this.force[i] in l) {
6264 delete l[this.force[i]];
6269 Y.mix(this.loaded, l);
6275 * Builds a module name for a language pack
6276 * @method getLangPackName
6277 * @param {string} lang the language code.
6278 * @param {string} mname the module to build it for.
6279 * @return {string} the language pack module name.
6281 getLangPackName: function(lang, mname) {
6282 return ('lang/' + mname + ((lang) ? '_' + lang : ''));
6285 * Inspects the required modules list looking for additional
6286 * dependencies. Expands the required list to include all
6287 * required modules. Called by calculate()
6291 _explode: function() {
6292 //TODO Move done out of scope
6293 var r = this.required, m, reqs, done = {},
6296 // the setup phase is over, all modules have been created
6299 self._explodeRollups();
6302 oeach(r, function(v, name) {
6305 m = self.getModule(name);
6307 var expound = m.expound;
6310 r[expound] = self.getModule(expound);
6311 reqs = self.getRequires(r[expound]);
6312 Y.mix(r, YArray.hash(reqs));
6315 reqs = self.getRequires(m);
6316 Y.mix(r, YArray.hash(reqs));
6323 * Get's the loader meta data for the requested module
6325 * @param {String} mname The module name to get
6326 * @return {Object} The module metadata
6328 getModule: function(mname) {
6329 //TODO: Remove name check - it's a quick hack to fix pattern WIP
6334 var p, found, pname,
6335 m = this.moduleInfo[mname],
6336 patterns = this.patterns;
6338 // check the patterns library to see if we should automatically add
6339 // the module with defaults
6341 for (pname in patterns) {
6342 if (patterns.hasOwnProperty(pname)) {
6343 p = patterns[pname];
6345 //There is no test method, create a default one that tests
6346 // the pattern against the mod name
6348 p.test = function(mname, pname) {
6349 return (mname.indexOf(pname) > -1);
6353 if (p.test(mname, pname)) {
6354 // use the metadata supplied for the pattern
6355 // as the module definition.
6364 p.action.call(this, mname, pname);
6366 // ext true or false?
6367 m = this.addModule(Y.merge(found), mname);
6376 // impl in rollup submodule
6377 _rollup: function() { },
6380 * Remove superceded modules and loaded modules. Called by
6381 * calculate() after we have the mega list of all dependencies
6383 * @return {object} the reduced dependency hash.
6386 _reduce: function(r) {
6388 r = r || this.required;
6390 var i, j, s, m, type = this.loadType,
6391 ignore = this.ignore ? YArray.hash(this.ignore) : false;
6394 if (r.hasOwnProperty(i)) {
6395 m = this.getModule(i);
6396 // remove if already loaded
6397 if (((this.loaded[i] || ON_PAGE[i]) &&
6398 !this.forceMap[i] && !this.ignoreRegistered) ||
6399 (type && m && m.type != type)) {
6402 if (ignore && ignore[i]) {
6405 // remove anything this module supersedes
6406 s = m && m.supersedes;
6408 for (j = 0; j < s.length; j++) {
6420 * Handles the queue when a module has been loaded for all cases
6423 * @param {String} msg The message from Loader
6424 * @param {Boolean} success A boolean denoting success or failure
6426 _finish: function(msg, success) {
6428 _queue.running = false;
6430 var onEnd = this.onEnd;
6432 onEnd.call(this.context, {
6441 * The default Loader onSuccess handler, calls this.onSuccess with a payload
6442 * @method _onSuccess
6445 _onSuccess: function() {
6446 var self = this, skipped = Y.merge(self.skipped), fn,
6447 failed = [], rreg = self.requireRegistration,
6450 oeach(skipped, function(k) {
6451 delete self.inserted[k];
6456 oeach(self.inserted, function(v, k) {
6457 var mod = self.getModule(k);
6458 if (mod && rreg && mod.type == JS && !(k in YUI.Env.mods)) {
6461 Y.mix(self.loaded, self.getProvides(k));
6465 fn = self.onSuccess;
6466 msg = (failed.length) ? 'notregistered' : 'success';
6467 success = !(failed.length);
6469 fn.call(self.context, {
6477 self._finish(msg, success);
6480 * The default Loader onProgress handler, calls this.onProgress with a payload
6481 * @method _onProgress
6484 _onProgress: function(e) {
6486 if (self.onProgress) {
6487 self.onProgress.call(self.context, {
6494 * The default Loader onFailure handler, calls this.onFailure with a payload
6495 * @method _onFailure
6498 _onFailure: function(o) {
6499 var f = this.onFailure, msg = [], i = 0, len = o.errors.length;
6501 for (i; i < len; i++) {
6502 msg.push(o.errors[i].error);
6505 msg = msg.join(',');
6509 f.call(this.context, {
6516 this._finish(msg, false);
6521 * The default Loader onTimeout handler, calls this.onTimeout with a payload
6522 * @method _onTimeout
6525 _onTimeout: function() {
6526 var f = this.onTimeout;
6528 f.call(this.context, {
6537 * Sorts the dependency tree. The last step of calculate()
6543 // create an indexed list
6544 var s = YObject.keys(this.required),
6545 // loaded = this.loaded,
6546 //TODO Move this out of scope
6548 p = 0, l, a, b, j, k, moved, doneKey;
6550 // keep going until we make a pass without moving anything
6556 // start the loop after items that are already sorted
6557 for (j = p; j < l; j++) {
6559 // check the next module on the list to see if its
6560 // dependencies have been met
6563 // check everything below current item and move if we
6564 // find a requirement for the current item
6565 for (k = j + 1; k < l; k++) {
6568 if (!done[doneKey] && this._requires(a, s[k])) {
6570 // extract the dependency so we can move it up
6573 // insert the dependency above the item that
6575 s.splice(j, 0, b[0]);
6577 // only swap two dependencies once to short circut
6578 // circular dependencies
6579 done[doneKey] = true;
6588 // jump out of loop if we moved something
6591 // this item is sorted, move our pointer and keep going
6597 // when we make it here and moved is false, we are
6609 * Handles the actual insertion of script/link tags
6612 * @param {Object} source The YUI instance the request came from
6613 * @param {Object} o The metadata to include
6614 * @param {String} type JS or CSS
6615 * @param {Boolean} [skipcalc=false] Do a Loader.calculate on the meta
6617 _insert: function(source, o, type, skipcalc) {
6620 // restore the state at the time of the request
6622 this._config(source);
6625 // build the dependency list
6626 // don't include type so we can process CSS and script in
6627 // one pass when the type is not specified.
6632 var modules = this.resolve(),
6633 self = this, comp = 0, actions = 0;
6636 //Filter out the opposite type and reset the array so the checks later work
6637 modules[((type === JS) ? CSS : JS)] = [];
6639 if (modules.js.length) {
6642 if (modules.css.length) {
6646 //console.log('Resolved Modules: ', modules);
6648 var complete = function(d) {
6650 var errs = {}, i = 0, u = '', fn;
6652 if (d && d.errors) {
6653 for (i = 0; i < d.errors.length; i++) {
6654 if (d.errors[i].request) {
6655 u = d.errors[i].request.url;
6663 if (d && d.data && d.data.length && (d.type === 'success')) {
6664 for (i = 0; i < d.data.length; i++) {
6665 self.inserted[d.data[i].name] = true;
6669 if (actions === comp) {
6670 self._loading = null;
6679 this._loading = true;
6681 if (!modules.js.length && !modules.css.length) {
6690 if (modules.css.length) { //Load CSS first
6691 Y.Get.css(modules.css, {
6692 data: modules.cssMods,
6693 attributes: self.cssAttributes,
6694 insertBefore: self.insertBefore,
6695 charset: self.charset,
6696 timeout: self.timeout,
6698 onProgress: function(e) {
6699 self._onProgress.call(self, e);
6701 onTimeout: function(d) {
6702 self._onTimeout.call(self, d);
6704 onSuccess: function(d) {
6706 d.fn = self._onSuccess;
6707 complete.call(self, d);
6709 onFailure: function(d) {
6711 d.fn = self._onFailure;
6712 complete.call(self, d);
6717 if (modules.js.length) {
6718 Y.Get.js(modules.js, {
6719 data: modules.jsMods,
6720 insertBefore: self.insertBefore,
6721 attributes: self.jsAttributes,
6722 charset: self.charset,
6723 timeout: self.timeout,
6727 onProgress: function(e) {
6728 self._onProgress.call(self, e);
6730 onTimeout: function(d) {
6731 self._onTimeout.call(self, d);
6733 onSuccess: function(d) {
6735 d.fn = self._onSuccess;
6736 complete.call(self, d);
6738 onFailure: function(d) {
6740 d.fn = self._onFailure;
6741 complete.call(self, d);
6747 * Once a loader operation is completely finished, process any additional queued items.
6751 _continue: function() {
6752 if (!(_queue.running) && _queue.size() > 0) {
6753 _queue.running = true;
6759 * inserts the requested modules and their dependencies.
6760 * <code>type</code> can be "js" or "css". Both script and
6761 * css are inserted if type is not provided.
6763 * @param {object} o optional options object.
6764 * @param {string} type the type of dependency to insert.
6766 insert: function(o, type, skipsort) {
6767 var self = this, copy = Y.merge(this);
6768 delete copy.require;
6770 _queue.add(function() {
6771 self._insert(copy, o, type, skipsort);
6777 * Executed every time a module is loaded, and if we are in a load
6778 * cycle, we attempt to load the next script. Public so that it
6779 * is possible to call this if using a method other than
6780 * Y.register to determine when scripts are fully loaded
6783 * @param {string} mname optional the name of the module that has
6784 * been loaded (which is usually why it is time to load the next
6787 loadNext: function(mname) {
6792 * Apply filter defined for this instance to a url/path
6794 * @param {string} u the string to filter.
6795 * @param {string} name the name of the module, if we are processing
6796 * a single module as opposed to a combined url.
6797 * @return {string} the filtered string.
6800 _filter: function(u, name, group) {
6801 var f = this.filter,
6802 hasFilter = name && (name in this.filters),
6803 modFilter = hasFilter && this.filters[name],
6804 groupName = group || (this.moduleInfo[name] ? this.moduleInfo[name].group : null);
6806 if (groupName && this.groups[groupName] && this.groups[groupName].filter) {
6807 modFilter = this.groups[groupName].filter;
6813 f = (L.isString(modFilter)) ?
6814 this.FILTER_DEFS[modFilter.toUpperCase()] || null :
6818 u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr);
6826 * Generates the full url for a module
6828 * @param {string} path the path fragment.
6829 * @param {String} name The name of the module
6830 * @param {String} [base=self.base] The base url to use
6831 * @return {string} the full url.
6834 _url: function(path, name, base) {
6835 return this._filter((base || this.base || '') + path, name);
6838 * Returns an Object hash of file arrays built from `loader.sorted` or from an arbitrary list of sorted modules.
6840 * @param {Boolean} [calc=false] Perform a loader.calculate() before anything else
6841 * @param {Array} [s=loader.sorted] An override for the loader.sorted array
6842 * @return {Object} Object hash (js and css) of two arrays of file lists
6843 * @example This method can be used as an off-line dep calculator
6846 * var loader = new Y.Loader({
6851 * require: ['node', 'dd', 'console']
6853 * var out = loader.resolve(true);
6856 resolve: function(calc, s) {
6858 var len, i, m, url, fn, msg, attr, group, groupName, j, frag,
6859 comboSource, comboSources, mods, comboBase,
6860 base, urls, u = [], tmpBase, baseLen, resCombos = {},
6861 self = this, comboSep, maxURLLength, singles = [],
6862 inserted = (self.ignoreRegistered) ? {} : self.inserted,
6863 resolved = { js: [], jsMods: [], css: [], cssMods: [] },
6864 type = self.loadType || 'js';
6869 s = s || self.sorted;
6871 var addSingle = function(m) {
6874 group = (m.group && self.groups[m.group]) || NOT_FOUND;
6876 //Always assume it's async
6877 if (group.async === false) {
6878 m.async = group.async;
6881 url = (m.fullpath) ? self._filter(m.fullpath, s[i]) :
6882 self._url(m.path, s[i], group.base || m.base);
6884 if (m.attributes || m.async === false) {
6890 url.attributes = m.attributes
6893 resolved[m.type].push(url);
6894 resolved[m.type + 'Mods'].push(m);
6902 // the default combo base
6903 comboBase = self.comboBase;
6909 for (i = 0; i < len; i++) {
6910 comboSource = comboBase;
6911 m = self.getModule(s[i]);
6912 groupName = m && m.group;
6913 group = self.groups[groupName];
6914 if (groupName && group) {
6916 if (!group.combine || m.fullpath) {
6917 //This is not a combo module, skip it and load it singly later.
6918 //singles.push(s[i]);
6923 if (group.comboBase) {
6924 comboSource = group.comboBase;
6927 if ("root" in group && L.isValue(group.root)) {
6928 m.root = group.root;
6930 m.comboSep = group.comboSep || self.comboSep;
6931 m.maxURLLength = group.maxURLLength || self.maxURLLength;
6933 if (!self.combine) {
6934 //This is not a combo module, skip it and load it singly later.
6935 //singles.push(s[i]);
6941 comboSources[comboSource] = comboSources[comboSource] || [];
6942 comboSources[comboSource].push(m);
6945 for (j in comboSources) {
6946 if (comboSources.hasOwnProperty(j)) {
6947 resCombos[j] = resCombos[j] || { js: [], jsMods: [], css: [], cssMods: [] };
6949 mods = comboSources[j];
6953 for (i = 0; i < len; i++) {
6954 if (inserted[mods[i]]) {
6958 // Do not try to combine non-yui JS unless combo def
6960 if (m && (m.combine || !m.ext)) {
6961 resCombos[j].comboSep = m.comboSep;
6962 resCombos[j].group = m.group;
6963 resCombos[j].maxURLLength = m.maxURLLength;
6964 frag = ((L.isValue(m.root)) ? m.root : self.root) + (m.path || m.fullpath);
6965 frag = self._filter(frag, m.name);
6966 resCombos[j][m.type].push(frag);
6967 resCombos[j][m.type + 'Mods'].push(m);
6969 //Add them to the next process..
6971 //singles.push(mods[i].name);
6982 for (j in resCombos) {
6984 comboSep = resCombos[base].comboSep || self.comboSep;
6985 maxURLLength = resCombos[base].maxURLLength || self.maxURLLength;
6986 for (type in resCombos[base]) {
6987 if (type === JS || type === CSS) {
6988 urls = resCombos[base][type];
6989 mods = resCombos[base][type + 'Mods'];
6991 tmpBase = base + urls.join(comboSep);
6992 baseLen = tmpBase.length;
6993 if (maxURLLength <= base.length) {
6994 maxURLLength = MAX_URL_LENGTH;
6998 if (baseLen > maxURLLength) {
7000 for (s = 0; s < len; s++) {
7002 tmpBase = base + u.join(comboSep);
7004 if (tmpBase.length > maxURLLength) {
7006 tmpBase = base + u.join(comboSep)
7007 resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
7015 tmpBase = base + u.join(comboSep);
7016 resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
7019 resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
7022 resolved[type + 'Mods'] = resolved[type + 'Mods'].concat(mods);
7032 Shortcut to calculate, resolve and load all modules.
7034 var loader = new Y.Loader({
7035 ignoreRegistered: true,
7043 loader.load(function() {
7044 console.log('All modules have loaded..');
7049 @param {Callback} cb Executed after all load operations are complete
7051 load: function(cb) {
7056 out = self.resolve(true);
7060 self.onEnd = function() {
7061 cb.apply(self.context || self, arguments);
7070 }, '3.5.1' ,{requires:['get', 'features']});
7071 YUI.add('loader-rollup', function(Y) {
7074 * Optional automatic rollup logic for reducing http connections
7075 * when not using a combo service.
7081 * Look for rollup packages to determine if all of the modules a
7082 * rollup supersedes are required. If so, include the rollup to
7083 * help reduce the total number of connections required. Called
7084 * by calculate(). This is an optional feature, and requires the
7085 * appropriate submodule to function.
7090 Y.Loader.prototype._rollup = function() {
7091 var i, j, m, s, r = this.required, roll,
7092 info = this.moduleInfo, rolled, c, smod;
7094 // find and cache rollup modules
7095 if (this.dirty || !this.rollups) {
7098 if (info.hasOwnProperty(i)) {
7099 m = this.getModule(i);
7100 // if (m && m.rollup && m.supersedes) {
7101 if (m && m.rollup) {
7102 this.rollups[i] = m;
7108 // make as many passes as needed to pick up rollup rollups
7112 // go through the rollup candidates
7113 for (i in this.rollups) {
7114 if (this.rollups.hasOwnProperty(i)) {
7115 // there can be only one, unless forced
7116 if (!r[i] && ((!this.loaded[i]) || this.forceMap[i])) {
7117 m = this.getModule(i);
7118 s = m.supersedes || [];
7121 // @TODO remove continue
7128 // check the threshold
7129 for (j = 0; j < s.length; j++) {
7132 // if the superseded module is loaded, we can't
7133 // load the rollup unless it has been forced.
7134 if (this.loaded[s[j]] && !this.forceMap[s[j]]) {
7137 // increment the counter if this module is required.
7138 // if we are beyond the rollup threshold, we will
7139 // use the rollup module
7140 } else if (r[s[j]] && m.type == smod.type) {
7142 roll = (c >= m.rollup);
7154 // expand the rollup's dependencies
7155 this.getRequires(m);
7161 // if we made it here w/o rolling up something, we are done
7169 }, '3.5.1' ,{requires:['loader-base']});
7170 YUI.add('loader-yui3', function(Y) {
7172 /* This file is auto-generated by src/loader/scripts/meta_join.py */
7175 * YUI 3 module metadata
7179 YUI.Env[Y.version].modules = YUI.Env[Y.version].modules || {
7218 "anim-node-plugin": {
7229 "anim-shape-transform": {
7260 "app-transitions": {
7265 "app-transitions-css": {
7268 "app-transitions-native": {
7270 "name": "app-transitions-native",
7271 "test": function (Y) {
7272 var doc = Y.config.doc,
7273 node = doc ? doc.documentElement : null;
7275 if (node && node.style) {
7276 return ('MozTransition' in node.style || 'WebkitTransition' in node.style);
7281 "trigger": "app-transitions"
7285 "app-transitions-css",
7310 "arraylist-filter": {
7338 "attribute-complex": {
7348 "attribute-events": {
7353 "attribute-extras": {
7360 "autocomplete-base",
7361 "autocomplete-sources",
7362 "autocomplete-list",
7363 "autocomplete-plugin"
7366 "autocomplete-base": {
7368 "autocomplete-sources"
7374 "event-valuechange",
7378 "autocomplete-filters": {
7384 "autocomplete-filters-accentfold": {
7391 "autocomplete-highlighters": {
7397 "autocomplete-highlighters-accentfold": {
7400 "highlight-accentfold"
7403 "autocomplete-list": {
7405 "autocomplete-sources"
7411 "autocomplete-base",
7418 "widget-position-align"
7422 "autocomplete-list-keys": {
7424 "name": "autocomplete-list-keys",
7425 "test": function (Y) {
7426 // Only add keyboard support to autocomplete-list if this doesn't appear to
7427 // be an iOS or Android-based mobile device.
7429 // There's currently no feasible way to actually detect whether a device has
7430 // a hardware keyboard, so this sniff will have to do. It can easily be
7431 // overridden by manually loading the autocomplete-list-keys module.
7433 // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
7434 // doesn't fire the keyboard events used by AutoCompleteList, so there's
7435 // no point loading the -keys module even when a bluetooth keyboard may be
7437 return !(Y.UA.ios || Y.UA.android);
7439 "trigger": "autocomplete-list"
7442 "autocomplete-list",
7446 "autocomplete-plugin": {
7448 "autocomplete-list",
7452 "autocomplete-sources": {
7489 "base-pluginhost": {
7579 "datatype-date-math",
7584 "calendarnavigator": {
7618 "classnamemanager": {
7650 "console-filters": {
7667 "createlink-base": {
7683 "cssbase-context": {
7700 "cssfonts-context": {
7730 "cssreset-context": {
7742 "dataschema-array": {
7747 "dataschema-base": {
7752 "dataschema-json": {
7758 "dataschema-text": {
7773 "datasource-function",
7775 "datasource-jsonschema",
7776 "datasource-xmlschema",
7777 "datasource-arrayschema",
7778 "datasource-textschema",
7779 "datasource-polling"
7782 "datasource-arrayschema": {
7789 "datasource-cache": {
7796 "datasource-function": {
7813 "datasource-jsonschema": {
7820 "datasource-local": {
7825 "datasource-polling": {
7830 "datasource-textschema": {
7837 "datasource-xmlschema": {
7850 "datatable-column-widths",
7851 "datatable-message",
7852 "datatable-mutable",
7854 "datatable-datasource"
7867 "datatable-base-deprecated": {
7883 "datatable-column-widths": {
7892 "node-event-delegate"
7895 "datatable-datasource": {
7902 "datatable-datasource-deprecated": {
7904 "datatable-base-deprecated",
7909 "datatable-deprecated": {
7911 "datatable-base-deprecated",
7912 "datatable-datasource-deprecated",
7913 "datatable-sort-deprecated",
7914 "datatable-scroll-deprecated"
7924 "datatable-message": {
7933 "datatable-mutable": {
7938 "datatable-scroll": {
7941 "datatable-column-widths",
7946 "datatable-scroll-deprecated": {
7948 "datatable-base-deprecated",
7961 "datatable-sort-deprecated": {
7966 "datatable-base-deprecated",
7980 "datatype-date-format"
7983 "datatype-date-parse",
7984 "datatype-date-format"
7987 "datatype-date-format": {
8071 "datatype-date-math": {
8076 "datatype-date-parse": {},
8077 "datatype-number": {
8079 "datatype-number-parse",
8080 "datatype-number-format"
8083 "datatype-number-format": {},
8084 "datatype-number-parse": {},
8087 "datatype-xml-parse",
8088 "datatype-xml-format"
8091 "datatype-xml-format": {},
8092 "datatype-xml-parse": {},
8155 "name": "dd-gestures",
8156 "test": function(Y) {
8157 return ((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.chrome && Y.UA.chrome < 6));
8159 "trigger": "dd-drag"
8241 "name": "dom-style-ie",
8242 "test": function (Y) {
8244 var testFeature = Y.Features.test,
8245 addFeature = Y.Features.add,
8246 WINDOW = Y.config.win,
8247 DOCUMENT = Y.config.doc,
8248 DOCUMENT_ELEMENT = 'documentElement',
8251 addFeature('style', 'computedStyle', {
8253 return WINDOW && 'getComputedStyle' in WINDOW;
8257 addFeature('style', 'opacity', {
8259 return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
8263 ret = (!testFeature('style', 'opacity') &&
8264 !testFeature('style', 'computedStyle'));
8268 "trigger": "dom-style"
8321 "editor-para-base": {
8328 "name": "editor-para-ie",
8329 "trigger": "editor-para",
8337 "editor-selection": {
8386 "name": "event-base-ie",
8387 "test": function(Y) {
8388 var imp = Y.config.doc && Y.config.doc.implementation;
8389 return (imp && (!imp.hasFeature('Events', '2.0')));
8391 "trigger": "node-base"
8397 "event-contextmenu": {
8405 "event-custom-base",
8406 "event-custom-complex"
8409 "event-custom-base": {
8414 "event-custom-complex": {
8452 "event-mouseenter": {
8457 "event-mousewheel": {
8485 "event-synthetic": {
8488 "event-custom-complex"
8496 "event-valuechange": {
8550 "graphics-canvas": {
8552 "name": "graphics-canvas",
8553 "test": function(Y) {
8554 var DOCUMENT = Y.config.doc,
8555 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
8556 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
8557 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
8558 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
8560 "trigger": "graphics"
8566 "graphics-canvas-default": {
8568 "name": "graphics-canvas-default",
8569 "test": function(Y) {
8570 var DOCUMENT = Y.config.doc,
8571 useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
8572 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
8573 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
8574 return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
8576 "trigger": "graphics"
8581 "name": "graphics-svg",
8582 "test": function(Y) {
8583 var DOCUMENT = Y.config.doc,
8584 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
8585 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
8586 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
8588 return svg && (useSVG || !canvas);
8590 "trigger": "graphics"
8596 "graphics-svg-default": {
8598 "name": "graphics-svg-default",
8599 "test": function(Y) {
8600 var DOCUMENT = Y.config.doc,
8601 useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
8602 canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
8603 svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
8605 return svg && (useSVG || !canvas);
8607 "trigger": "graphics"
8612 "name": "graphics-vml",
8613 "test": function(Y) {
8614 var DOCUMENT = Y.config.doc,
8615 canvas = DOCUMENT && DOCUMENT.createElement("canvas");
8616 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
8618 "trigger": "graphics"
8624 "graphics-vml-default": {
8626 "name": "graphics-vml-default",
8627 "test": function(Y) {
8628 var DOCUMENT = Y.config.doc,
8629 canvas = DOCUMENT && DOCUMENT.createElement("canvas");
8630 return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
8632 "trigger": "graphics"
8637 "handlebars-compiler"
8640 "handlebars-base": {
8645 "handlebars-compiler": {
8653 "highlight-accentfold"
8656 "highlight-accentfold": {
8680 "event-custom-complex"
8693 "history-hash-ie": {
8695 "name": "history-hash-ie",
8696 "test": function (Y) {
8697 var docMode = Y.config.doc && Y.config.doc.documentMode;
8699 return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
8700 !docMode || docMode < 8);
8702 "trigger": "history-hash"
8748 "event-custom-base",
8749 "querystring-stringify-simple"
8760 "name": "io-nodejs",
8761 "trigger": "io-base",
8774 "io-upload-iframe": {
8783 "datatype-xml-parse"
8862 "node-event-delegate",
8881 "node-deprecated": {
8886 "node-event-delegate": {
8892 "node-event-html5": {
8897 "node-event-simulate": {
8912 "node-focusmanager": {
8917 "node-event-simulate",
8937 "node-pluginhost": {
8965 "widget-position-align",
8967 "widget-position-constrain"
8978 "widget-position-align",
8979 "widget-position-constrain",
8999 "node-event-delegate",
9021 "pluginhost-base": {
9026 "pluginhost-config": {
9038 "querystring-parse",
9039 "querystring-stringify"
9042 "querystring-parse": {
9048 "querystring-parse-simple": {
9053 "querystring-stringify": {
9058 "querystring-stringify-simple": {
9071 "slider-value-range",
9089 "recordset-filter": {
9096 "recordset-indexer": {
9129 "resize-constrain": {
9169 "scrollview-scrollbars"
9172 "scrollview-base": {
9181 "scrollview-base-ie": {
9183 "name": "scrollview-base-ie",
9184 "trigger": "scrollview-base",
9191 "scrollview-list": {
9198 "scrollview-paginator": {
9203 "scrollview-scrollbars": {
9218 "name": "selector-css2",
9219 "test": function (Y) {
9220 var DOCUMENT = Y.config.doc,
9221 ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
9225 "trigger": "selector"
9237 "selector-native": {
9251 "slider-value-range",
9265 "slider-value-range": {
9277 "sortable-scroll": {
9322 "node-event-delegate",
9354 "text-accentfold": {
9357 "text-data-accentfold"
9360 "text-data-accentfold": {
9365 "text-data-wordbreak": {
9373 "text-data-wordbreak"
9381 "transition-timer": {
9383 "name": "transition-timer",
9384 "test": function (Y) {
9385 var DOCUMENT = Y.config.doc,
9386 node = (DOCUMENT) ? DOCUMENT.documentElement: null,
9389 if (node && node.style) {
9390 ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style);
9395 "trigger": "transition"
9407 "uploader-deprecated": {
9431 "node-event-simulate",
9445 "node-event-delegate"
9456 "widget-htmlparser",
9468 "widget-autohide": {
9490 "name": "widget-base-ie",
9491 "trigger": "widget-base",
9511 "widget-htmlparser": {
9521 "widget-modality": {
9536 "widget-position": {
9543 "widget-position-align": {
9548 "widget-position-constrain": {
9571 "widget-uievents": {
9573 "node-event-delegate",
9602 YUI.Env[Y.version].md5 = 'f5a3bc9bda2441a3b15fb52c567fc1f7';
9605 }, '3.5.1' ,{requires:['loader-base']});
9608 YUI.add('yui', function(Y){}, '3.5.1' ,{use:['yui-base','get','features','intl-base','yui-log','yui-log-nodejs','yui-later','loader-base', 'loader-rollup', 'loader-yui3']});