NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / yui-core / yui-core-debug.js
blob1d0b8b656ea69cac9f0dade7a1b4633a0ab2ed00
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 /**
9 The YUI module contains the components required for building the YUI seed file.
10 This includes the script loading mechanism, a simple queue, and the core
11 utilities for the library.
13 @module yui
14 @main yui
15 @submodule yui-base
16 **/
18 /*jshint eqeqeq: false*/
19 if (typeof YUI != 'undefined') {
20     YUI._YUI = YUI;
23 /**
24 The YUI global namespace object. This is the constructor for all YUI instances.
26 This is a self-instantiable factory function, meaning you don't need to precede
27 it with the `new` operator. You can invoke it directly like this:
29     YUI().use('*', function (Y) {
30         // Y is a new YUI instance.
31     });
33 But it also works like this:
35     var Y = YUI();
37 The `YUI` constructor accepts an optional config object, like this:
39     YUI({
40         debug: true,
41         combine: false
42     }).use('node', function (Y) {
43         // Y.Node is ready to use.
44     });
46 See the API docs for the <a href="config.html">Config</a> class for the complete
47 list of supported configuration properties accepted by the YUI constuctor.
49 If a global `YUI` object is already defined, the existing YUI object will not be
50 overwritten, to ensure that defined namespaces are preserved.
52 Each YUI instance has full custom event support, but only if the event system is
53 available.
55 @class YUI
56 @uses EventTarget
57 @constructor
58 @global
59 @param {Object} [config]* Zero or more optional configuration objects. Config
60     values are stored in the `Y.config` property. See the
61     <a href="config.html">Config</a> docs for the list of supported properties.
62 **/
64     /*global YUI*/
65     /*global YUI_config*/
66     var YUI = function() {
67         var i = 0,
68             Y = this,
69             args = arguments,
70             l = args.length,
71             instanceOf = function(o, type) {
72                 return (o && o.hasOwnProperty && (o instanceof type));
73             },
74             gconf = (typeof YUI_config !== 'undefined') && YUI_config;
76         if (!(instanceOf(Y, YUI))) {
77             Y = new YUI();
78         } else {
79             // set up the core environment
80             Y._init();
82             /**
83             Master configuration that might span multiple contexts in a non-
84             browser environment. It is applied first to all instances in all
85             contexts.
87             @example
89                 YUI.GlobalConfig = {
90                     filter: 'debug'
91                 };
93                 YUI().use('node', function (Y) {
94                     // debug files used here
95                 });
97                 YUI({
98                     filter: 'min'
99                 }).use('node', function (Y) {
100                     // min files used here
101                 });
103             @property {Object} GlobalConfig
104             @global
105             @static
106             **/
107             if (YUI.GlobalConfig) {
108                 Y.applyConfig(YUI.GlobalConfig);
109             }
111             /**
112             Page-level config applied to all YUI instances created on the
113             current page. This is applied after `YUI.GlobalConfig` and before
114             any instance-level configuration.
116             @example
118                 // Single global var to include before YUI seed file
119                 YUI_config = {
120                     filter: 'debug'
121                 };
123                 YUI().use('node', function (Y) {
124                     // debug files used here
125                 });
127                 YUI({
128                     filter: 'min'
129                 }).use('node', function (Y) {
130                     // min files used here
131                 });
133             @property {Object} YUI_config
134             @global
135             **/
136             if (gconf) {
137                 Y.applyConfig(gconf);
138             }
140             // bind the specified additional modules for this instance
141             if (!l) {
142                 Y._setup();
143             }
144         }
146         if (l) {
147             // Each instance can accept one or more configuration objects.
148             // These are applied after YUI.GlobalConfig and YUI_Config,
149             // overriding values set in those config files if there is a
150             // matching property.
151             for (; i < l; i++) {
152                 Y.applyConfig(args[i]);
153             }
155             Y._setup();
156         }
158         Y.instanceOf = instanceOf;
160         return Y;
161     };
163 (function() {
165     var proto, prop,
166         VERSION = '3.13.0',
167         PERIOD = '.',
168         BASE = 'http://yui.yahooapis.com/',
169         /*
170             These CSS class names can't be generated by
171             getClassName since it is not available at the
172             time they are being used.
173         */
174         DOC_LABEL = 'yui3-js-enabled',
175         CSS_STAMP_EL = 'yui3-css-stamp',
176         NOOP = function() {},
177         SLICE = Array.prototype.slice,
178         APPLY_TO_AUTH = { 'io.xdrReady': 1,   // the functions applyTo
179                           'io.xdrResponse': 1,   // can call. this should
180                           'SWF.eventHandler': 1 }, // be done at build time
181         hasWin = (typeof window != 'undefined'),
182         win = (hasWin) ? window : null,
183         doc = (hasWin) ? win.document : null,
184         docEl = doc && doc.documentElement,
185         docClass = docEl && docEl.className,
186         instances = {},
187         time = new Date().getTime(),
188         add = function(el, type, fn, capture) {
189             if (el && el.addEventListener) {
190                 el.addEventListener(type, fn, capture);
191             } else if (el && el.attachEvent) {
192                 el.attachEvent('on' + type, fn);
193             }
194         },
195         remove = function(el, type, fn, capture) {
196             if (el && el.removeEventListener) {
197                 // this can throw an uncaught exception in FF
198                 try {
199                     el.removeEventListener(type, fn, capture);
200                 } catch (ex) {}
201             } else if (el && el.detachEvent) {
202                 el.detachEvent('on' + type, fn);
203             }
204         },
205         handleLoad = function() {
206             YUI.Env.windowLoaded = true;
207             YUI.Env.DOMReady = true;
208             if (hasWin) {
209                 remove(window, 'load', handleLoad);
210             }
211         },
212         getLoader = function(Y, o) {
213             var loader = Y.Env._loader,
214                 lCore = [ 'loader-base' ],
215                 G_ENV = YUI.Env,
216                 mods = G_ENV.mods;
218             if (loader) {
219                 //loader._config(Y.config);
220                 loader.ignoreRegistered = false;
221                 loader.onEnd = null;
222                 loader.data = null;
223                 loader.required = [];
224                 loader.loadType = null;
225             } else {
226                 loader = new Y.Loader(Y.config);
227                 Y.Env._loader = loader;
228             }
229             if (mods && mods.loader) {
230                 lCore = [].concat(lCore, YUI.Env.loaderExtras);
231             }
232             YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
234             return loader;
235         },
237         clobber = function(r, s) {
238             for (var i in s) {
239                 if (s.hasOwnProperty(i)) {
240                     r[i] = s[i];
241                 }
242             }
243         },
245         ALREADY_DONE = { success: true };
247 //  Stamp the documentElement (HTML) with a class of "yui-loaded" to
248 //  enable styles that need to key off of JS being enabled.
249 if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
250     if (docClass) {
251         docClass += ' ';
252     }
253     docClass += DOC_LABEL;
254     docEl.className = docClass;
257 if (VERSION.indexOf('@') > -1) {
258     VERSION = '3.5.0'; // dev time hack for cdn test
261 proto = {
262     /**
263     Applies a new configuration object to the config of this YUI instance. This
264     will merge new group/module definitions, and will also update the loader
265     cache if necessary. Updating `Y.config` directly will not update the cache.
267     @method applyConfig
268     @param {Object} o the configuration object.
269     @since 3.2.0
270     **/
271     applyConfig: function(o) {
273         o = o || NOOP;
275         var attr,
276             name,
277             // detail,
278             config = this.config,
279             mods = config.modules,
280             groups = config.groups,
281             aliases = config.aliases,
282             loader = this.Env._loader;
284         for (name in o) {
285             if (o.hasOwnProperty(name)) {
286                 attr = o[name];
287                 if (mods && name == 'modules') {
288                     clobber(mods, attr);
289                 } else if (aliases && name == 'aliases') {
290                     clobber(aliases, attr);
291                 } else if (groups && name == 'groups') {
292                     clobber(groups, attr);
293                 } else if (name == 'win') {
294                     config[name] = (attr && attr.contentWindow) || attr;
295                     config.doc = config[name] ? config[name].document : null;
296                 } else if (name == '_yuid') {
297                     // preserve the guid
298                 } else {
299                     config[name] = attr;
300                 }
301             }
302         }
304         if (loader) {
305             loader._config(o);
306         }
308     },
310     /**
311     Old way to apply a config to this instance (calls `applyConfig` under the
312     hood).
314     @private
315     @method _config
316     @param {Object} o The config to apply
317     **/
318     _config: function(o) {
319         this.applyConfig(o);
320     },
322     /**
323     Initializes this YUI instance.
325     @private
326     @method _init
327     **/
328     _init: function() {
329         var filter, el,
330             Y = this,
331             G_ENV = YUI.Env,
332             Env = Y.Env,
333             prop;
335         /**
336         The version number of this YUI instance.
338         This value is typically updated by a script when a YUI release is built,
339         so it may not reflect the correct version number when YUI is run from
340         the development source tree.
342         @property {String} version
343         **/
344         Y.version = VERSION;
346         if (!Env) {
347             Y.Env = {
348                 core: ['intl-base'],
349                 loaderExtras: ['loader-rollup', 'loader-yui3'],
350                 mods: {}, // flat module map
351                 versions: {}, // version module map
352                 base: BASE,
353                 cdn: BASE + VERSION + '/build/',
354                 // bootstrapped: false,
355                 _idx: 0,
356                 _used: {},
357                 _attached: {},
358                 _missed: [],
359                 _yidx: 0,
360                 _uidx: 0,
361                 _guidp: 'y',
362                 _loaded: {},
363                 // serviced: {},
364                 // Regex in English:
365                 // I'll start at the \b(yui).
366                 // 1. Look in the test string for "yui" or
367                 //    "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break.  That is, it
368                 //    can't match "foyui" or "i_heart_yui". This can be anywhere in the string.
369                 // 2. After #1 must come a forward slash followed by the string matched in #1, so
370                 //    "yui-base/yui-base" or "yui-pants/yui-pants".
371                 // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
372                 //    so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
373                 // 4. This is followed by ".js", so "yui/yui.js".
374                 // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
375                 //    then capture the junk between the LAST "&" and the string in 1-4.  So
376                 //    "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
377                 //    will capture "3.3.0/build/"
378                 //
379                 // Regex Exploded:
380                 // (?:\?             Find a ?
381                 //   (?:[^&]*&)      followed by 0..n characters followed by an &
382                 //   *               in fact, find as many sets of characters followed by a & as you can
383                 //   ([^&]*)         capture the stuff after the last & in \1
384                 // )?                but it's ok if all this ?junk&more_junk stuff isn't even there
385                 // \b(               after a word break find either the string
386                 //    yui(?:-\w+)?   "yui" optionally followed by a -, then more characters
387                 // )                 and store the yui-* string in \2
388                 // \/\2              then comes a / followed by the yui-* string in \2
389                 // (?:-(min|debug))? optionally followed by "-min" or "-debug"
390                 // .js               and ending in ".js"
391                 _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
392                 parseBasePath: function(src, pattern) {
393                     var match = src.match(pattern),
394                         path, filter;
396                     if (match) {
397                         path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
399                         // this is to set up the path to the loader.  The file
400                         // filter for loader should match the yui include.
401                         filter = match[3];
403                         // extract correct path for mixed combo urls
404                         // http://yuilibrary.com/projects/yui3/ticket/2528423
405                         if (match[1]) {
406                             path += '?' + match[1];
407                         }
408                         path = {
409                             filter: filter,
410                             path: path
411                         };
412                     }
413                     return path;
414                 },
415                 getBase: G_ENV && G_ENV.getBase ||
416                         function(pattern) {
417                             var nodes = (doc && doc.getElementsByTagName('script')) || [],
418                                 path = Env.cdn, parsed,
419                                 i, len, src;
421                             for (i = 0, len = nodes.length; i < len; ++i) {
422                                 src = nodes[i].src;
423                                 if (src) {
424                                     parsed = Y.Env.parseBasePath(src, pattern);
425                                     if (parsed) {
426                                         filter = parsed.filter;
427                                         path = parsed.path;
428                                         break;
429                                     }
430                                 }
431                             }
433                             // use CDN default
434                             return path;
435                         }
437             };
439             Env = Y.Env;
441             Env._loaded[VERSION] = {};
443             if (G_ENV && Y !== YUI) {
444                 Env._yidx = ++G_ENV._yidx;
445                 Env._guidp = ('yui_' + VERSION + '_' +
446                              Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_');
447             } else if (YUI._YUI) {
449                 G_ENV = YUI._YUI.Env;
450                 Env._yidx += G_ENV._yidx;
451                 Env._uidx += G_ENV._uidx;
453                 for (prop in G_ENV) {
454                     if (!(prop in Env)) {
455                         Env[prop] = G_ENV[prop];
456                     }
457                 }
459                 delete YUI._YUI;
460             }
462             Y.id = Y.stamp(Y);
463             instances[Y.id] = Y;
465         }
467         Y.constructor = YUI;
469         // configuration defaults
470         Y.config = Y.config || {
471             bootstrap: true,
472             cacheUse: true,
473             debug: true,
474             doc: doc,
475             fetchCSS: true,
476             throwFail: true,
477             useBrowserConsole: true,
478             useNativeES5: true,
479             win: win,
480             global: Function('return this')()
481         };
483         //Register the CSS stamp element
484         if (doc && !doc.getElementById(CSS_STAMP_EL)) {
485             el = doc.createElement('div');
486             el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
487             YUI.Env.cssStampEl = el.firstChild;
488             if (doc.body) {
489                 doc.body.appendChild(YUI.Env.cssStampEl);
490             } else {
491                 docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
492             }
493         } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) {
494             YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL);
495         }
497         Y.config.lang = Y.config.lang || 'en-US';
499         Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
501         if (!filter || (!('mindebug').indexOf(filter))) {
502             filter = 'min';
503         }
504         filter = (filter) ? '-' + filter : filter;
505         Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
507     },
509     /**
510     Finishes the instance setup. Attaches whatever YUI modules were defined
511     at the time that this instance was created.
513     @method _setup
514     @private
515     **/
516     _setup: function() {
517         var i, Y = this,
518             core = [],
519             mods = YUI.Env.mods,
520             extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
522         for (i = 0; i < extras.length; i++) {
523             if (mods[extras[i]]) {
524                 core.push(extras[i]);
525             }
526         }
528         Y._attach(['yui-base']);
529         Y._attach(core);
531         if (Y.Loader) {
532             getLoader(Y);
533         }
535         // Y.log(Y.id + ' initialized', 'info', 'yui');
536     },
538     /**
539     Executes the named method on the specified YUI instance if that method is
540     whitelisted.
542     @method applyTo
543     @param {String} id YUI instance id.
544     @param {String} method Name of the method to execute. For example:
545         'Object.keys'.
546     @param {Array} args Arguments to apply to the method.
547     @return {Mixed} Return value from the applied method, or `null` if the
548         specified instance was not found or the method was not whitelisted.
549     **/
550     applyTo: function(id, method, args) {
551         if (!(method in APPLY_TO_AUTH)) {
552             this.log(method + ': applyTo not allowed', 'warn', 'yui');
553             return null;
554         }
556         var instance = instances[id], nest, m, i;
557         if (instance) {
558             nest = method.split('.');
559             m = instance;
560             for (i = 0; i < nest.length; i = i + 1) {
561                 m = m[nest[i]];
562                 if (!m) {
563                     this.log('applyTo not found: ' + method, 'warn', 'yui');
564                 }
565             }
566             return m && m.apply(instance, args);
567         }
569         return null;
570     },
573 Registers a YUI module and makes it available for use in a `YUI().use()` call or
574 as a dependency for other modules.
576 The easiest way to create a first-class YUI module is to use
577 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
578 tool.
580 Shifter will automatically wrap your module code in a `YUI.add()` call along
581 with any configuration info required for the module.
583 @example
585     YUI.add('davglass', function (Y) {
586         Y.davglass = function () {
587             Y.log('Dav was here!');
588         };
589     }, '3.4.0', {
590         requires: ['harley-davidson', 'mt-dew']
591     });
593 @method add
594 @param {String} name Module name.
595 @param {Function} fn Function containing module code. This function will be
596     executed whenever the module is attached to a specific YUI instance.
598     @param {YUI} fn.Y The YUI instance to which this module is attached.
599     @param {String} fn.name Name of the module
601 @param {String} version Module version number. This is currently used only for
602     informational purposes, and is not used internally by YUI.
604 @param {Object} [config] Module config.
605     @param {Array} [config.requires] Array of other module names that must be
606         attached before this module can be attached.
607     @param {Array} [config.optional] Array of optional module names that should
608         be attached before this module is attached if they've already been
609         loaded. If the `loadOptional` YUI option is `true`, optional modules
610         that have not yet been loaded will be loaded just as if they were hard
611         requirements.
612     @param {Array} [config.use] Array of module names that are included within
613         or otherwise provided by this module, and which should be attached
614         automatically when this module is attached. This makes it possible to
615         create "virtual rollup" modules that simply attach a collection of other
616         modules or submodules.
618 @return {YUI} This YUI instance.
620     add: function(name, fn, version, details) {
621         details = details || {};
622         var env = YUI.Env,
623             mod = {
624                 name: name,
625                 fn: fn,
626                 version: version,
627                 details: details
628             },
629             //Instance hash so we don't apply it to the same instance twice
630             applied = {},
631             loader, inst,
632             i, versions = env.versions;
634         env.mods[name] = mod;
635         versions[version] = versions[version] || {};
636         versions[version][name] = mod;
638         for (i in instances) {
639             if (instances.hasOwnProperty(i)) {
640                 inst = instances[i];
641                 if (!applied[inst.id]) {
642                     applied[inst.id] = true;
643                     loader = inst.Env._loader;
644                     if (loader) {
645                         if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
646                             loader.addModule(details, name);
647                         }
648                     }
649                 }
650             }
651         }
653         return this;
654     },
656     /**
657     Executes the callback function associated with each required module,
658     attaching the module to this YUI instance.
660     @method _attach
661     @param {Array} r The array of modules to attach
662     @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
663         is not attached.
664     @private
665     **/
666     _attach: function(r, moot) {
667         var i, name, mod, details, req, use, after,
668             mods = YUI.Env.mods,
669             aliases = YUI.Env.aliases,
670             Y = this, j,
671             cache = YUI.Env._renderedMods,
672             loader = Y.Env._loader,
673             done = Y.Env._attached,
674             len = r.length, loader, def, go,
675             c = [];
677         //Check for conditional modules (in a second+ instance) and add their requirements
678         //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
679         for (i = 0; i < len; i++) {
680             name = r[i];
681             mod = mods[name];
682             c.push(name);
683             if (loader && loader.conditions[name]) {
684                 for (j in loader.conditions[name]) {
685                     if (loader.conditions[name].hasOwnProperty(j)) {
686                         def = loader.conditions[name][j];
687                         go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
688                         if (go) {
689                             c.push(def.name);
690                         }
691                     }
692                 }
693             }
694         }
695         r = c;
696         len = r.length;
698         for (i = 0; i < len; i++) {
699             if (!done[r[i]]) {
700                 name = r[i];
701                 mod = mods[name];
703                 if (aliases && aliases[name] && !mod) {
704                     Y._attach(aliases[name]);
705                     continue;
706                 }
707                 if (!mod) {
708                     if (loader && loader.moduleInfo[name]) {
709                         mod = loader.moduleInfo[name];
710                         moot = true;
711                     }
713                     // Y.log('no js def for: ' + name, 'info', 'yui');
715                     //if (!loader || !loader.moduleInfo[name]) {
716                     //if ((!loader || !loader.moduleInfo[name]) && !moot) {
717                     if (!moot && name) {
718                         if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
719                             Y.Env._missed.push(name);
720                             Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
721                             Y.message('NOT loaded: ' + name, 'warn', 'yui');
722                         }
723                     }
724                 } else {
725                     done[name] = true;
726                     //Don't like this, but in case a mod was asked for once, then we fetch it
727                     //We need to remove it from the missed list ^davglass
728                     for (j = 0; j < Y.Env._missed.length; j++) {
729                         if (Y.Env._missed[j] === name) {
730                             Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
731                             Y.Env._missed.splice(j, 1);
732                         }
733                     }
734                     /*
735                         If it's a temp module, we need to redo it's requirements if it's already loaded
736                         since it may have been loaded by another instance and it's dependencies might
737                         have been redefined inside the fetched file.
738                     */
739                     if (loader && cache && cache[name] && cache[name].temp) {
740                         loader.getRequires(cache[name]);
741                         req = [];
742                         for (j in loader.moduleInfo[name].expanded_map) {
743                             if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
744                                 req.push(j);
745                             }
746                         }
747                         Y._attach(req);
748                     }
750                     details = mod.details;
751                     req = details.requires;
752                     use = details.use;
753                     after = details.after;
754                     //Force Intl load if there is a language (Loader logic) @todo fix this shit
755                     if (details.lang) {
756                         req = req || [];
757                         req.unshift('intl');
758                     }
760                     if (req) {
761                         for (j = 0; j < req.length; j++) {
762                             if (!done[req[j]]) {
763                                 if (!Y._attach(req)) {
764                                     return false;
765                                 }
766                                 break;
767                             }
768                         }
769                     }
771                     if (after) {
772                         for (j = 0; j < after.length; j++) {
773                             if (!done[after[j]]) {
774                                 if (!Y._attach(after, true)) {
775                                     return false;
776                                 }
777                                 break;
778                             }
779                         }
780                     }
782                     if (mod.fn) {
783                             if (Y.config.throwFail) {
784                                 mod.fn(Y, name);
785                             } else {
786                                 try {
787                                     mod.fn(Y, name);
788                                 } catch (e) {
789                                     Y.error('Attach error: ' + name, e, name);
790                                 return false;
791                             }
792                         }
793                     }
795                     if (use) {
796                         for (j = 0; j < use.length; j++) {
797                             if (!done[use[j]]) {
798                                 if (!Y._attach(use)) {
799                                     return false;
800                                 }
801                                 break;
802                             }
803                         }
804                     }
808                 }
809             }
810         }
812         return true;
813     },
815     /**
816     Delays the `use` callback until another event has taken place such as
817     `window.onload`, `domready`, `contentready`, or `available`.
819     @private
820     @method _delayCallback
821     @param {Function} cb The original `use` callback.
822     @param {String|Object} until Either an event name ('load', 'domready', etc.)
823         or an object containing event/args keys for contentready/available.
824     @return {Function}
825     **/
826     _delayCallback: function(cb, until) {
828         var Y = this,
829             mod = ['event-base'];
831         until = (Y.Lang.isObject(until) ? until : { event: until });
833         if (until.event === 'load') {
834             mod.push('event-synthetic');
835         }
837         Y.log('Delaying use callback until: ' + until.event, 'info', 'yui');
838         return function() {
839             Y.log('Use callback fired, waiting on delay', 'info', 'yui');
840             var args = arguments;
841             Y._use(mod, function() {
842                 Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui');
843                 Y.on(until.event, function() {
844                     args[1].delayUntil = until.event;
845                     Y.log('Delayed use callback done after ' + until.event, 'info', 'yui');
846                     cb.apply(Y, args);
847                 }, until.args);
848             });
849         };
850     },
852     /**
853     Attaches one or more modules to this YUI instance. When this is executed,
854     the requirements of the desired modules are analyzed, and one of several
855     things can happen:
858       * All required modules have already been loaded, and just need to be
859         attached to this YUI instance. In this case, the `use()` callback will
860         be executed synchronously after the modules are attached.
862       * One or more modules have not yet been loaded, or the Get utility is not
863         available, or the `bootstrap` config option is `false`. In this case,
864         a warning is issued indicating that modules are missing, but all
865         available modules will still be attached and the `use()` callback will
866         be executed synchronously.
868       * One or more modules are missing and the Loader is not available but the
869         Get utility is, and `bootstrap` is not `false`. In this case, the Get
870         utility will be used to load the Loader, and we will then proceed to
871         the following state:
873       * One or more modules are missing and the Loader is available. In this
874         case, the Loader will be used to resolve the dependency tree for the
875         missing modules and load them and their dependencies. When the Loader is
876         finished loading modules, the `use()` callback will be executed
877         asynchronously.
879     @example
881         // Loads and attaches dd and its dependencies.
882         YUI().use('dd', function (Y) {
883             // ...
884         });
886         // Loads and attaches dd and node as well as all of their dependencies.
887         YUI().use(['dd', 'node'], function (Y) {
888             // ...
889         });
891         // Attaches all modules that have already been loaded.
892         YUI().use('*', function (Y) {
893             // ...
894         });
896         // Attaches a gallery module.
897         YUI().use('gallery-yql', function (Y) {
898             // ...
899         });
901         // Attaches a YUI 2in3 module.
902         YUI().use('yui2-datatable', function (Y) {
903             // ...
904         });
906     @method use
907     @param {String|Array} modules* One or more module names to attach.
908     @param {Function} [callback] Callback function to be executed once all
909         specified modules and their dependencies have been attached.
910     @param {YUI} callback.Y The YUI instance created for this sandbox.
911     @param {Object} callback.status Object containing `success`, `msg` and
912         `data` properties.
913     @chainable
914     **/
915     use: function() {
916         var args = SLICE.call(arguments, 0),
917             callback = args[args.length - 1],
918             Y = this,
919             i = 0,
920             name,
921             Env = Y.Env,
922             provisioned = true;
924         // The last argument supplied to use can be a load complete callback
925         if (Y.Lang.isFunction(callback)) {
926             args.pop();
927             if (Y.config.delayUntil) {
928                 callback = Y._delayCallback(callback, Y.config.delayUntil);
929             }
930         } else {
931             callback = null;
932         }
933         if (Y.Lang.isArray(args[0])) {
934             args = args[0];
935         }
937         if (Y.config.cacheUse) {
938             while ((name = args[i++])) {
939                 if (!Env._attached[name]) {
940                     provisioned = false;
941                     break;
942                 }
943             }
945             if (provisioned) {
946                 if (args.length) {
947                     Y.log('already provisioned: ' + args, 'info', 'yui');
948                 }
949                 Y._notify(callback, ALREADY_DONE, args);
950                 return Y;
951             }
952         }
954         if (Y._loading) {
955             Y._useQueue = Y._useQueue || new Y.Queue();
956             Y._useQueue.add([args, callback]);
957         } else {
958             Y._use(args, function(Y, response) {
959                 Y._notify(callback, response, args);
960             });
961         }
963         return Y;
964     },
966     /**
967     Handles Loader notifications about attachment/load errors.
969     @method _notify
970     @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
971     @param {Object} response Response returned from Loader.
972     @param {Array} args Arguments passed from Loader.
973     @private
974     **/
975     _notify: function(callback, response, args) {
976         if (!response.success && this.config.loadErrorFn) {
977             this.config.loadErrorFn.call(this, this, callback, response, args);
978         } else if (callback) {
979             if (this.Env._missed && this.Env._missed.length) {
980                 response.msg = 'Missing modules: ' + this.Env._missed.join();
981                 response.success = false;
982             }
983             if (this.config.throwFail) {
984                 callback(this, response);
985             } else {
986                 try {
987                     callback(this, response);
988                 } catch (e) {
989                     this.error('use callback error', e, args);
990                 }
991             }
992         }
993     },
995     /**
996     Called from the `use` method queue to ensure that only one set of loading
997     logic is performed at a time.
999     @method _use
1000     @param {String} args* One or more modules to attach.
1001     @param {Function} [callback] Function to call once all required modules have
1002         been attached.
1003     @private
1004     **/
1005     _use: function(args, callback) {
1007         if (!this.Array) {
1008             this._attach(['yui-base']);
1009         }
1011         var len, loader, handleBoot,
1012             Y = this,
1013             G_ENV = YUI.Env,
1014             mods = G_ENV.mods,
1015             Env = Y.Env,
1016             used = Env._used,
1017             aliases = G_ENV.aliases,
1018             queue = G_ENV._loaderQueue,
1019             firstArg = args[0],
1020             YArray = Y.Array,
1021             config = Y.config,
1022             boot = config.bootstrap,
1023             missing = [],
1024             i,
1025             r = [],
1026             ret = true,
1027             fetchCSS = config.fetchCSS,
1028             process = function(names, skip) {
1030                 var i = 0, a = [], name, len, m, req, use;
1032                 if (!names.length) {
1033                     return;
1034                 }
1036                 if (aliases) {
1037                     len = names.length;
1038                     for (i = 0; i < len; i++) {
1039                         if (aliases[names[i]] && !mods[names[i]]) {
1040                             a = [].concat(a, aliases[names[i]]);
1041                         } else {
1042                             a.push(names[i]);
1043                         }
1044                     }
1045                     names = a;
1046                 }
1048                 len = names.length;
1050                 for (i = 0; i < len; i++) {
1051                     name = names[i];
1052                     if (!skip) {
1053                         r.push(name);
1054                     }
1056                     // only attach a module once
1057                     if (used[name]) {
1058                         continue;
1059                     }
1061                     m = mods[name];
1062                     req = null;
1063                     use = null;
1065                     if (m) {
1066                         used[name] = true;
1067                         req = m.details.requires;
1068                         use = m.details.use;
1069                     } else {
1070                         // CSS files don't register themselves, see if it has
1071                         // been loaded
1072                         if (!G_ENV._loaded[VERSION][name]) {
1073                             missing.push(name);
1074                         } else {
1075                             used[name] = true; // probably css
1076                         }
1077                     }
1079                     // make sure requirements are attached
1080                     if (req && req.length) {
1081                         process(req);
1082                     }
1084                     // make sure we grab the submodule dependencies too
1085                     if (use && use.length) {
1086                         process(use, 1);
1087                     }
1088                 }
1090             },
1092             handleLoader = function(fromLoader) {
1093                 var response = fromLoader || {
1094                         success: true,
1095                         msg: 'not dynamic'
1096                     },
1097                     redo, origMissing,
1098                     ret = true,
1099                     data = response.data;
1101                 Y._loading = false;
1103                 if (data) {
1104                     origMissing = missing;
1105                     missing = [];
1106                     r = [];
1107                     process(data);
1108                     redo = missing.length;
1109                     if (redo) {
1110                         if ([].concat(missing).sort().join() ==
1111                                 origMissing.sort().join()) {
1112                             redo = false;
1113                         }
1114                     }
1115                 }
1117                 if (redo && data) {
1118                     Y._loading = true;
1119                     Y._use(missing, function() {
1120                         Y.log('Nested use callback: ' + data, 'info', 'yui');
1121                         if (Y._attach(data)) {
1122                             Y._notify(callback, response, data);
1123                         }
1124                     });
1125                 } else {
1126                     if (data) {
1127                         // Y.log('attaching from loader: ' + data, 'info', 'yui');
1128                         ret = Y._attach(data);
1129                     }
1130                     if (ret) {
1131                         Y._notify(callback, response, args);
1132                     }
1133                 }
1135                 if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
1136                     Y._use.apply(Y, Y._useQueue.next());
1137                 }
1139             };
1141 // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
1143         // YUI().use('*'); // bind everything available
1144         if (firstArg === '*') {
1145             args = [];
1146             for (i in mods) {
1147                 if (mods.hasOwnProperty(i)) {
1148                     args.push(i);
1149                 }
1150             }
1151             ret = Y._attach(args);
1152             if (ret) {
1153                 handleLoader();
1154             }
1155             return Y;
1156         }
1158         if ((mods.loader || mods['loader-base']) && !Y.Loader) {
1159             Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui');
1160             Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
1161         }
1163         // Y.log('before loader requirements: ' + args, 'info', 'yui');
1165         // use loader to expand dependencies and sort the
1166         // requirements if it is available.
1167         if (boot && Y.Loader && args.length) {
1168             Y.log('Using loader to expand dependencies', 'info', 'yui');
1169             loader = getLoader(Y);
1170             loader.require(args);
1171             loader.ignoreRegistered = true;
1172             loader._boot = true;
1173             loader.calculate(null, (fetchCSS) ? null : 'js');
1174             args = loader.sorted;
1175             loader._boot = false;
1176         }
1178         process(args);
1180         len = missing.length;
1183         if (len) {
1184             missing = YArray.dedupe(missing);
1185             len = missing.length;
1186 Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
1187         }
1190         // dynamic load
1191         if (boot && len && Y.Loader) {
1192 // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
1193             Y.log('Using Loader', 'info', 'yui');
1194             Y._loading = true;
1195             loader = getLoader(Y);
1196             loader.onEnd = handleLoader;
1197             loader.context = Y;
1198             loader.data = args;
1199             loader.ignoreRegistered = false;
1200             loader.require(missing);
1201             loader.insert(null, (fetchCSS) ? null : 'js');
1203         } else if (boot && len && Y.Get && !Env.bootstrapped) {
1205             Y._loading = true;
1207             handleBoot = function() {
1208                 Y._loading = false;
1209                 queue.running = false;
1210                 Env.bootstrapped = true;
1211                 G_ENV._bootstrapping = false;
1212                 if (Y._attach(['loader'])) {
1213                     Y._use(args, callback);
1214                 }
1215             };
1217             if (G_ENV._bootstrapping) {
1218 Y.log('Waiting for loader', 'info', 'yui');
1219                 queue.add(handleBoot);
1220             } else {
1221                 G_ENV._bootstrapping = true;
1222 Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
1223                 Y.Get.script(config.base + config.loaderPath, {
1224                     onEnd: handleBoot
1225                 });
1226             }
1228         } else {
1229             Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
1230             ret = Y._attach(args);
1231             if (ret) {
1232                 handleLoader();
1233             }
1234         }
1236         return Y;
1237     },
1240     /**
1241     Utility method for safely creating namespaces if they don't already exist.
1242     May be called statically on the YUI global object or as a method on a YUI
1243     instance.
1245     When called statically, a namespace will be created on the YUI global
1246     object:
1248         // Create `YUI.your.namespace.here` as nested objects, preserving any
1249         // objects that already exist instead of overwriting them.
1250         YUI.namespace('your.namespace.here');
1252     When called as a method on a YUI instance, a namespace will be created on
1253     that instance:
1255         // Creates `Y.property.package`.
1256         Y.namespace('property.package');
1258     Dots in the input string cause `namespace` to create nested objects for each
1259     token. If any part of the requested namespace already exists, the current
1260     object will be left in place and will not be overwritten. This allows
1261     multiple calls to `namespace` to preserve existing namespaced properties.
1263     If the first token in the namespace string is "YAHOO", that token is
1264     discarded. This is legacy behavior for backwards compatibility with YUI 2.
1266     Be careful with namespace tokens. Reserved words may work in some browsers
1267     and not others. For instance, the following will fail in some browsers
1268     because the supported version of JavaScript reserves the word "long":
1270         Y.namespace('really.long.nested.namespace');
1272     Note: If you pass multiple arguments to create multiple namespaces, only the
1273     last one created is returned from this function.
1275     @method namespace
1276     @param {String} namespace* One or more namespaces to create.
1277     @return {Object} Reference to the last namespace object created.
1278     **/
1279     namespace: function() {
1280         var a = arguments, o, i = 0, j, d, arg;
1282         for (; i < a.length; i++) {
1283             o = this; //Reset base object per argument or it will get reused from the last
1284             arg = a[i];
1285             if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
1286                 d = arg.split(PERIOD);
1287                 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1288                     o[d[j]] = o[d[j]] || {};
1289                     o = o[d[j]];
1290                 }
1291             } else {
1292                 o[arg] = o[arg] || {};
1293                 o = o[arg]; //Reset base object to the new object so it's returned
1294             }
1295         }
1296         return o;
1297     },
1299     // this is replaced if the log module is included
1300     log: NOOP,
1301     message: NOOP,
1302     // this is replaced if the dump module is included
1303     dump: function (o) { return ''+o; },
1305     /**
1306     Reports an error.
1308     The reporting mechanism is controlled by the `throwFail` configuration
1309     attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
1310     truthy, a JS exception is thrown.
1312     If an `errorFn` is specified in the config it must return `true` to indicate
1313     that the exception was handled and keep it from being thrown.
1315     @method error
1316     @param {String} msg Error message.
1317     @param {Error|String} [e] JavaScript error object or an error string.
1318     @param {String} [src] Source of the error (such as the name of the module in
1319         which the error occurred).
1320     @chainable
1321     **/
1322     error: function(msg, e, src) {
1323         //TODO Add check for window.onerror here
1325         var Y = this, ret;
1327         if (Y.config.errorFn) {
1328             ret = Y.config.errorFn.apply(Y, arguments);
1329         }
1331         if (!ret) {
1332             throw (e || new Error(msg));
1333         } else {
1334             Y.message(msg, 'error', ''+src); // don't scrub this one
1335         }
1337         return Y;
1338     },
1340     /**
1341     Generates an id string that is unique among all YUI instances in this
1342     execution context.
1344     @method guid
1345     @param {String} [pre] Prefix.
1346     @return {String} Unique id.
1347     **/
1348     guid: function(pre) {
1349         var id = this.Env._guidp + '_' + (++this.Env._uidx);
1350         return (pre) ? (pre + id) : id;
1351     },
1353     /**
1354     Returns a unique id associated with the given object and (if *readOnly* is
1355     falsy) stamps the object with that id so it can be identified in the future.
1357     Stamping an object involves adding a `_yuid` property to it that contains
1358     the object's id. One exception to this is that in Internet Explorer, DOM
1359     nodes have a `uniqueID` property that contains a browser-generated unique
1360     id, which will be used instead of a YUI-generated id when available.
1362     @method stamp
1363     @param {Object} o Object to stamp.
1364     @param {Boolean} readOnly If truthy and the given object has not already
1365         been stamped, the object will not be modified and `null` will be
1366         returned.
1367     @return {String} Object's unique id, or `null` if *readOnly* was truthy and
1368         the given object was not already stamped.
1369     **/
1370     stamp: function(o, readOnly) {
1371         var uid;
1372         if (!o) {
1373             return o;
1374         }
1376         // IE generates its own unique ID for dom nodes
1377         // The uniqueID property of a document node returns a new ID
1378         if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1379             uid = o.uniqueID;
1380         } else {
1381             uid = (typeof o === 'string') ? o : o._yuid;
1382         }
1384         if (!uid) {
1385             uid = this.guid();
1386             if (!readOnly) {
1387                 try {
1388                     o._yuid = uid;
1389                 } catch (e) {
1390                     uid = null;
1391                 }
1392             }
1393         }
1394         return uid;
1395     },
1397     /**
1398     Destroys this YUI instance.
1400     @method destroy
1401     @since 3.3.0
1402     **/
1403     destroy: function() {
1404         var Y = this;
1405         if (Y.Event) {
1406             Y.Event._unload();
1407         }
1408         delete instances[Y.id];
1409         delete Y.Env;
1410         delete Y.config;
1411     }
1413     /**
1414     Safe `instanceof` wrapper that works around a memory leak in IE when the
1415     object being tested is `window` or `document`.
1417     Unless you are testing objects that may be `window` or `document`, you
1418     should use the native `instanceof` operator instead of this method.
1420     @method instanceOf
1421     @param {Object} o Object to check.
1422     @param {Object} type Class to check against.
1423     @since 3.3.0
1424     **/
1427     YUI.prototype = proto;
1429     // inheritance utilities are not available yet
1430     for (prop in proto) {
1431         if (proto.hasOwnProperty(prop)) {
1432             YUI[prop] = proto[prop];
1433         }
1434     }
1436     /**
1437     Applies a configuration to all YUI instances in this execution context.
1439     The main use case for this method is in "mashups" where several third-party
1440     scripts need to write to a global YUI config, but cannot share a single
1441     centrally-managed config object. This way they can all call
1442     `YUI.applyConfig({})` instead of overwriting the single global config.
1444     @example
1446         YUI.applyConfig({
1447             modules: {
1448                 davglass: {
1449                     fullpath: './davglass.js'
1450                 }
1451             }
1452         });
1454         YUI.applyConfig({
1455             modules: {
1456                 foo: {
1457                     fullpath: './foo.js'
1458                 }
1459             }
1460         });
1462         YUI().use('davglass', function (Y) {
1463             // Module davglass will be available here.
1464         });
1466     @method applyConfig
1467     @param {Object} o Configuration object to apply.
1468     @static
1469     @since 3.5.0
1470     **/
1471     YUI.applyConfig = function(o) {
1472         if (!o) {
1473             return;
1474         }
1475         //If there is a GlobalConfig, apply it first to set the defaults
1476         if (YUI.GlobalConfig) {
1477             this.prototype.applyConfig.call(this, YUI.GlobalConfig);
1478         }
1479         //Apply this config to it
1480         this.prototype.applyConfig.call(this, o);
1481         //Reset GlobalConfig to the combined config
1482         YUI.GlobalConfig = this.config;
1483     };
1485     // set up the environment
1486     YUI._init();
1488     if (hasWin) {
1489         // add a window load event at load time so we can capture
1490         // the case where it fires before dynamic loading is
1491         // complete.
1492         add(window, 'load', handleLoad);
1493     } else {
1494         handleLoad();
1495     }
1497     YUI.Env.add = add;
1498     YUI.Env.remove = remove;
1500     /*global exports*/
1501     // Support the CommonJS method for exporting our single global
1502     if (typeof exports == 'object') {
1503         exports.YUI = YUI;
1504         /**
1505         * Set a method to be called when `Get.script` is called in Node.js
1506         * `Get` will open the file, then pass it's content and it's path
1507         * to this method before attaching it. Commonly used for code coverage
1508         * instrumentation. <strong>Calling this multiple times will only
1509         * attach the last hook method</strong>. This method is only
1510         * available in Node.js.
1511         * @method setLoadHook
1512         * @static
1513         * @param {Function} fn The function to set
1514         * @param {String} fn.data The content of the file
1515         * @param {String} fn.path The file path of the file
1516         */
1517         YUI.setLoadHook = function(fn) {
1518             YUI._getLoadHook = fn;
1519         };
1520         /**
1521         * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
1522         * @method _getLoadHook
1523         * @private
1524         * @param {String} data The content of the file
1525         * @param {String} path The file path of the file
1526         */
1527         YUI._getLoadHook = null;
1528     }
1530     YUI.Env[VERSION] = {};
1531 }());
1535 Config object that contains all of the configuration options for
1536 this `YUI` instance.
1538 This object is supplied by the implementer when instantiating YUI. Some
1539 properties have default values if they are not supplied by the implementer.
1541 This object should not be updated directly because some values are cached. Use
1542 `applyConfig()` to update the config object on a YUI instance that has already
1543 been configured.
1545 @class config
1546 @static
1550 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
1551 if they're needed to load additional dependencies and aren't already available.
1553 Setting this to `false` will prevent YUI from automatically loading the Loader
1554 and module metadata, so you will need to manually ensure that they're available
1555 or handle dependency resolution yourself.
1557 @property {Boolean} bootstrap
1558 @default true
1562 If `true`, `Y.log()` messages will be written to the browser's debug console
1563 when available and when `useBrowserConsole` is also `true`.
1565 @property {Boolean} debug
1566 @default true
1570 Log messages to the browser console if `debug` is `true` and the browser has a
1571 supported console.
1573 @property {Boolean} useBrowserConsole
1574 @default true
1578 A hash of log sources that should be logged. If specified, only messages from
1579 these sources will be logged. Others will be discarded.
1581 @property {Object} logInclude
1582 @type object
1586 A hash of log sources that should be not be logged. If specified, all sources
1587 will be logged *except* those on this list.
1589 @property {Object} logExclude
1593 When the YUI seed file is dynamically loaded after the `window.onload` event has
1594 fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload`
1595 to occur.
1597 This ensures that components that rely on `window.onload` and the `domready`
1598 custom event will work as expected even when YUI is dynamically injected.
1600 @property {Boolean} injected
1601 @default false
1605 If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise,
1606 errors are merely logged silently.
1608 @property {Boolean} throwFail
1609 @default true
1613 Reference to the global object for this execution context.
1615 In a browser, this is the current `window` object. In Node.js, this is the
1616 Node.js `global` object.
1618 @property {Object} global
1622 The browser window or frame that this YUI instance should operate in.
1624 When running in Node.js, this property is `undefined`, since there is no
1625 `window` object. Use `global` to get a reference to the global object that will
1626 work in both browsers and Node.js.
1628 @property {Window} win
1632 The browser `document` object associated with this YUI instance's `win` object.
1634 When running in Node.js, this property is `undefined`, since there is no
1635 `document` object.
1637 @property {Document} doc
1641 A list of modules that defines the YUI core (overrides the default list).
1643 @property {Array} core
1644 @type Array
1645 @default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3']
1649 A list of languages to use in order of preference.
1651 This list is matched against the list of available languages in modules that the
1652 YUI instance uses to determine the best possible localization of language
1653 sensitive modules.
1655 Languages are represented using BCP 47 language tags, such as "en-GB" for
1656 English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as
1657 used in China. The list may be provided as a comma-separated string or as an
1658 array.
1660 @property {String|String[]} lang
1664 Default date format.
1666 @property {String} dateFormat
1667 @deprecated Use configuration in `DataType.Date.format()` instead.
1671 Default locale.
1673 @property {String} locale
1674 @deprecated Use `config.lang` instead.
1678 Default generic polling interval in milliseconds.
1680 @property {Number} pollInterval
1681 @default 20
1685 The number of dynamic `<script>` nodes to insert by default before automatically
1686 removing them when loading scripts.
1688 This applies only to script nodes because removing the node will not make the
1689 evaluated script unavailable. Dynamic CSS nodes are not auto purged, because
1690 removing a linked style sheet will also remove the style definitions.
1692 @property {Number} purgethreshold
1693 @default 20
1697 Delay in milliseconds to wait after a window `resize` event before firing the
1698 event. If another `resize` event occurs before this delay has elapsed, the
1699 delay will start over to ensure that `resize` events are throttled.
1701 @property {Number} windowResizeDelay
1702 @default 40
1706 Base directory for dynamic loading.
1708 @property {String} base
1712 Base URL for a dynamic combo handler. This will be used to make combo-handled
1713 module requests if `combine` is set to `true.
1715 @property {String} comboBase
1716 @default "http://yui.yahooapis.com/combo?"
1720 Root path to prepend to each module path when creating a combo-handled request.
1722 This is updated for each YUI release to point to a specific version of the
1723 library; for example: "3.8.0/build/".
1725 @property {String} root
1729 Filter to apply to module urls. This filter will modify the default path for all
1730 modules.
1732 The default path for the YUI library is the minified version of the files (e.g.,
1733 event-min.js). The filter property can be a predefined filter or a custom
1734 filter. The valid predefined filters are:
1736   - **debug**: Loads debug versions of modules (e.g., event-debug.js).
1737   - **raw**: Loads raw, non-minified versions of modules without debug logging
1738     (e.g., event.js).
1740 You can also define a custom filter, which must be an object literal containing
1741 a search regular expression and a replacement string:
1743     myFilter: {
1744         searchExp : "-min\\.js",
1745         replaceStr: "-debug.js"
1746     }
1748 @property {Object|String} filter
1752 Skin configuration and customizations.
1754 @property {Object} skin
1755 @param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be
1756     applied automatically to skinnable components if not overridden by a
1757     component-specific skin name.
1758 @param {String} [skin.base='assets/skins/'] Default base path for a skin,
1759     relative to Loader's `base` path.
1760 @param {Object} [skin.overrides] Component-specific skin name overrides. Specify
1761     a component name as the key and, as the value, a string or array of strings
1762     for a skin or skins that should be loaded for that component instead of the
1763     `defaultSkin`.
1767 Hash of per-component filter specifications. If specified for a given component,
1768 this overrides the global `filter` config.
1770 @property {Object} filters
1774 If `true`, YUI will use a combo handler to load multiple modules in as few
1775 requests as possible.
1777 The YUI CDN (which YUI uses by default) supports combo handling, but other
1778 servers may not. If the server from which you're loading YUI does not support
1779 combo handling, set this to `false`.
1781 Providing a value for the `base` config property will cause `combine` to default
1782 to `false` instead of `true`.
1784 @property {Boolean} combine
1785 @default true
1789 Array of module names that should never be dynamically loaded.
1791 @property {String[]} ignore
1795 Array of module names that should always be loaded when required, even if
1796 already present on the page.
1798 @property {String[]} force
1802 DOM element or id that should be used as the insertion point for dynamically
1803 added `<script>` and `<link>` nodes.
1805 @property {HTMLElement|String} insertBefore
1809 Object hash containing attributes to add to dynamically added `<script>` nodes.
1811 @property {Object} jsAttributes
1815 Object hash containing attributes to add to dynamically added `<link>` nodes.
1817 @property {Object} cssAttributes
1821 Timeout in milliseconds before a dynamic JS or CSS request will be considered a
1822 failure. If not set, no timeout will be enforced.
1824 @property {Number} timeout
1828 Callback for the 'CSSComplete' event. When dynamically loading YUI components
1829 with CSS, this property fires when the CSS is finished loading.
1831 This provides an opportunity to enhance the presentation of a loading page a
1832 little bit before the entire loading process is done.
1834 @property {Function} onCSS
1838 A hash of module definitions to add to the list of available YUI modules. These
1839 modules can then be dynamically loaded via the `use()` method.
1841 This is a hash in which keys are module names and values are objects containing
1842 module metadata.
1844 See `Loader.addModule()` for the supported module metadata fields. Also see
1845 `groups`, which provides a way to configure the base and combo spec for a set of
1846 modules.
1848 @example
1850     modules: {
1851         mymod1: {
1852             requires: ['node'],
1853             fullpath: '/mymod1/mymod1.js'
1854         },
1856         mymod2: {
1857             requires: ['mymod1'],
1858             fullpath: '/mymod2/mymod2.js'
1859         },
1861         mymod3: '/js/mymod3.js',
1862         mycssmod: '/css/mycssmod.css'
1863     }
1865 @property {Object} modules
1869 Aliases are dynamic groups of modules that can be used as shortcuts.
1871 @example
1873     YUI({
1874         aliases: {
1875             davglass: [ 'node', 'yql', 'dd' ],
1876             mine: [ 'davglass', 'autocomplete']
1877         }
1878     }).use('mine', function (Y) {
1879         // Node, YQL, DD & AutoComplete available here.
1880     });
1882 @property {Object} aliases
1886 A hash of module group definitions.
1888 For each group you can specify a list of modules and the base path and
1889 combo spec to use when dynamically loading the modules.
1891 @example
1893     groups: {
1894         yui2: {
1895             // specify whether or not this group has a combo service
1896             combine: true,
1898             // The comboSeperator to use with this group's combo handler
1899             comboSep: ';',
1901             // The maxURLLength for this server
1902             maxURLLength: 500,
1904             // the base path for non-combo paths
1905             base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1907             // the path to the combo service
1908             comboBase: 'http://yui.yahooapis.com/combo?',
1910             // a fragment to prepend to the path attribute when
1911             // when building combo urls
1912             root: '2.8.0r4/build/',
1914             // the module definitions
1915             modules:  {
1916                 yui2_yde: {
1917                     path: "yahoo-dom-event/yahoo-dom-event.js"
1918                 },
1919                 yui2_anim: {
1920                     path: "animation/animation.js",
1921                     requires: ['yui2_yde']
1922                 }
1923             }
1924         }
1925     }
1927 @property {Object} groups
1931 Path to the Loader JS file, relative to the `base` path.
1933 This is used to dynamically bootstrap the Loader when it's needed and isn't yet
1934 available.
1936 @property {String} loaderPath
1937 @default "loader/loader-min.js"
1941 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
1942 `false` to prevent YUI from loading any CSS, or set it to the string `"force"`
1943 to force CSS dependencies to be loaded even if their associated JS modules are
1944 already loaded.
1946 @property {Boolean|String} fetchCSS
1947 @default true
1951 Default gallery version used to build gallery module urls.
1953 @property {String} gallery
1954 @since 3.1.0
1958 Default YUI 2 version used to build YUI 2 module urls.
1960 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
1961 `2in3` config for pulling different revisions of the wrapped YUI 2 modules.
1963 @property {String} yui2
1964 @default "2.9.0"
1965 @since 3.1.0
1969 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
1971 @property {String} 2in3
1972 @default "4"
1973 @since 3.1.0
1977 Alternate console log function that should be used in environments without a
1978 supported native console. This function is executed with the YUI instance as its
1979 `this` object.
1981 @property {Function} logFn
1982 @since 3.1.0
1986 The minimum log level to log messages for. Log levels are defined
1987 incrementally. Messages greater than or equal to the level specified will
1988 be shown. All others will be discarded. The order of log levels in
1989 increasing priority is:
1991     debug
1992     info
1993     warn
1994     error
1996 @property {String} logLevel
1997 @default 'debug'
1998 @since 3.10.0
2002 Callback to execute when `Y.error()` is called. It receives the error message
2003 and a JavaScript error object if one was provided.
2005 This function is executed with the YUI instance as its `this` object.
2007 Returning `true` from this function will prevent an exception from being thrown.
2009 @property {Function} errorFn
2010 @param {String} errorFn.msg Error message
2011 @param {Object} [errorFn.err] Error object (if one was provided).
2012 @since 3.2.0
2016 A callback to execute when Loader fails to load one or more resources.
2018 This could be because of a script load failure. It could also be because a
2019 module fails to register itself when the `requireRegistration` config is `true`.
2021 If this function is defined, the `use()` callback will only be called when the
2022 loader succeeds. Otherwise, `use()` will always executes unless there was a
2023 JavaScript error when attaching a module.
2025 @property {Function} loadErrorFn
2026 @since 3.3.0
2030 If `true`, Loader will expect all loaded scripts to be first-class YUI modules
2031 that register themselves with the YUI global, and will trigger a failure if a
2032 loaded script does not register a YUI module.
2034 @property {Boolean} requireRegistration
2035 @default false
2036 @since 3.3.0
2040 Cache serviced use() requests.
2042 @property {Boolean} cacheUse
2043 @default true
2044 @since 3.3.0
2045 @deprecated No longer used.
2049 Whether or not YUI should use native ES5 functionality when available for
2050 features like `Y.Array.each()`, `Y.Object()`, etc.
2052 When `false`, YUI will always use its own fallback implementations instead of
2053 relying on ES5 functionality, even when ES5 functionality is available.
2055 @property {Boolean} useNativeES5
2056 @default true
2057 @since 3.5.0
2061  * Leverage native JSON stringify if the browser has a native
2062  * implementation.  In general, this is a good idea.  See the Known Issues
2063  * section in the JSON user guide for caveats.  The default value is true
2064  * for browsers with native JSON support.
2066  * @property useNativeJSONStringify
2067  * @type Boolean
2068  * @default true
2069  * @since 3.8.0
2070  */
2072  /**
2073  * Leverage native JSON parse if the browser has a native implementation.
2074  * In general, this is a good idea.  See the Known Issues section in the
2075  * JSON user guide for caveats.  The default value is true for browsers with
2076  * native JSON support.
2078  * @property useNativeJSONParse
2079  * @type Boolean
2080  * @default true
2081  * @since 3.8.0
2082  */
2085 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
2087 @property {Object|String} delayUntil
2088 @since 3.6.0
2089 @example
2091 You can use `load` or `domready` strings by default:
2093     YUI({
2094         delayUntil: 'domready'
2095     }, function (Y) {
2096         // This will not execute until 'domeready' occurs.
2097     });
2099 Or you can delay until a node is available (with `available` or `contentready`):
2101     YUI({
2102         delayUntil: {
2103             event: 'available',
2104             args : '#foo'
2105         }
2106     }, function (Y) {
2107         // This will not execute until a node matching the selector "#foo" is
2108         // available in the DOM.
2109     });
2112 YUI.add('yui-base', function (Y, NAME) {
2115  * YUI stub
2116  * @module yui
2117  * @submodule yui-base
2118  */
2120  * The YUI module contains the components required for building the YUI
2121  * seed file.  This includes the script loading mechanism, a simple queue,
2122  * and the core utilities for the library.
2123  * @module yui
2124  * @submodule yui-base
2125  */
2128  * Provides core language utilites and extensions used throughout YUI.
2130  * @class Lang
2131  * @static
2132  */
2134 var L = Y.Lang || (Y.Lang = {}),
2136 STRING_PROTO = String.prototype,
2137 TOSTRING     = Object.prototype.toString,
2139 TYPES = {
2140     'undefined'        : 'undefined',
2141     'number'           : 'number',
2142     'boolean'          : 'boolean',
2143     'string'           : 'string',
2144     '[object Function]': 'function',
2145     '[object RegExp]'  : 'regexp',
2146     '[object Array]'   : 'array',
2147     '[object Date]'    : 'date',
2148     '[object Error]'   : 'error'
2151 SUBREGEX         = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
2153 WHITESPACE       = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF",
2154 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
2155 TRIM_LEFT_REGEX  = new RegExp("^" + WHITESPACE_CLASS),
2156 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
2157 TRIMREGEX        = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
2159 NATIVE_FN_REGEX  = /\{\s*\[(?:native code|function)\]\s*\}/i;
2161 // -- Protected Methods --------------------------------------------------------
2164 Returns `true` if the given function appears to be implemented in native code,
2165 `false` otherwise. Will always return `false` -- even in ES5-capable browsers --
2166 if the `useNativeES5` YUI config option is set to `false`.
2168 This isn't guaranteed to be 100% accurate and won't work for anything other than
2169 functions, but it can be useful for determining whether a function like
2170 `Array.prototype.forEach` is native or a JS shim provided by another library.
2172 There's a great article by @kangax discussing certain flaws with this technique:
2173 <http://perfectionkills.com/detecting-built-in-host-methods/>
2175 While his points are valid, it's still possible to benefit from this function
2176 as long as it's used carefully and sparingly, and in such a way that false
2177 negatives have minimal consequences. It's used internally to avoid using
2178 potentially broken non-native ES5 shims that have been added to the page by
2179 other libraries.
2181 @method _isNative
2182 @param {Function} fn Function to test.
2183 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
2184 @static
2185 @protected
2186 @since 3.5.0
2188 L._isNative = function (fn) {
2189     return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
2192 // -- Public Methods -----------------------------------------------------------
2195  * Determines whether or not the provided item is an array.
2197  * Returns `false` for array-like collections such as the function `arguments`
2198  * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
2199  * test for an array-like collection.
2201  * @method isArray
2202  * @param o The object to test.
2203  * @return {boolean} true if o is an array.
2204  * @static
2205  */
2206 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
2207     return L.type(o) === 'array';
2211  * Determines whether or not the provided item is a boolean.
2212  * @method isBoolean
2213  * @static
2214  * @param o The object to test.
2215  * @return {boolean} true if o is a boolean.
2216  */
2217 L.isBoolean = function(o) {
2218     return typeof o === 'boolean';
2222  * Determines whether or not the supplied item is a date instance.
2223  * @method isDate
2224  * @static
2225  * @param o The object to test.
2226  * @return {boolean} true if o is a date.
2227  */
2228 L.isDate = function(o) {
2229     return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
2233  * <p>
2234  * Determines whether or not the provided item is a function.
2235  * Note: Internet Explorer thinks certain functions are objects:
2236  * </p>
2238  * <pre>
2239  * var obj = document.createElement("object");
2240  * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
2241  * &nbsp;
2242  * var input = document.createElement("input"); // append to body
2243  * Y.Lang.isFunction(input.focus) // reports false in IE
2244  * </pre>
2246  * <p>
2247  * You will have to implement additional tests if these functions
2248  * matter to you.
2249  * </p>
2251  * @method isFunction
2252  * @static
2253  * @param o The object to test.
2254  * @return {boolean} true if o is a function.
2255  */
2256 L.isFunction = function(o) {
2257     return L.type(o) === 'function';
2261  * Determines whether or not the provided item is null.
2262  * @method isNull
2263  * @static
2264  * @param o The object to test.
2265  * @return {boolean} true if o is null.
2266  */
2267 L.isNull = function(o) {
2268     return o === null;
2272  * Determines whether or not the provided item is a legal number.
2273  * @method isNumber
2274  * @static
2275  * @param o The object to test.
2276  * @return {boolean} true if o is a number.
2277  */
2278 L.isNumber = function(o) {
2279     return typeof o === 'number' && isFinite(o);
2283  * Determines whether or not the provided item is of type object
2284  * or function. Note that arrays are also objects, so
2285  * <code>Y.Lang.isObject([]) === true</code>.
2286  * @method isObject
2287  * @static
2288  * @param o The object to test.
2289  * @param failfn {boolean} fail if the input is a function.
2290  * @return {boolean} true if o is an object.
2291  * @see isPlainObject
2292  */
2293 L.isObject = function(o, failfn) {
2294     var t = typeof o;
2295     return (o && (t === 'object' ||
2296         (!failfn && (t === 'function' || L.isFunction(o))))) || false;
2300  * Determines whether or not the provided value is a regexp.
2301  * @method isRegExp
2302  * @static
2303  * @param value The value or object to test.
2304  * @return {boolean} true if value is a regexp.
2305  */
2306 L.isRegExp = function(value) {
2307     return L.type(value) === 'regexp';
2311  * Determines whether or not the provided item is a string.
2312  * @method isString
2313  * @static
2314  * @param o The object to test.
2315  * @return {boolean} true if o is a string.
2316  */
2317 L.isString = function(o) {
2318     return typeof o === 'string';
2322  * Determines whether or not the provided item is undefined.
2323  * @method isUndefined
2324  * @static
2325  * @param o The object to test.
2326  * @return {boolean} true if o is undefined.
2327  */
2328 L.isUndefined = function(o) {
2329     return typeof o === 'undefined';
2333  * A convenience method for detecting a legitimate non-null value.
2334  * Returns false for null/undefined/NaN, true for other values,
2335  * including 0/false/''
2336  * @method isValue
2337  * @static
2338  * @param o The item to test.
2339  * @return {boolean} true if it is not null/undefined/NaN || false.
2340  */
2341 L.isValue = function(o) {
2342     var t = L.type(o);
2344     switch (t) {
2345         case 'number':
2346             return isFinite(o);
2348         case 'null': // fallthru
2349         case 'undefined':
2350             return false;
2352         default:
2353             return !!t;
2354     }
2358  * Returns the current time in milliseconds.
2360  * @method now
2361  * @return {Number} Current time in milliseconds.
2362  * @static
2363  * @since 3.3.0
2364  */
2365 L.now = Date.now || function () {
2366     return new Date().getTime();
2370  * Lightweight version of <code>Y.substitute</code>. Uses the same template
2371  * structure as <code>Y.substitute</code>, but doesn't support recursion,
2372  * auto-object coersion, or formats.
2373  * @method sub
2374  * @param {string} s String to be modified.
2375  * @param {object} o Object containing replacement values.
2376  * @return {string} the substitute result.
2377  * @static
2378  * @since 3.2.0
2379  */
2380 L.sub = function(s, o) {
2381     return s.replace ? s.replace(SUBREGEX, function (match, key) {
2382         return L.isUndefined(o[key]) ? match : o[key];
2383     }) : s;
2387  * Returns a string without any leading or trailing whitespace.  If
2388  * the input is not a string, the input will be returned untouched.
2389  * @method trim
2390  * @static
2391  * @param s {string} the string to trim.
2392  * @return {string} the trimmed string.
2393  */
2394 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
2395     return s && s.trim ? s.trim() : s;
2396 } : function (s) {
2397     try {
2398         return s.replace(TRIMREGEX, '');
2399     } catch (e) {
2400         return s;
2401     }
2405  * Returns a string without any leading whitespace.
2406  * @method trimLeft
2407  * @static
2408  * @param s {string} the string to trim.
2409  * @return {string} the trimmed string.
2410  */
2411 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
2412     return s.trimLeft();
2413 } : function (s) {
2414     return s.replace(TRIM_LEFT_REGEX, '');
2418  * Returns a string without any trailing whitespace.
2419  * @method trimRight
2420  * @static
2421  * @param s {string} the string to trim.
2422  * @return {string} the trimmed string.
2423  */
2424 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
2425     return s.trimRight();
2426 } : function (s) {
2427     return s.replace(TRIM_RIGHT_REGEX, '');
2431 Returns one of the following strings, representing the type of the item passed
2434  * "array"
2435  * "boolean"
2436  * "date"
2437  * "error"
2438  * "function"
2439  * "null"
2440  * "number"
2441  * "object"
2442  * "regexp"
2443  * "string"
2444  * "undefined"
2446 Known issues:
2448  * `typeof HTMLElementCollection` returns function in Safari, but
2449     `Y.Lang.type()` reports "object", which could be a good thing --
2450     but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
2452 @method type
2453 @param o the item to test.
2454 @return {string} the detected type.
2455 @static
2457 L.type = function(o) {
2458     return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
2461 @module yui
2462 @submodule yui-base
2465 var Lang   = Y.Lang,
2466     Native = Array.prototype,
2468     hasOwn = Object.prototype.hasOwnProperty;
2471 Provides utility methods for working with arrays. Additional array helpers can
2472 be found in the `collection` and `array-extras` modules.
2474 `Y.Array(thing)` returns a native array created from _thing_. Depending on
2475 _thing_'s type, one of the following will happen:
2477   * Arrays are returned unmodified unless a non-zero _startIndex_ is
2478     specified.
2479   * Array-like collections (see `Array.test()`) are converted to arrays.
2480   * For everything else, a new array is created with _thing_ as the sole
2481     item.
2483 Note: elements that are also collections, such as `<form>` and `<select>`
2484 elements, are not automatically converted to arrays. To force a conversion,
2485 pass `true` as the value of the _force_ parameter.
2487 @class Array
2488 @constructor
2489 @param {Any} thing The thing to arrayify.
2490 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2491   collection, a subset of items starting at the specified index will be
2492   returned.
2493 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2494   array-like collection no matter what.
2495 @return {Array} A native array created from _thing_, according to the rules
2496   described above.
2498 function YArray(thing, startIndex, force) {
2499     var len, result;
2501     /*jshint expr: true*/
2502     startIndex || (startIndex = 0);
2504     if (force || YArray.test(thing)) {
2505         // IE throws when trying to slice HTMLElement collections.
2506         try {
2507             return Native.slice.call(thing, startIndex);
2508         } catch (ex) {
2509             result = [];
2511             for (len = thing.length; startIndex < len; ++startIndex) {
2512                 result.push(thing[startIndex]);
2513             }
2515             return result;
2516         }
2517     }
2519     return [thing];
2522 Y.Array = YArray;
2525 Dedupes an array of strings, returning an array that's guaranteed to contain
2526 only one copy of a given string.
2528 This method differs from `Array.unique()` in that it's optimized for use only
2529 with arrays consisting entirely of strings or entirely of numbers, whereas
2530 `unique` may be used with other value types (but is slower).
2532 Using `dedupe()` with values other than strings or numbers, or with arrays
2533 containing a mix of strings and numbers, may result in unexpected behavior.
2535 @method dedupe
2536 @param {String[]|Number[]} array Array of strings or numbers to dedupe.
2537 @return {Array} Copy of _array_ containing no duplicate values.
2538 @static
2539 @since 3.4.0
2541 YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
2542     var hash    = Object.create(null),
2543         results = [],
2544         i, item, len;
2546     for (i = 0, len = array.length; i < len; ++i) {
2547         item = array[i];
2549         if (!hash[item]) {
2550             hash[item] = 1;
2551             results.push(item);
2552         }
2553     }
2555     return results;
2556 } : function (array) {
2557     var hash    = {},
2558         results = [],
2559         i, item, len;
2561     for (i = 0, len = array.length; i < len; ++i) {
2562         item = array[i];
2564         if (!hasOwn.call(hash, item)) {
2565             hash[item] = 1;
2566             results.push(item);
2567         }
2568     }
2570     return results;
2574 Executes the supplied function on each item in the array. This method wraps
2575 the native ES5 `Array.forEach()` method if available.
2577 @method each
2578 @param {Array} array Array to iterate.
2579 @param {Function} fn Function to execute on each item in the array. The function
2580   will receive the following arguments:
2581     @param {Any} fn.item Current array item.
2582     @param {Number} fn.index Current array index.
2583     @param {Array} fn.array Array being iterated.
2584 @param {Object} [thisObj] `this` object to use when calling _fn_.
2585 @return {YUI} The YUI instance.
2586 @static
2588 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
2589     Native.forEach.call(array || [], fn, thisObj || Y);
2590     return Y;
2591 } : function (array, fn, thisObj) {
2592     for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2593         if (i in array) {
2594             fn.call(thisObj || Y, array[i], i, array);
2595         }
2596     }
2598     return Y;
2602 Alias for `each()`.
2604 @method forEach
2605 @static
2609 Returns an object using the first array as keys and the second as values. If
2610 the second array is not provided, or if it doesn't contain the same number of
2611 values as the first array, then `true` will be used in place of the missing
2612 values.
2614 @example
2616     Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2617     // => {a: 'foo', b: 'bar', c: true}
2619 @method hash
2620 @param {String[]} keys Array of strings to use as keys.
2621 @param {Array} [values] Array to use as values.
2622 @return {Object} Hash using the first array as keys and the second as values.
2623 @static
2625 YArray.hash = function (keys, values) {
2626     var hash = {},
2627         vlen = (values && values.length) || 0,
2628         i, len;
2630     for (i = 0, len = keys.length; i < len; ++i) {
2631         if (i in keys) {
2632             hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2633         }
2634     }
2636     return hash;
2640 Returns the index of the first item in the array that's equal (using a strict
2641 equality check) to the specified _value_, or `-1` if the value isn't found.
2643 This method wraps the native ES5 `Array.indexOf()` method if available.
2645 @method indexOf
2646 @param {Array} array Array to search.
2647 @param {Any} value Value to search for.
2648 @param {Number} [from=0] The index at which to begin the search.
2649 @return {Number} Index of the item strictly equal to _value_, or `-1` if not
2650     found.
2651 @static
2653 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
2654     return Native.indexOf.call(array, value, from);
2655 } : function (array, value, from) {
2656     // http://es5.github.com/#x15.4.4.14
2657     var len = array.length;
2659     from = +from || 0;
2660     from = (from > 0 || -1) * Math.floor(Math.abs(from));
2662     if (from < 0) {
2663         from += len;
2665         if (from < 0) {
2666             from = 0;
2667         }
2668     }
2670     for (; from < len; ++from) {
2671         if (from in array && array[from] === value) {
2672             return from;
2673         }
2674     }
2676     return -1;
2680 Numeric sort convenience function.
2682 The native `Array.prototype.sort()` function converts values to strings and
2683 sorts them in lexicographic order, which is unsuitable for sorting numeric
2684 values. Provide `Array.numericSort` as a custom sort function when you want
2685 to sort values in numeric order.
2687 @example
2689     [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2690     // => [4, 8, 15, 16, 23, 42]
2692 @method numericSort
2693 @param {Number} a First value to compare.
2694 @param {Number} b Second value to compare.
2695 @return {Number} Difference between _a_ and _b_.
2696 @static
2698 YArray.numericSort = function (a, b) {
2699     return a - b;
2703 Executes the supplied function on each item in the array. Returning a truthy
2704 value from the function will stop the processing of remaining items.
2706 @method some
2707 @param {Array} array Array to iterate over.
2708 @param {Function} fn Function to execute on each item. The function will receive
2709   the following arguments:
2710     @param {Any} fn.value Current array item.
2711     @param {Number} fn.index Current array index.
2712     @param {Array} fn.array Array being iterated over.
2713 @param {Object} [thisObj] `this` object to use when calling _fn_.
2714 @return {Boolean} `true` if the function returns a truthy value on any of the
2715   items in the array; `false` otherwise.
2716 @static
2718 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
2719     return Native.some.call(array, fn, thisObj);
2720 } : function (array, fn, thisObj) {
2721     for (var i = 0, len = array.length; i < len; ++i) {
2722         if (i in array && fn.call(thisObj, array[i], i, array)) {
2723             return true;
2724         }
2725     }
2727     return false;
2731 Evaluates _obj_ to determine if it's an array, an array-like collection, or
2732 something else. This is useful when working with the function `arguments`
2733 collection and `HTMLElement` collections.
2735 Note: This implementation doesn't consider elements that are also
2736 collections, such as `<form>` and `<select>`, to be array-like.
2738 @method test
2739 @param {Object} obj Object to test.
2740 @return {Number} A number indicating the results of the test:
2742   * 0: Neither an array nor an array-like collection.
2743   * 1: Real array.
2744   * 2: Array-like collection.
2746 @static
2748 YArray.test = function (obj) {
2749     var result = 0;
2751     if (Lang.isArray(obj)) {
2752         result = 1;
2753     } else if (Lang.isObject(obj)) {
2754         try {
2755             // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
2756             // or functions without apply/call (Safari
2757             // HTMLElementCollection bug).
2758             if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
2759                 result = 2;
2760             }
2761         } catch (ex) {}
2762     }
2764     return result;
2767  * The YUI module contains the components required for building the YUI
2768  * seed file.  This includes the script loading mechanism, a simple queue,
2769  * and the core utilities for the library.
2770  * @module yui
2771  * @submodule yui-base
2772  */
2775  * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
2776  * removed using next().
2778  * @class Queue
2779  * @constructor
2780  * @param {MIXED} item* 0..n items to seed the queue.
2781  */
2782 function Queue() {
2783     this._init();
2784     this.add.apply(this, arguments);
2787 Queue.prototype = {
2788     /**
2789      * Initialize the queue
2790      *
2791      * @method _init
2792      * @protected
2793      */
2794     _init: function() {
2795         /**
2796          * The collection of enqueued items
2797          *
2798          * @property _q
2799          * @type Array
2800          * @protected
2801          */
2802         this._q = [];
2803     },
2805     /**
2806      * Get the next item in the queue. FIFO support
2807      *
2808      * @method next
2809      * @return {MIXED} the next item in the queue.
2810      */
2811     next: function() {
2812         return this._q.shift();
2813     },
2815     /**
2816      * Get the last in the queue. LIFO support.
2817      *
2818      * @method last
2819      * @return {MIXED} the last item in the queue.
2820      */
2821     last: function() {
2822         return this._q.pop();
2823     },
2825     /**
2826      * Add 0..n items to the end of the queue.
2827      *
2828      * @method add
2829      * @param {MIXED} item* 0..n items.
2830      * @return {object} this queue.
2831      */
2832     add: function() {
2833         this._q.push.apply(this._q, arguments);
2835         return this;
2836     },
2838     /**
2839      * Returns the current number of queued items.
2840      *
2841      * @method size
2842      * @return {Number} The size.
2843      */
2844     size: function() {
2845         return this._q.length;
2846     }
2849 Y.Queue = Queue;
2851 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2854 The YUI module contains the components required for building the YUI seed file.
2855 This includes the script loading mechanism, a simple queue, and the core
2856 utilities for the library.
2858 @module yui
2859 @submodule yui-base
2862 var CACHED_DELIMITER = '__',
2864     hasOwn   = Object.prototype.hasOwnProperty,
2865     isObject = Y.Lang.isObject;
2868 Returns a wrapper for a function which caches the return value of that function,
2869 keyed off of the combined string representation of the argument values provided
2870 when the wrapper is called.
2872 Calling this function again with the same arguments will return the cached value
2873 rather than executing the wrapped function.
2875 Note that since the cache is keyed off of the string representation of arguments
2876 passed to the wrapper function, arguments that aren't strings and don't provide
2877 a meaningful `toString()` method may result in unexpected caching behavior. For
2878 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2879 string `[object Object]` when used as a cache key.
2881 @method cached
2882 @param {Function} source The function to memoize.
2883 @param {Object} [cache={}] Object in which to store cached values. You may seed
2884   this object with pre-existing cached values if desired.
2885 @param {any} [refetch] If supplied, this value is compared with the cached value
2886   using a `==` comparison. If the values are equal, the wrapped function is
2887   executed again even though a cached value exists.
2888 @return {Function} Wrapped function.
2889 @for YUI
2891 Y.cached = function (source, cache, refetch) {
2892     /*jshint expr: true*/
2893     cache || (cache = {});
2895     return function (arg) {
2896         var key = arguments.length > 1 ?
2897                 Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2898                 String(arg);
2900         /*jshint eqeqeq: false*/
2901         if (!(key in cache) || (refetch && cache[key] == refetch)) {
2902             cache[key] = source.apply(source, arguments);
2903         }
2905         return cache[key];
2906     };
2910 Returns the `location` object from the window/frame in which this YUI instance
2911 operates, or `undefined` when executing in a non-browser environment
2912 (e.g. Node.js).
2914 It is _not_ recommended to hold references to the `window.location` object
2915 outside of the scope of a function in which its properties are being accessed or
2916 its methods are being called. This is because of a nasty bug/issue that exists
2917 in both Safari and MobileSafari browsers:
2918 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
2920 @method getLocation
2921 @return {location} The `location` object from the window/frame in which this YUI
2922     instance operates.
2923 @since 3.5.0
2925 Y.getLocation = function () {
2926     // It is safer to look this up every time because yui-base is attached to a
2927     // YUI instance before a user's config is applied; i.e. `Y.config.win` does
2928     // not point the correct window object when this file is loaded.
2929     var win = Y.config.win;
2931     // It is not safe to hold a reference to the `location` object outside the
2932     // scope in which it is being used. The WebKit engine used in Safari and
2933     // MobileSafari will "disconnect" the `location` object from the `window`
2934     // when a page is restored from back/forward history cache.
2935     return win && win.location;
2939 Returns a new object containing all of the properties of all the supplied
2940 objects. The properties from later objects will overwrite those in earlier
2941 objects.
2943 Passing in a single object will create a shallow copy of it. For a deep copy,
2944 use `clone()`.
2946 @method merge
2947 @param {Object} objects* One or more objects to merge.
2948 @return {Object} A new merged object.
2950 Y.merge = function () {
2951     var i      = 0,
2952         len    = arguments.length,
2953         result = {},
2954         key,
2955         obj;
2957     for (; i < len; ++i) {
2958         obj = arguments[i];
2960         for (key in obj) {
2961             if (hasOwn.call(obj, key)) {
2962                 result[key] = obj[key];
2963             }
2964         }
2965     }
2967     return result;
2971 Mixes _supplier_'s properties into _receiver_.
2973 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
2974 shadowed unless the _overwrite_ parameter is `true`, and will not be merged
2975 unless the _merge_ parameter is `true`.
2977 In the default mode (0), only properties the supplier owns are copied (prototype
2978 properties are not copied). The following copying modes are available:
2980   * `0`: _Default_. Object to object.
2981   * `1`: Prototype to prototype.
2982   * `2`: Prototype to prototype and object to object.
2983   * `3`: Prototype to object.
2984   * `4`: Object to prototype.
2986 @method mix
2987 @param {Function|Object} receiver The object or function to receive the mixed
2988   properties.
2989 @param {Function|Object} supplier The object or function supplying the
2990   properties to be mixed.
2991 @param {Boolean} [overwrite=false] If `true`, properties that already exist
2992   on the receiver will be overwritten with properties from the supplier.
2993 @param {String[]} [whitelist] An array of property names to copy. If
2994   specified, only the whitelisted properties will be copied, and all others
2995   will be ignored.
2996 @param {Number} [mode=0] Mix mode to use. See above for available modes.
2997 @param {Boolean} [merge=false] If `true`, objects and arrays that already
2998   exist on the receiver will have the corresponding object/array from the
2999   supplier merged into them, rather than being skipped or overwritten. When
3000   both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
3001 @return {Function|Object|YUI} The receiver, or the YUI instance if the
3002   specified receiver is falsy.
3004 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
3005     var alwaysOverwrite, exists, from, i, key, len, to;
3007     // If no supplier is given, we return the receiver. If no receiver is given,
3008     // we return Y. Returning Y doesn't make much sense to me, but it's
3009     // grandfathered in for backcompat reasons.
3010     if (!receiver || !supplier) {
3011         return receiver || Y;
3012     }
3014     if (mode) {
3015         // In mode 2 (prototype to prototype and object to object), we recurse
3016         // once to do the proto to proto mix. The object to object mix will be
3017         // handled later on.
3018         if (mode === 2) {
3019             Y.mix(receiver.prototype, supplier.prototype, overwrite,
3020                     whitelist, 0, merge);
3021         }
3023         // Depending on which mode is specified, we may be copying from or to
3024         // the prototypes of the supplier and receiver.
3025         from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
3026         to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
3028         // If either the supplier or receiver doesn't actually have a
3029         // prototype property, then we could end up with an undefined `from`
3030         // or `to`. If that happens, we abort and return the receiver.
3031         if (!from || !to) {
3032             return receiver;
3033         }
3034     } else {
3035         from = supplier;
3036         to   = receiver;
3037     }
3039     // If `overwrite` is truthy and `merge` is falsy, then we can skip a
3040     // property existence check on each iteration and save some time.
3041     alwaysOverwrite = overwrite && !merge;
3043     if (whitelist) {
3044         for (i = 0, len = whitelist.length; i < len; ++i) {
3045             key = whitelist[i];
3047             // We call `Object.prototype.hasOwnProperty` instead of calling
3048             // `hasOwnProperty` on the object itself, since the object's
3049             // `hasOwnProperty` method may have been overridden or removed.
3050             // Also, some native objects don't implement a `hasOwnProperty`
3051             // method.
3052             if (!hasOwn.call(from, key)) {
3053                 continue;
3054             }
3056             // The `key in to` check here is (sadly) intentional for backwards
3057             // compatibility reasons. It prevents undesired shadowing of
3058             // prototype members on `to`.
3059             exists = alwaysOverwrite ? false : key in to;
3061             if (merge && exists && isObject(to[key], true)
3062                     && isObject(from[key], true)) {
3063                 // If we're in merge mode, and the key is present on both
3064                 // objects, and the value on both objects is either an object or
3065                 // an array (but not a function), then we recurse to merge the
3066                 // `from` value into the `to` value instead of overwriting it.
3067                 //
3068                 // Note: It's intentional that the whitelist isn't passed to the
3069                 // recursive call here. This is legacy behavior that lots of
3070                 // code still depends on.
3071                 Y.mix(to[key], from[key], overwrite, null, 0, merge);
3072             } else if (overwrite || !exists) {
3073                 // We're not in merge mode, so we'll only copy the `from` value
3074                 // to the `to` value if we're in overwrite mode or if the
3075                 // current key doesn't exist on the `to` object.
3076                 to[key] = from[key];
3077             }
3078         }
3079     } else {
3080         for (key in from) {
3081             // The code duplication here is for runtime performance reasons.
3082             // Combining whitelist and non-whitelist operations into a single
3083             // loop or breaking the shared logic out into a function both result
3084             // in worse performance, and Y.mix is critical enough that the byte
3085             // tradeoff is worth it.
3086             if (!hasOwn.call(from, key)) {
3087                 continue;
3088             }
3090             // The `key in to` check here is (sadly) intentional for backwards
3091             // compatibility reasons. It prevents undesired shadowing of
3092             // prototype members on `to`.
3093             exists = alwaysOverwrite ? false : key in to;
3095             if (merge && exists && isObject(to[key], true)
3096                     && isObject(from[key], true)) {
3097                 Y.mix(to[key], from[key], overwrite, null, 0, merge);
3098             } else if (overwrite || !exists) {
3099                 to[key] = from[key];
3100             }
3101         }
3103         // If this is an IE browser with the JScript enumeration bug, force
3104         // enumeration of the buggy properties by making a recursive call with
3105         // the buggy properties as the whitelist.
3106         if (Y.Object._hasEnumBug) {
3107             Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
3108         }
3109     }
3111     return receiver;
3114  * The YUI module contains the components required for building the YUI
3115  * seed file.  This includes the script loading mechanism, a simple queue,
3116  * and the core utilities for the library.
3117  * @module yui
3118  * @submodule yui-base
3119  */
3122  * Adds utilities to the YUI instance for working with objects.
3124  * @class Object
3125  */
3127 var Lang   = Y.Lang,
3128     hasOwn = Object.prototype.hasOwnProperty,
3130     UNDEFINED, // <-- Note the comma. We're still declaring vars.
3133  * Returns a new object that uses _obj_ as its prototype. This method wraps the
3134  * native ES5 `Object.create()` method if available, but doesn't currently
3135  * pass through `Object.create()`'s second argument (properties) in order to
3136  * ensure compatibility with older browsers.
3138  * @method ()
3139  * @param {Object} obj Prototype object.
3140  * @return {Object} New object using _obj_ as its prototype.
3141  * @static
3142  */
3143 O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
3144     // We currently wrap the native Object.create instead of simply aliasing it
3145     // to ensure consistency with our fallback shim, which currently doesn't
3146     // support Object.create()'s second argument (properties). Once we have a
3147     // safe fallback for the properties arg, we can stop wrapping
3148     // Object.create().
3149     return Object.create(obj);
3150 } : (function () {
3151     // Reusable constructor function for the Object.create() shim.
3152     function F() {}
3154     // The actual shim.
3155     return function (obj) {
3156         F.prototype = obj;
3157         return new F();
3158     };
3159 }()),
3162  * Property names that IE doesn't enumerate in for..in loops, even when they
3163  * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
3164  * manually enumerate these properties.
3166  * @property _forceEnum
3167  * @type String[]
3168  * @protected
3169  * @static
3170  */
3171 forceEnum = O._forceEnum = [
3172     'hasOwnProperty',
3173     'isPrototypeOf',
3174     'propertyIsEnumerable',
3175     'toString',
3176     'toLocaleString',
3177     'valueOf'
3181  * `true` if this browser has the JScript enumeration bug that prevents
3182  * enumeration of the properties named in the `_forceEnum` array, `false`
3183  * otherwise.
3185  * See:
3186  *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
3187  *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
3189  * @property _hasEnumBug
3190  * @type Boolean
3191  * @protected
3192  * @static
3193  */
3194 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
3197  * `true` if this browser incorrectly considers the `prototype` property of
3198  * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
3200  * @property _hasProtoEnumBug
3201  * @type Boolean
3202  * @protected
3203  * @static
3204  */
3205 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
3208  * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
3209  * exists only on _obj_'s prototype. This is essentially a safer version of
3210  * `obj.hasOwnProperty()`.
3212  * @method owns
3213  * @param {Object} obj Object to test.
3214  * @param {String} key Property name to look for.
3215  * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3216  * @static
3217  */
3218 owns = O.owns = function (obj, key) {
3219     return !!obj && hasOwn.call(obj, key);
3220 }; // <-- End of var declarations.
3223  * Alias for `owns()`.
3225  * @method hasKey
3226  * @param {Object} obj Object to test.
3227  * @param {String} key Property name to look for.
3228  * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
3229  * @static
3230  */
3231 O.hasKey = owns;
3234  * Returns an array containing the object's enumerable keys. Does not include
3235  * prototype keys or non-enumerable keys.
3237  * Note that keys are returned in enumeration order (that is, in the same order
3238  * that they would be enumerated by a `for-in` loop), which may not be the same
3239  * as the order in which they were defined.
3241  * This method is an alias for the native ES5 `Object.keys()` method if
3242  * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of
3243  * `Object.keys()` have an inconsistency as they consider `prototype` to be
3244  * enumerable, so a non-native shim is used to rectify the difference.
3246  * @example
3248  *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
3249  *     // => ['a', 'b', 'c']
3251  * @method keys
3252  * @param {Object} obj An object.
3253  * @return {String[]} Array of keys.
3254  * @static
3255  */
3256 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
3257     if (!Lang.isObject(obj)) {
3258         throw new TypeError('Object.keys called on a non-object');
3259     }
3261     var keys = [],
3262         i, key, len;
3264     if (hasProtoEnumBug && typeof obj === 'function') {
3265         for (key in obj) {
3266             if (owns(obj, key) && key !== 'prototype') {
3267                 keys.push(key);
3268             }
3269         }
3270     } else {
3271         for (key in obj) {
3272             if (owns(obj, key)) {
3273                 keys.push(key);
3274             }
3275         }
3276     }
3278     if (hasEnumBug) {
3279         for (i = 0, len = forceEnum.length; i < len; ++i) {
3280             key = forceEnum[i];
3282             if (owns(obj, key)) {
3283                 keys.push(key);
3284             }
3285         }
3286     }
3288     return keys;
3292  * Returns an array containing the values of the object's enumerable keys.
3294  * Note that values are returned in enumeration order (that is, in the same
3295  * order that they would be enumerated by a `for-in` loop), which may not be the
3296  * same as the order in which they were defined.
3298  * @example
3300  *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
3301  *     // => ['foo', 'bar', 'baz']
3303  * @method values
3304  * @param {Object} obj An object.
3305  * @return {Array} Array of values.
3306  * @static
3307  */
3308 O.values = function (obj) {
3309     var keys   = O.keys(obj),
3310         i      = 0,
3311         len    = keys.length,
3312         values = [];
3314     for (; i < len; ++i) {
3315         values.push(obj[keys[i]]);
3316     }
3318     return values;
3322  * Returns the number of enumerable keys owned by an object.
3324  * @method size
3325  * @param {Object} obj An object.
3326  * @return {Number} The object's size.
3327  * @static
3328  */
3329 O.size = function (obj) {
3330     try {
3331         return O.keys(obj).length;
3332     } catch (ex) {
3333         return 0; // Legacy behavior for non-objects.
3334     }
3338  * Returns `true` if the object owns an enumerable property with the specified
3339  * value.
3341  * @method hasValue
3342  * @param {Object} obj An object.
3343  * @param {any} value The value to search for.
3344  * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
3345  * @static
3346  */
3347 O.hasValue = function (obj, value) {
3348     return Y.Array.indexOf(O.values(obj), value) > -1;
3352  * Executes a function on each enumerable property in _obj_. The function
3353  * receives the value, the key, and the object itself as parameters (in that
3354  * order).
3356  * By default, only properties owned by _obj_ are enumerated. To include
3357  * prototype properties, set the _proto_ parameter to `true`.
3359  * @method each
3360  * @param {Object} obj Object to enumerate.
3361  * @param {Function} fn Function to execute on each enumerable property.
3362  *   @param {mixed} fn.value Value of the current property.
3363  *   @param {String} fn.key Key of the current property.
3364  *   @param {Object} fn.obj Object being enumerated.
3365  * @param {Object} [thisObj] `this` object to use when calling _fn_.
3366  * @param {Boolean} [proto=false] Include prototype properties.
3367  * @return {YUI} the YUI instance.
3368  * @chainable
3369  * @static
3370  */
3371 O.each = function (obj, fn, thisObj, proto) {
3372     var key;
3374     for (key in obj) {
3375         if (proto || owns(obj, key)) {
3376             fn.call(thisObj || Y, obj[key], key, obj);
3377         }
3378     }
3380     return Y;
3384  * Executes a function on each enumerable property in _obj_, but halts if the
3385  * function returns a truthy value. The function receives the value, the key,
3386  * and the object itself as paramters (in that order).
3388  * By default, only properties owned by _obj_ are enumerated. To include
3389  * prototype properties, set the _proto_ parameter to `true`.
3391  * @method some
3392  * @param {Object} obj Object to enumerate.
3393  * @param {Function} fn Function to execute on each enumerable property.
3394  *   @param {mixed} fn.value Value of the current property.
3395  *   @param {String} fn.key Key of the current property.
3396  *   @param {Object} fn.obj Object being enumerated.
3397  * @param {Object} [thisObj] `this` object to use when calling _fn_.
3398  * @param {Boolean} [proto=false] Include prototype properties.
3399  * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
3400  *   `false` otherwise.
3401  * @static
3402  */
3403 O.some = function (obj, fn, thisObj, proto) {
3404     var key;
3406     for (key in obj) {
3407         if (proto || owns(obj, key)) {
3408             if (fn.call(thisObj || Y, obj[key], key, obj)) {
3409                 return true;
3410             }
3411         }
3412     }
3414     return false;
3418  * Retrieves the sub value at the provided path,
3419  * from the value object provided.
3421  * @method getValue
3422  * @static
3423  * @param o The object from which to extract the property value.
3424  * @param path {Array} A path array, specifying the object traversal path
3425  * from which to obtain the sub value.
3426  * @return {Any} The value stored in the path, undefined if not found,
3427  * undefined if the source is not an object.  Returns the source object
3428  * if an empty path is provided.
3429  */
3430 O.getValue = function(o, path) {
3431     if (!Lang.isObject(o)) {
3432         return UNDEFINED;
3433     }
3435     var i,
3436         p = Y.Array(path),
3437         l = p.length;
3439     for (i = 0; o !== UNDEFINED && i < l; i++) {
3440         o = o[p[i]];
3441     }
3443     return o;
3447  * Sets the sub-attribute value at the provided path on the
3448  * value object.  Returns the modified value object, or
3449  * undefined if the path is invalid.
3451  * @method setValue
3452  * @static
3453  * @param o             The object on which to set the sub value.
3454  * @param path {Array}  A path array, specifying the object traversal path
3455  *                      at which to set the sub value.
3456  * @param val {Any}     The new value for the sub-attribute.
3457  * @return {Object}     The modified object, with the new sub value set, or
3458  *                      undefined, if the path was invalid.
3459  */
3460 O.setValue = function(o, path, val) {
3461     var i,
3462         p = Y.Array(path),
3463         leafIdx = p.length - 1,
3464         ref = o;
3466     if (leafIdx >= 0) {
3467         for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
3468             ref = ref[p[i]];
3469         }
3471         if (ref !== UNDEFINED) {
3472             ref[p[i]] = val;
3473         } else {
3474             return UNDEFINED;
3475         }
3476     }
3478     return o;
3482  * Returns `true` if the object has no enumerable properties of its own.
3484  * @method isEmpty
3485  * @param {Object} obj An object.
3486  * @return {Boolean} `true` if the object is empty.
3487  * @static
3488  * @since 3.2.0
3489  */
3490 O.isEmpty = function (obj) {
3491     return !O.keys(Object(obj)).length;
3494  * The YUI module contains the components required for building the YUI seed
3495  * file.  This includes the script loading mechanism, a simple queue, and the
3496  * core utilities for the library.
3497  * @module yui
3498  * @submodule yui-base
3499  */
3502  * YUI user agent detection.
3503  * Do not fork for a browser if it can be avoided.  Use feature detection when
3504  * you can.  Use the user agent as a last resort.  For all fields listed
3505  * as @type float, UA stores a version number for the browser engine,
3506  * 0 otherwise.  This value may or may not map to the version number of
3507  * the browser using the engine.  The value is presented as a float so
3508  * that it can easily be used for boolean evaluation as well as for
3509  * looking for a particular range of versions.  Because of this,
3510  * some of the granularity of the version info may be lost.  The fields that
3511  * are @type string default to null.  The API docs list the values that
3512  * these fields can have.
3513  * @class UA
3514  * @static
3515  */
3518 * Static method on `YUI.Env` for parsing a UA string.  Called at instantiation
3519 * to populate `Y.UA`.
3521 * @static
3522 * @method parseUA
3523 * @param {String} [subUA=navigator.userAgent] UA string to parse
3524 * @return {Object} The Y.UA object
3526 YUI.Env.parseUA = function(subUA) {
3528     var numberify = function(s) {
3529             var c = 0;
3530             return parseFloat(s.replace(/\./g, function() {
3531                 return (c++ === 1) ? '' : '.';
3532             }));
3533         },
3535         win = Y.config.win,
3537         nav = win && win.navigator,
3539         o = {
3541         /**
3542          * Internet Explorer version number or 0.  Example: 6
3543          * @property ie
3544          * @type float
3545          * @static
3546          */
3547         ie: 0,
3549         /**
3550          * Opera version number or 0.  Example: 9.2
3551          * @property opera
3552          * @type float
3553          * @static
3554          */
3555         opera: 0,
3557         /**
3558          * Gecko engine revision number.  Will evaluate to 1 if Gecko
3559          * is detected but the revision could not be found. Other browsers
3560          * will be 0.  Example: 1.8
3561          * <pre>
3562          * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
3563          * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3564          * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3565          * Firefox 3.0   <-- 1.9
3566          * Firefox 3.5   <-- 1.91
3567          * </pre>
3568          * @property gecko
3569          * @type float
3570          * @static
3571          */
3572         gecko: 0,
3574         /**
3575          * AppleWebKit version.  KHTML browsers that are not WebKit browsers
3576          * will evaluate to 1, other browsers 0.  Example: 418.9
3577          * <pre>
3578          * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3579          *                                   latest available for Mac OSX 10.3.
3580          * Safari 2.0.2:         416     <-- hasOwnProperty introduced
3581          * Safari 2.0.4:         418     <-- preventDefault fixed
3582          * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3583          *                                   different versions of webkit
3584          * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
3585          *                                   updated, but not updated
3586          *                                   to the latest patch.
3587          * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
3588          * SVG and many major issues fixed).
3589          * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
3590          * update from 2.x via the 10.4.11 OS patch.
3591          * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
3592          *                                   yahoo.com user agent hack removed.
3593          * </pre>
3594          * http://en.wikipedia.org/wiki/Safari_version_history
3595          * @property webkit
3596          * @type float
3597          * @static
3598          */
3599         webkit: 0,
3601         /**
3602          * Safari will be detected as webkit, but this property will also
3603          * be populated with the Safari version number
3604          * @property safari
3605          * @type float
3606          * @static
3607          */
3608         safari: 0,
3610         /**
3611          * Chrome will be detected as webkit, but this property will also
3612          * be populated with the Chrome version number
3613          * @property chrome
3614          * @type float
3615          * @static
3616          */
3617         chrome: 0,
3619         /**
3620          * The mobile property will be set to a string containing any relevant
3621          * user agent information when a modern mobile browser is detected.
3622          * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3623          * devices with the WebKit-based browser, and Opera Mini.
3624          * @property mobile
3625          * @type string
3626          * @default null
3627          * @static
3628          */
3629         mobile: null,
3631         /**
3632          * Adobe AIR version number or 0.  Only populated if webkit is detected.
3633          * Example: 1.0
3634          * @property air
3635          * @type float
3636          */
3637         air: 0,
3638         /**
3639          * PhantomJS version number or 0.  Only populated if webkit is detected.
3640          * Example: 1.0
3641          * @property phantomjs
3642          * @type float
3643          */
3644         phantomjs: 0,
3645         /**
3646          * Detects Apple iPad's OS version
3647          * @property ipad
3648          * @type float
3649          * @static
3650          */
3651         ipad: 0,
3652         /**
3653          * Detects Apple iPhone's OS version
3654          * @property iphone
3655          * @type float
3656          * @static
3657          */
3658         iphone: 0,
3659         /**
3660          * Detects Apples iPod's OS version
3661          * @property ipod
3662          * @type float
3663          * @static
3664          */
3665         ipod: 0,
3666         /**
3667          * General truthy check for iPad, iPhone or iPod
3668          * @property ios
3669          * @type Boolean
3670          * @default null
3671          * @static
3672          */
3673         ios: null,
3674         /**
3675          * Detects Googles Android OS version
3676          * @property android
3677          * @type float
3678          * @static
3679          */
3680         android: 0,
3681         /**
3682          * Detects Kindle Silk
3683          * @property silk
3684          * @type float
3685          * @static
3686          */
3687         silk: 0,
3688         /**
3689          * Detects Kindle Silk Acceleration
3690          * @property accel
3691          * @type Boolean
3692          * @static
3693          */
3694         accel: false,
3695         /**
3696          * Detects Palms WebOS version
3697          * @property webos
3698          * @type float
3699          * @static
3700          */
3701         webos: 0,
3703         /**
3704          * Google Caja version number or 0.
3705          * @property caja
3706          * @type float
3707          */
3708         caja: nav && nav.cajaVersion,
3710         /**
3711          * Set to true if the page appears to be in SSL
3712          * @property secure
3713          * @type boolean
3714          * @static
3715          */
3716         secure: false,
3718         /**
3719          * The operating system.  Currently only detecting windows or macintosh
3720          * @property os
3721          * @type string
3722          * @default null
3723          * @static
3724          */
3725         os: null,
3727         /**
3728          * The Nodejs Version
3729          * @property nodejs
3730          * @type float
3731          * @default 0
3732          * @static
3733          */
3734         nodejs: 0,
3735         /**
3736         * Window8/IE10 Application host environment
3737         * @property winjs
3738         * @type Boolean
3739         * @static
3740         */
3741         winjs: !!((typeof Windows !== "undefined") && Windows.System),
3742         /**
3743         * Are touch/msPointer events available on this device
3744         * @property touchEnabled
3745         * @type Boolean
3746         * @static
3747         */
3748         touchEnabled: false
3749     },
3751     ua = subUA || nav && nav.userAgent,
3753     loc = win && win.location,
3755     href = loc && loc.href,
3757     m;
3759     /**
3760     * The User Agent string that was parsed
3761     * @property userAgent
3762     * @type String
3763     * @static
3764     */
3765     o.userAgent = ua;
3768     o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3770     if (ua) {
3772         if ((/windows|win32/i).test(ua)) {
3773             o.os = 'windows';
3774         } else if ((/macintosh|mac_powerpc/i).test(ua)) {
3775             o.os = 'macintosh';
3776         } else if ((/android/i).test(ua)) {
3777             o.os = 'android';
3778         } else if ((/symbos/i).test(ua)) {
3779             o.os = 'symbos';
3780         } else if ((/linux/i).test(ua)) {
3781             o.os = 'linux';
3782         } else if ((/rhino/i).test(ua)) {
3783             o.os = 'rhino';
3784         }
3786         // Modern KHTML browsers should qualify as Safari X-Grade
3787         if ((/KHTML/).test(ua)) {
3788             o.webkit = 1;
3789         }
3790         if ((/IEMobile|XBLWP7/).test(ua)) {
3791             o.mobile = 'windows';
3792         }
3793         if ((/Fennec/).test(ua)) {
3794             o.mobile = 'gecko';
3795         }
3796         // Modern WebKit browsers are at least X-Grade
3797         m = ua.match(/AppleWebKit\/([^\s]*)/);
3798         if (m && m[1]) {
3799             o.webkit = numberify(m[1]);
3800             o.safari = o.webkit;
3802             if (/PhantomJS/.test(ua)) {
3803                 m = ua.match(/PhantomJS\/([^\s]*)/);
3804                 if (m && m[1]) {
3805                     o.phantomjs = numberify(m[1]);
3806                 }
3807             }
3809             // Mobile browser check
3810             if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
3811                 o.mobile = 'Apple'; // iPhone or iPod Touch
3813                 m = ua.match(/OS ([^\s]*)/);
3814                 if (m && m[1]) {
3815                     m = numberify(m[1].replace('_', '.'));
3816                 }
3817                 o.ios = m;
3818                 o.os = 'ios';
3819                 o.ipad = o.ipod = o.iphone = 0;
3821                 m = ua.match(/iPad|iPod|iPhone/);
3822                 if (m && m[0]) {
3823                     o[m[0].toLowerCase()] = o.ios;
3824                 }
3825             } else {
3826                 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3827                 if (m) {
3828                     // Nokia N-series, webOS, ex: NokiaN95
3829                     o.mobile = m[0];
3830                 }
3831                 if (/webOS/.test(ua)) {
3832                     o.mobile = 'WebOS';
3833                     m = ua.match(/webOS\/([^\s]*);/);
3834                     if (m && m[1]) {
3835                         o.webos = numberify(m[1]);
3836                     }
3837                 }
3838                 if (/ Android/.test(ua)) {
3839                     if (/Mobile/.test(ua)) {
3840                         o.mobile = 'Android';
3841                     }
3842                     m = ua.match(/Android ([^\s]*);/);
3843                     if (m && m[1]) {
3844                         o.android = numberify(m[1]);
3845                     }
3847                 }
3848                 if (/Silk/.test(ua)) {
3849                     m = ua.match(/Silk\/([^\s]*)\)/);
3850                     if (m && m[1]) {
3851                         o.silk = numberify(m[1]);
3852                     }
3853                     if (!o.android) {
3854                         o.android = 2.34; //Hack for desktop mode in Kindle
3855                         o.os = 'Android';
3856                     }
3857                     if (/Accelerated=true/.test(ua)) {
3858                         o.accel = true;
3859                     }
3860                 }
3861             }
3863             m = ua.match(/OPR\/(\d+\.\d+)/);
3865             if (m && m[1]) {
3866                 // Opera 15+ with Blink (pretends to be both Chrome and Safari)
3867                 o.opera = numberify(m[1]);
3868             } else {
3869                 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
3871                 if (m && m[1] && m[2]) {
3872                     o.chrome = numberify(m[2]); // Chrome
3873                     o.safari = 0; //Reset safari back to 0
3874                     if (m[1] === 'CrMo') {
3875                         o.mobile = 'chrome';
3876                     }
3877                 } else {
3878                     m = ua.match(/AdobeAIR\/([^\s]*)/);
3879                     if (m) {
3880                         o.air = m[0]; // Adobe AIR 1.0 or better
3881                     }
3882                 }
3883             }
3884         }
3886         if (!o.webkit) { // not webkit
3887 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3888             if (/Opera/.test(ua)) {
3889                 m = ua.match(/Opera[\s\/]([^\s]*)/);
3890                 if (m && m[1]) {
3891                     o.opera = numberify(m[1]);
3892                 }
3893                 m = ua.match(/Version\/([^\s]*)/);
3894                 if (m && m[1]) {
3895                     o.opera = numberify(m[1]); // opera 10+
3896                 }
3898                 if (/Opera Mobi/.test(ua)) {
3899                     o.mobile = 'opera';
3900                     m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
3901                     if (m && m[1]) {
3902                         o.opera = numberify(m[1]);
3903                     }
3904                 }
3905                 m = ua.match(/Opera Mini[^;]*/);
3907                 if (m) {
3908                     o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3909                 }
3910             } else { // not opera or webkit
3911                 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
3913                 if (m && (m[1] || m[2])) {
3914                     o.ie = numberify(m[1] || m[2]);
3915                 } else { // not opera, webkit, or ie
3916                     m = ua.match(/Gecko\/([^\s]*)/);
3918                     if (m) {
3919                         o.gecko = 1; // Gecko detected, look for revision
3920                         m = ua.match(/rv:([^\s\)]*)/);
3921                         if (m && m[1]) {
3922                             o.gecko = numberify(m[1]);
3923                             if (/Mobile|Tablet/.test(ua)) {
3924                                 o.mobile = "ffos";
3925                             }
3926                         }
3927                     }
3928                 }
3929             }
3930         }
3931     }
3933     //Check for known properties to tell if touch events are enabled on this device or if
3934     //the number of MSPointer touchpoints on this device is greater than 0.
3935     if (win && nav && !(o.chrome && o.chrome < 6)) {
3936         o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
3937     }
3939     //It was a parsed UA, do not assign the global value.
3940     if (!subUA) {
3942         if (typeof process === 'object') {
3944             if (process.versions && process.versions.node) {
3945                 //NodeJS
3946                 o.os = process.platform;
3947                 o.nodejs = numberify(process.versions.node);
3948             }
3949         }
3951         YUI.Env.UA = o;
3953     }
3955     return o;
3959 Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3962 Performs a simple comparison between two version numbers, accounting for
3963 standard versioning logic such as the fact that "535.8" is a lower version than
3964 "535.24", even though a simple numerical comparison would indicate that it's
3965 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
3966 considered equivalent.
3968 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
3969 1 if _a_ is higher than _b_.
3971 Versions may be numbers or strings containing numbers and dots. For example,
3972 both `535` and `"535.8.10"` are acceptable. A version string containing
3973 non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
3975 @method compareVersions
3976 @param {Number|String} a First version number to compare.
3977 @param {Number|String} b Second version number to compare.
3978 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
3979     higher than _b_.
3981 Y.UA.compareVersions = function (a, b) {
3982     var aPart, aParts, bPart, bParts, i, len;
3984     if (a === b) {
3985         return 0;
3986     }
3988     aParts = (a + '').split('.');
3989     bParts = (b + '').split('.');
3991     for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
3992         aPart = parseInt(aParts[i], 10);
3993         bPart = parseInt(bParts[i], 10);
3995         /*jshint expr: true*/
3996         isNaN(aPart) && (aPart = 0);
3997         isNaN(bPart) && (bPart = 0);
3999         if (aPart < bPart) {
4000             return -1;
4001         }
4003         if (aPart > bPart) {
4004             return 1;
4005         }
4006     }
4008     return 0;
4010 YUI.Env.aliases = {
4011     "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
4012     "anim-shape-transform": ["anim-shape"],
4013     "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"],
4014     "attribute": ["attribute-base","attribute-complex"],
4015     "attribute-events": ["attribute-observable"],
4016     "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
4017     "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
4018     "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
4019     "base": ["base-base","base-pluginhost","base-build"],
4020     "cache": ["cache-base","cache-offline","cache-plugin"],
4021     "charts": ["charts-base"],
4022     "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
4023     "color": ["color-base","color-hsl","color-harmony"],
4024     "controller": ["router"],
4025     "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
4026     "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
4027     "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
4028     "datatype": ["datatype-date","datatype-number","datatype-xml"],
4029     "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
4030     "datatype-number": ["datatype-number-parse","datatype-number-format"],
4031     "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
4032     "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
4033     "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
4034     "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
4035     "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","event-tap"],
4036     "event-custom": ["event-custom-base","event-custom-complex"],
4037     "event-gestures": ["event-flick","event-move"],
4038     "handlebars": ["handlebars-compiler"],
4039     "highlight": ["highlight-base","highlight-accentfold"],
4040     "history": ["history-base","history-hash","history-hash-ie","history-html5"],
4041     "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
4042     "json": ["json-parse","json-stringify"],
4043     "loader": ["loader-base","loader-rollup","loader-yui3"],
4044     "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
4045     "pluginhost": ["pluginhost-base","pluginhost-config"],
4046     "querystring": ["querystring-parse","querystring-stringify"],
4047     "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
4048     "resize": ["resize-base","resize-proxy","resize-constrain"],
4049     "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
4050     "template": ["template-base","template-micro"],
4051     "text": ["text-accentfold","text-wordbreak"],
4052     "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
4056 }, '3.13.0');