src/cm/media/js/lib/yui/yui3-3.15.0/build/yui-base/yui-base.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 /**
       
     2 The YUI module contains the components required for building the YUI seed file.
       
     3 This includes the script loading mechanism, a simple queue, and the core
       
     4 utilities for the library.
       
     5 
       
     6 @module yui
       
     7 @main yui
       
     8 @submodule yui-base
       
     9 **/
       
    10 
       
    11 /*jshint eqeqeq: false*/
       
    12 if (typeof YUI != 'undefined') {
       
    13     YUI._YUI = YUI;
       
    14 }
       
    15 
       
    16 /**
       
    17 The YUI global namespace object. This is the constructor for all YUI instances.
       
    18 
       
    19 This is a self-instantiable factory function, meaning you don't need to precede
       
    20 it with the `new` operator. You can invoke it directly like this:
       
    21 
       
    22     YUI().use('*', function (Y) {
       
    23         // Y is a new YUI instance.
       
    24     });
       
    25 
       
    26 But it also works like this:
       
    27 
       
    28     var Y = YUI();
       
    29 
       
    30 The `YUI` constructor accepts an optional config object, like this:
       
    31 
       
    32     YUI({
       
    33         debug: true,
       
    34         combine: false
       
    35     }).use('node', function (Y) {
       
    36         // Y.Node is ready to use.
       
    37     });
       
    38 
       
    39 See the API docs for the <a href="config.html">Config</a> class for the complete
       
    40 list of supported configuration properties accepted by the YUI constuctor.
       
    41 
       
    42 If a global `YUI` object is already defined, the existing YUI object will not be
       
    43 overwritten, to ensure that defined namespaces are preserved.
       
    44 
       
    45 Each YUI instance has full custom event support, but only if the event system is
       
    46 available.
       
    47 
       
    48 @class YUI
       
    49 @uses EventTarget
       
    50 @constructor
       
    51 @global
       
    52 @param {Object} [config]* Zero or more optional configuration objects. Config
       
    53     values are stored in the `Y.config` property. See the
       
    54     <a href="config.html">Config</a> docs for the list of supported properties.
       
    55 **/
       
    56 
       
    57     /*global YUI*/
       
    58     /*global YUI_config*/
       
    59     var YUI = function() {
       
    60         var i = 0,
       
    61             Y = this,
       
    62             args = arguments,
       
    63             l = args.length,
       
    64             instanceOf = function(o, type) {
       
    65                 return (o && o.hasOwnProperty && (o instanceof type));
       
    66             },
       
    67             gconf = (typeof YUI_config !== 'undefined') && YUI_config;
       
    68 
       
    69         if (!(instanceOf(Y, YUI))) {
       
    70             Y = new YUI();
       
    71         } else {
       
    72             // set up the core environment
       
    73             Y._init();
       
    74 
       
    75             /**
       
    76             Master configuration that might span multiple contexts in a non-
       
    77             browser environment. It is applied first to all instances in all
       
    78             contexts.
       
    79 
       
    80             @example
       
    81 
       
    82                 YUI.GlobalConfig = {
       
    83                     filter: 'debug'
       
    84                 };
       
    85 
       
    86                 YUI().use('node', function (Y) {
       
    87                     // debug files used here
       
    88                 });
       
    89 
       
    90                 YUI({
       
    91                     filter: 'min'
       
    92                 }).use('node', function (Y) {
       
    93                     // min files used here
       
    94                 });
       
    95 
       
    96             @property {Object} GlobalConfig
       
    97             @global
       
    98             @static
       
    99             **/
       
   100             if (YUI.GlobalConfig) {
       
   101                 Y.applyConfig(YUI.GlobalConfig);
       
   102             }
       
   103 
       
   104             /**
       
   105             Page-level config applied to all YUI instances created on the
       
   106             current page. This is applied after `YUI.GlobalConfig` and before
       
   107             any instance-level configuration.
       
   108 
       
   109             @example
       
   110 
       
   111                 // Single global var to include before YUI seed file
       
   112                 YUI_config = {
       
   113                     filter: 'debug'
       
   114                 };
       
   115 
       
   116                 YUI().use('node', function (Y) {
       
   117                     // debug files used here
       
   118                 });
       
   119 
       
   120                 YUI({
       
   121                     filter: 'min'
       
   122                 }).use('node', function (Y) {
       
   123                     // min files used here
       
   124                 });
       
   125 
       
   126             @property {Object} YUI_config
       
   127             @global
       
   128             **/
       
   129             if (gconf) {
       
   130                 Y.applyConfig(gconf);
       
   131             }
       
   132 
       
   133             // bind the specified additional modules for this instance
       
   134             if (!l) {
       
   135                 Y._setup();
       
   136             }
       
   137         }
       
   138 
       
   139         if (l) {
       
   140             // Each instance can accept one or more configuration objects.
       
   141             // These are applied after YUI.GlobalConfig and YUI_Config,
       
   142             // overriding values set in those config files if there is a
       
   143             // matching property.
       
   144             for (; i < l; i++) {
       
   145                 Y.applyConfig(args[i]);
       
   146             }
       
   147 
       
   148             Y._setup();
       
   149         }
       
   150 
       
   151         Y.instanceOf = instanceOf;
       
   152 
       
   153         return Y;
       
   154     };
       
   155 
       
   156 (function() {
       
   157 
       
   158     var proto, prop,
       
   159         VERSION = '@VERSION@',
       
   160         PERIOD = '.',
       
   161         BASE = 'http://yui.yahooapis.com/',
       
   162         /*
       
   163             These CSS class names can't be generated by
       
   164             getClassName since it is not available at the
       
   165             time they are being used.
       
   166         */
       
   167         DOC_LABEL = 'yui3-js-enabled',
       
   168         CSS_STAMP_EL = 'yui3-css-stamp',
       
   169         NOOP = function() {},
       
   170         SLICE = Array.prototype.slice,
       
   171         APPLY_TO_AUTH = { 'io.xdrReady': 1,   // the functions applyTo
       
   172                           'io.xdrResponse': 1,   // can call. this should
       
   173                           'SWF.eventHandler': 1 }, // be done at build time
       
   174         hasWin = (typeof window != 'undefined'),
       
   175         win = (hasWin) ? window : null,
       
   176         doc = (hasWin) ? win.document : null,
       
   177         docEl = doc && doc.documentElement,
       
   178         docClass = docEl && docEl.className,
       
   179         instances = {},
       
   180         time = new Date().getTime(),
       
   181         add = function(el, type, fn, capture) {
       
   182             if (el && el.addEventListener) {
       
   183                 el.addEventListener(type, fn, capture);
       
   184             } else if (el && el.attachEvent) {
       
   185                 el.attachEvent('on' + type, fn);
       
   186             }
       
   187         },
       
   188         remove = function(el, type, fn, capture) {
       
   189             if (el && el.removeEventListener) {
       
   190                 // this can throw an uncaught exception in FF
       
   191                 try {
       
   192                     el.removeEventListener(type, fn, capture);
       
   193                 } catch (ex) {}
       
   194             } else if (el && el.detachEvent) {
       
   195                 el.detachEvent('on' + type, fn);
       
   196             }
       
   197         },
       
   198         handleReady = function() {
       
   199             YUI.Env.DOMReady = true;
       
   200             if (hasWin) {
       
   201                 remove(doc, 'DOMContentLoaded', handleReady);
       
   202             }        
       
   203         },
       
   204         handleLoad = function() {
       
   205             YUI.Env.windowLoaded = true;
       
   206             YUI.Env.DOMReady = true;
       
   207             if (hasWin) {
       
   208                 remove(window, 'load', handleLoad);
       
   209             }
       
   210         },
       
   211         getLoader = function(Y, o) {
       
   212             var loader = Y.Env._loader,
       
   213                 lCore = [ 'loader-base' ],
       
   214                 G_ENV = YUI.Env,
       
   215                 mods = G_ENV.mods;
       
   216 
       
   217             if (loader) {
       
   218                 //loader._config(Y.config);
       
   219                 loader.ignoreRegistered = false;
       
   220                 loader.onEnd = null;
       
   221                 loader.data = null;
       
   222                 loader.required = [];
       
   223                 loader.loadType = null;
       
   224             } else {
       
   225                 loader = new Y.Loader(Y.config);
       
   226                 Y.Env._loader = loader;
       
   227             }
       
   228             if (mods && mods.loader) {
       
   229                 lCore = [].concat(lCore, YUI.Env.loaderExtras);
       
   230             }
       
   231             YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
       
   232 
       
   233             return loader;
       
   234         },
       
   235 
       
   236         clobber = function(r, s) {
       
   237             for (var i in s) {
       
   238                 if (s.hasOwnProperty(i)) {
       
   239                     r[i] = s[i];
       
   240                 }
       
   241             }
       
   242         },
       
   243 
       
   244         ALREADY_DONE = { success: true };
       
   245 
       
   246 //  Stamp the documentElement (HTML) with a class of "yui-loaded" to
       
   247 //  enable styles that need to key off of JS being enabled.
       
   248 if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
       
   249     if (docClass) {
       
   250         docClass += ' ';
       
   251     }
       
   252     docClass += DOC_LABEL;
       
   253     docEl.className = docClass;
       
   254 }
       
   255 
       
   256 if (VERSION.indexOf('@') > -1) {
       
   257     VERSION = '3.5.0'; // dev time hack for cdn test
       
   258 }
       
   259 
       
   260 proto = {
       
   261     /**
       
   262     Applies a new configuration object to the config of this YUI instance. This
       
   263     will merge new group/module definitions, and will also update the loader
       
   264     cache if necessary. Updating `Y.config` directly will not update the cache.
       
   265 
       
   266     @method applyConfig
       
   267     @param {Object} o the configuration object.
       
   268     @since 3.2.0
       
   269     **/
       
   270     applyConfig: function(o) {
       
   271 
       
   272         o = o || NOOP;
       
   273 
       
   274         var attr,
       
   275             name,
       
   276             // detail,
       
   277             config = this.config,
       
   278             mods = config.modules,
       
   279             groups = config.groups,
       
   280             aliases = config.aliases,
       
   281             loader = this.Env._loader;
       
   282 
       
   283         for (name in o) {
       
   284             if (o.hasOwnProperty(name)) {
       
   285                 attr = o[name];
       
   286                 if (mods && name == 'modules') {
       
   287                     clobber(mods, attr);
       
   288                 } else if (aliases && name == 'aliases') {
       
   289                     clobber(aliases, attr);
       
   290                 } else if (groups && name == 'groups') {
       
   291                     clobber(groups, attr);
       
   292                 } else if (name == 'win') {
       
   293                     config[name] = (attr && attr.contentWindow) || attr;
       
   294                     config.doc = config[name] ? config[name].document : null;
       
   295                 } else if (name == '_yuid') {
       
   296                     // preserve the guid
       
   297                 } else {
       
   298                     config[name] = attr;
       
   299                 }
       
   300             }
       
   301         }
       
   302 
       
   303         if (loader) {
       
   304             loader._config(o);
       
   305         }
       
   306 
       
   307     },
       
   308 
       
   309     /**
       
   310     Old way to apply a config to this instance (calls `applyConfig` under the
       
   311     hood).
       
   312 
       
   313     @private
       
   314     @method _config
       
   315     @param {Object} o The config to apply
       
   316     **/
       
   317     _config: function(o) {
       
   318         this.applyConfig(o);
       
   319     },
       
   320 
       
   321     /**
       
   322     Initializes this YUI instance.
       
   323 
       
   324     @private
       
   325     @method _init
       
   326     **/
       
   327     _init: function() {
       
   328         var filter, el,
       
   329             Y = this,
       
   330             G_ENV = YUI.Env,
       
   331             Env = Y.Env,
       
   332             prop;
       
   333 
       
   334         /**
       
   335         The version number of this YUI instance.
       
   336 
       
   337         This value is typically updated by a script when a YUI release is built,
       
   338         so it may not reflect the correct version number when YUI is run from
       
   339         the development source tree.
       
   340 
       
   341         @property {String} version
       
   342         **/
       
   343         Y.version = VERSION;
       
   344 
       
   345         if (!Env) {
       
   346             Y.Env = {
       
   347                 core: ['get', 'features', 'intl-base', 'yui-log', 'yui-later'],
       
   348                 loaderExtras: ['loader-rollup', 'loader-yui3'],
       
   349                 mods: {}, // flat module map
       
   350                 versions: {}, // version module map
       
   351                 base: BASE,
       
   352                 cdn: BASE + VERSION + '/build/',
       
   353                 // bootstrapped: false,
       
   354                 _idx: 0,
       
   355                 _used: {},
       
   356                 _attached: {},
       
   357                 _exported: {},
       
   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;
       
   395 
       
   396                     if (match) {
       
   397                         path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
       
   398 
       
   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];
       
   402 
       
   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;
       
   420 
       
   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                             }
       
   432 
       
   433                             // use CDN default
       
   434                             return path;
       
   435                         }
       
   436 
       
   437             };
       
   438 
       
   439             Env = Y.Env;
       
   440 
       
   441             Env._loaded[VERSION] = {};
       
   442 
       
   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) {
       
   448 
       
   449                 G_ENV = YUI._YUI.Env;
       
   450                 Env._yidx += G_ENV._yidx;
       
   451                 Env._uidx += G_ENV._uidx;
       
   452 
       
   453                 for (prop in G_ENV) {
       
   454                     if (!(prop in Env)) {
       
   455                         Env[prop] = G_ENV[prop];
       
   456                     }
       
   457                 }
       
   458 
       
   459                 delete YUI._YUI;
       
   460             }
       
   461 
       
   462             Y.id = Y.stamp(Y);
       
   463             instances[Y.id] = Y;
       
   464 
       
   465         }
       
   466 
       
   467         Y.constructor = YUI;
       
   468 
       
   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         };
       
   482 
       
   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         }
       
   496 
       
   497         Y.config.lang = Y.config.lang || 'en-US';
       
   498 
       
   499         Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
       
   500 
       
   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';
       
   506 
       
   507     },
       
   508 
       
   509     /**
       
   510     Finishes the instance setup. Attaches whatever YUI modules were defined
       
   511     at the time that this instance was created.
       
   512 
       
   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..
       
   521 
       
   522         for (i = 0; i < extras.length; i++) {
       
   523             if (mods[extras[i]]) {
       
   524                 core.push(extras[i]);
       
   525             }
       
   526         }
       
   527 
       
   528         Y._attach(['yui-base']);
       
   529         Y._attach(core);
       
   530 
       
   531         if (Y.Loader) {
       
   532             getLoader(Y);
       
   533         }
       
   534 
       
   535     },
       
   536 
       
   537     /**
       
   538     Executes the named method on the specified YUI instance if that method is
       
   539     whitelisted.
       
   540 
       
   541     @method applyTo
       
   542     @param {String} id YUI instance id.
       
   543     @param {String} method Name of the method to execute. For example:
       
   544         'Object.keys'.
       
   545     @param {Array} args Arguments to apply to the method.
       
   546     @return {Mixed} Return value from the applied method, or `null` if the
       
   547         specified instance was not found or the method was not whitelisted.
       
   548     **/
       
   549     applyTo: function(id, method, args) {
       
   550         if (!(method in APPLY_TO_AUTH)) {
       
   551             this.log(method + ': applyTo not allowed', 'warn', 'yui');
       
   552             return null;
       
   553         }
       
   554 
       
   555         var instance = instances[id], nest, m, i;
       
   556         if (instance) {
       
   557             nest = method.split('.');
       
   558             m = instance;
       
   559             for (i = 0; i < nest.length; i = i + 1) {
       
   560                 m = m[nest[i]];
       
   561                 if (!m) {
       
   562                     this.log('applyTo not found: ' + method, 'warn', 'yui');
       
   563                 }
       
   564             }
       
   565             return m && m.apply(instance, args);
       
   566         }
       
   567 
       
   568         return null;
       
   569     },
       
   570 
       
   571 /**
       
   572 Registers a YUI module and makes it available for use in a `YUI().use()` call or
       
   573 as a dependency for other modules.
       
   574 
       
   575 The easiest way to create a first-class YUI module is to use
       
   576 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
       
   577 tool.
       
   578 
       
   579 Shifter will automatically wrap your module code in a `YUI.add()` call along
       
   580 with any configuration info required for the module.
       
   581 
       
   582 @example
       
   583 
       
   584     YUI.add('davglass', function (Y) {
       
   585         Y.davglass = function () {
       
   586         };
       
   587     }, '3.4.0', {
       
   588         requires: ['harley-davidson', 'mt-dew']
       
   589     });
       
   590 
       
   591 @method add
       
   592 @param {String} name Module name.
       
   593 @param {Function} fn Function containing module code. This function will be
       
   594     executed whenever the module is attached to a specific YUI instance.
       
   595 
       
   596     @param {YUI} fn.Y The YUI instance to which this module is attached.
       
   597     @param {String} fn.name Name of the module
       
   598 
       
   599 @param {String} version Module version number. This is currently used only for
       
   600     informational purposes, and is not used internally by YUI.
       
   601 
       
   602 @param {Object} [config] Module config.
       
   603     @param {Array} [config.requires] Array of other module names that must be
       
   604         attached before this module can be attached.
       
   605     @param {Array} [config.optional] Array of optional module names that should
       
   606         be attached before this module is attached if they've already been
       
   607         loaded. If the `loadOptional` YUI option is `true`, optional modules
       
   608         that have not yet been loaded will be loaded just as if they were hard
       
   609         requirements.
       
   610     @param {Array} [config.use] Array of module names that are included within
       
   611         or otherwise provided by this module, and which should be attached
       
   612         automatically when this module is attached. This makes it possible to
       
   613         create "virtual rollup" modules that simply attach a collection of other
       
   614         modules or submodules.
       
   615 
       
   616 @return {YUI} This YUI instance.
       
   617 **/
       
   618     add: function(name, fn, version, details) {
       
   619         details = details || {};
       
   620         var env = YUI.Env,
       
   621             mod = {
       
   622                 name: name,
       
   623                 fn: fn,
       
   624                 version: version,
       
   625                 details: details
       
   626             },
       
   627             //Instance hash so we don't apply it to the same instance twice
       
   628             applied = {},
       
   629             loader, inst,
       
   630             i, versions = env.versions;
       
   631 
       
   632         env.mods[name] = mod;
       
   633         versions[version] = versions[version] || {};
       
   634         versions[version][name] = mod;
       
   635 
       
   636         for (i in instances) {
       
   637             if (instances.hasOwnProperty(i)) {
       
   638                 inst = instances[i];
       
   639                 if (!applied[inst.id]) {
       
   640                     applied[inst.id] = true;
       
   641                     loader = inst.Env._loader;
       
   642                     if (loader) {
       
   643                         if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
       
   644                             loader.addModule(details, name);
       
   645                         }
       
   646                     }
       
   647                 }
       
   648             }
       
   649         }
       
   650 
       
   651         return this;
       
   652     },
       
   653 
       
   654     /**
       
   655     Executes the callback function associated with each required module,
       
   656     attaching the module to this YUI instance.
       
   657 
       
   658     @method _attach
       
   659     @param {Array} r The array of modules to attach
       
   660     @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
       
   661         is not attached.
       
   662     @private
       
   663     **/
       
   664     _attach: function(r, moot) {
       
   665         var i, name, mod, details, req, use, after,
       
   666             mods = YUI.Env.mods,
       
   667             aliases = YUI.Env.aliases,
       
   668             Y = this, j,
       
   669             cache = YUI.Env._renderedMods,
       
   670             loader = Y.Env._loader,
       
   671             done = Y.Env._attached,
       
   672             exported = Y.Env._exported,
       
   673             len = r.length, loader, def, go,
       
   674             c = [],
       
   675             modArgs, esCompat, reqlen,
       
   676             condition,
       
   677             __exports__, __imports__;
       
   678 
       
   679         //Check for conditional modules (in a second+ instance) and add their requirements
       
   680         //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
       
   681         for (i = 0; i < len; i++) {
       
   682             name = r[i];
       
   683             mod = mods[name];
       
   684             c.push(name);
       
   685             if (loader && loader.conditions[name]) {
       
   686                 for (j in loader.conditions[name]) {
       
   687                     if (loader.conditions[name].hasOwnProperty(j)) {
       
   688                         def = loader.conditions[name][j];
       
   689                         go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
       
   690                         if (go) {
       
   691                             c.push(def.name);
       
   692                         }
       
   693                     }
       
   694                 }
       
   695             }
       
   696         }
       
   697         r = c;
       
   698         len = r.length;
       
   699 
       
   700         for (i = 0; i < len; i++) {
       
   701             if (!done[r[i]]) {
       
   702                 name = r[i];
       
   703                 mod = mods[name];
       
   704 
       
   705                 if (aliases && aliases[name] && !mod) {
       
   706                     Y._attach(aliases[name]);
       
   707                     continue;
       
   708                 }
       
   709                 if (!mod) {
       
   710                     if (loader && loader.moduleInfo[name]) {
       
   711                         mod = loader.moduleInfo[name];
       
   712                         moot = true;
       
   713                     }
       
   714 
       
   715 
       
   716                     //if (!loader || !loader.moduleInfo[name]) {
       
   717                     //if ((!loader || !loader.moduleInfo[name]) && !moot) {
       
   718                     if (!moot && name) {
       
   719                         if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
       
   720                             Y.Env._missed.push(name);
       
   721                             Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
       
   722                             Y.message('NOT loaded: ' + name, 'warn', 'yui');
       
   723                         }
       
   724                     }
       
   725                 } else {
       
   726                     done[name] = true;
       
   727                     //Don't like this, but in case a mod was asked for once, then we fetch it
       
   728                     //We need to remove it from the missed list ^davglass
       
   729                     for (j = 0; j < Y.Env._missed.length; j++) {
       
   730                         if (Y.Env._missed[j] === name) {
       
   731                             Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
       
   732                             Y.Env._missed.splice(j, 1);
       
   733                         }
       
   734                     }
       
   735                     /*
       
   736                         If it's a temp module, we need to redo it's requirements if it's already loaded
       
   737                         since it may have been loaded by another instance and it's dependencies might
       
   738                         have been redefined inside the fetched file.
       
   739                     */
       
   740                     if (loader && cache && cache[name] && cache[name].temp) {
       
   741                         loader.getRequires(cache[name]);
       
   742                         req = [];
       
   743                         for (j in loader.moduleInfo[name].expanded_map) {
       
   744                             if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
       
   745                                 req.push(j);
       
   746                             }
       
   747                         }
       
   748                         Y._attach(req);
       
   749                     }
       
   750 
       
   751                     details = mod.details;
       
   752                     req = details.requires;
       
   753                     esCompat = details.es;
       
   754                     use = details.use;
       
   755                     after = details.after;
       
   756                     //Force Intl load if there is a language (Loader logic) @todo fix this shit
       
   757                     if (details.lang) {
       
   758                         req = req || [];
       
   759                         req.unshift('intl');
       
   760                     }
       
   761 
       
   762                     if (req) {
       
   763                         reqlen = req.length;
       
   764                         for (j = 0; j < reqlen; j++) {
       
   765                             if (!done[req[j]]) {
       
   766                                 if (!Y._attach(req)) {
       
   767                                     return false;
       
   768                                 }
       
   769                                 break;
       
   770                             }
       
   771                         }
       
   772                     }
       
   773 
       
   774                     if (after) {
       
   775                         for (j = 0; j < after.length; j++) {
       
   776                             if (!done[after[j]]) {
       
   777                                 if (!Y._attach(after, true)) {
       
   778                                     return false;
       
   779                                 }
       
   780                                 break;
       
   781                             }
       
   782                         }
       
   783                     }
       
   784 
       
   785                     if (mod.fn) {
       
   786                         modArgs = [Y, name];
       
   787                         if (esCompat) {
       
   788                             __imports__ = {};
       
   789                             __exports__ = {};
       
   790                             // passing `exports` and `imports` onto the module function
       
   791                             modArgs.push(__imports__, __exports__);
       
   792                             if (req) {
       
   793                                 reqlen = req.length;
       
   794                                 for (j = 0; j < reqlen; j++) {
       
   795                                     __imports__[req[j]] = exported.hasOwnProperty(req[j]) ? exported[req[j]] : Y;
       
   796                                 }
       
   797                             }
       
   798                         }
       
   799                         if (Y.config.throwFail) {
       
   800                             __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs);
       
   801                         } else {
       
   802                             try {
       
   803                                 __exports__ = mod.fn.apply(esCompat ? undefined : mod, modArgs);
       
   804                             } catch (e) {
       
   805                                 Y.error('Attach error: ' + name, e, name);
       
   806                                 return false;
       
   807                             }
       
   808                         }
       
   809                         if (esCompat) {
       
   810                             // store the `exports` in case others `es` modules requires it
       
   811                             exported[name] = __exports__;
       
   812 
       
   813                             // If an ES module is conditionally loaded and set
       
   814                             // to be used "instead" another module, replace the
       
   815                             // trigger module's content with the conditionally
       
   816                             // loaded one so the values returned by require()
       
   817                             // still makes sense
       
   818                             condition = mod.details.condition;
       
   819                             if (condition && condition.when === 'instead') {
       
   820                                 exported[condition.trigger] = __exports__;
       
   821                             }
       
   822                         }
       
   823                     }
       
   824 
       
   825                     if (use) {
       
   826                         for (j = 0; j < use.length; j++) {
       
   827                             if (!done[use[j]]) {
       
   828                                 if (!Y._attach(use)) {
       
   829                                     return false;
       
   830                                 }
       
   831                                 break;
       
   832                             }
       
   833                         }
       
   834                     }
       
   835 
       
   836 
       
   837 
       
   838                 }
       
   839             }
       
   840         }
       
   841 
       
   842         return true;
       
   843     },
       
   844 
       
   845     /**
       
   846     Delays the `use` callback until another event has taken place such as
       
   847     `window.onload`, `domready`, `contentready`, or `available`.
       
   848 
       
   849     @private
       
   850     @method _delayCallback
       
   851     @param {Function} cb The original `use` callback.
       
   852     @param {String|Object} until Either an event name ('load', 'domready', etc.)
       
   853         or an object containing event/args keys for contentready/available.
       
   854     @return {Function}
       
   855     **/
       
   856     _delayCallback: function(cb, until) {
       
   857 
       
   858         var Y = this,
       
   859             mod = ['event-base'];
       
   860 
       
   861         until = (Y.Lang.isObject(until) ? until : { event: until });
       
   862 
       
   863         if (until.event === 'load') {
       
   864             mod.push('event-synthetic');
       
   865         }
       
   866 
       
   867         return function() {
       
   868             var args = arguments;
       
   869             Y._use(mod, function() {
       
   870                 Y.on(until.event, function() {
       
   871                     args[1].delayUntil = until.event;
       
   872                     cb.apply(Y, args);
       
   873                 }, until.args);
       
   874             });
       
   875         };
       
   876     },
       
   877 
       
   878     /**
       
   879     Attaches one or more modules to this YUI instance. When this is executed,
       
   880     the requirements of the desired modules are analyzed, and one of several
       
   881     things can happen:
       
   882 
       
   883 
       
   884       * All required modules have already been loaded, and just need to be
       
   885         attached to this YUI instance. In this case, the `use()` callback will
       
   886         be executed synchronously after the modules are attached.
       
   887 
       
   888       * One or more modules have not yet been loaded, or the Get utility is not
       
   889         available, or the `bootstrap` config option is `false`. In this case,
       
   890         a warning is issued indicating that modules are missing, but all
       
   891         available modules will still be attached and the `use()` callback will
       
   892         be executed synchronously.
       
   893 
       
   894       * One or more modules are missing and the Loader is not available but the
       
   895         Get utility is, and `bootstrap` is not `false`. In this case, the Get
       
   896         utility will be used to load the Loader, and we will then proceed to
       
   897         the following state:
       
   898 
       
   899       * One or more modules are missing and the Loader is available. In this
       
   900         case, the Loader will be used to resolve the dependency tree for the
       
   901         missing modules and load them and their dependencies. When the Loader is
       
   902         finished loading modules, the `use()` callback will be executed
       
   903         asynchronously.
       
   904 
       
   905     @example
       
   906 
       
   907         // Loads and attaches dd and its dependencies.
       
   908         YUI().use('dd', function (Y) {
       
   909             // ...
       
   910         });
       
   911 
       
   912         // Loads and attaches dd and node as well as all of their dependencies.
       
   913         YUI().use(['dd', 'node'], function (Y) {
       
   914             // ...
       
   915         });
       
   916 
       
   917         // Attaches all modules that have already been loaded.
       
   918         YUI().use('*', function (Y) {
       
   919             // ...
       
   920         });
       
   921 
       
   922         // Attaches a gallery module.
       
   923         YUI().use('gallery-yql', function (Y) {
       
   924             // ...
       
   925         });
       
   926 
       
   927         // Attaches a YUI 2in3 module.
       
   928         YUI().use('yui2-datatable', function (Y) {
       
   929             // ...
       
   930         });
       
   931 
       
   932     @method use
       
   933     @param {String|Array} modules* One or more module names to attach.
       
   934     @param {Function} [callback] Callback function to be executed once all
       
   935         specified modules and their dependencies have been attached.
       
   936     @param {YUI} callback.Y The YUI instance created for this sandbox.
       
   937     @param {Object} callback.status Object containing `success`, `msg` and
       
   938         `data` properties.
       
   939     @chainable
       
   940     **/
       
   941     use: function() {
       
   942         var args = SLICE.call(arguments, 0),
       
   943             callback = args[args.length - 1],
       
   944             Y = this,
       
   945             i = 0,
       
   946             name,
       
   947             Env = Y.Env,
       
   948             provisioned = true;
       
   949 
       
   950         // The last argument supplied to use can be a load complete callback
       
   951         if (Y.Lang.isFunction(callback)) {
       
   952             args.pop();
       
   953             if (Y.config.delayUntil) {
       
   954                 callback = Y._delayCallback(callback, Y.config.delayUntil);
       
   955             }
       
   956         } else {
       
   957             callback = null;
       
   958         }
       
   959         if (Y.Lang.isArray(args[0])) {
       
   960             args = args[0];
       
   961         }
       
   962 
       
   963         if (Y.config.cacheUse) {
       
   964             while ((name = args[i++])) {
       
   965                 if (!Env._attached[name]) {
       
   966                     provisioned = false;
       
   967                     break;
       
   968                 }
       
   969             }
       
   970 
       
   971             if (provisioned) {
       
   972                 if (args.length) {
       
   973                 }
       
   974                 Y._notify(callback, ALREADY_DONE, args);
       
   975                 return Y;
       
   976             }
       
   977         }
       
   978 
       
   979         if (Y._loading) {
       
   980             Y._useQueue = Y._useQueue || new Y.Queue();
       
   981             Y._useQueue.add([args, callback]);
       
   982         } else {
       
   983             Y._use(args, function(Y, response) {
       
   984                 Y._notify(callback, response, args);
       
   985             });
       
   986         }
       
   987 
       
   988         return Y;
       
   989     },
       
   990 
       
   991     /**
       
   992     Sugar for loading both legacy and ES6-based YUI modules.
       
   993 
       
   994     @method require
       
   995     @param {String} [modules*] List of module names to import or a single
       
   996         module name.
       
   997     @param {Function} callback Callback that gets called once all the modules
       
   998         were loaded. Each parameter of the callback is the export value of the
       
   999         corresponding module in the list. If the module is a legacy YUI module,
       
  1000         the YUI instance is used instead of the module exports.
       
  1001     @example
       
  1002     ```
       
  1003     YUI().require(['es6-set'], function (Y, imports) {
       
  1004         var Set = imports.Set,
       
  1005             set = new Set();
       
  1006     });
       
  1007     ```
       
  1008     **/
       
  1009     require: function () {
       
  1010         var args = SLICE.call(arguments),
       
  1011             callback;
       
  1012 
       
  1013         if (typeof args[args.length - 1] === 'function') {
       
  1014             callback = args.pop();
       
  1015 
       
  1016             // only add the callback if one was provided
       
  1017             // YUI().require('foo'); is valid
       
  1018             args.push(function (Y) {
       
  1019                 var i, length = args.length,
       
  1020                     exported = Y.Env._exported,
       
  1021                     __imports__ = {};
       
  1022 
       
  1023                 // Get only the imports requested as arguments
       
  1024                 for (i = 0; i < length; i++) {
       
  1025                     if (exported.hasOwnProperty(args[i])) {
       
  1026                         __imports__[args[i]] = exported[args[i]];
       
  1027                     }
       
  1028                 }
       
  1029 
       
  1030                 // Using `undefined` because:
       
  1031                 // - Using `Y.config.global` would force the value of `this` to be
       
  1032                 //   the global object even in strict mode
       
  1033                 // - Using `Y` goes against the goal of moving away from a shared
       
  1034                 //   object and start thinking in terms of imported and exported
       
  1035                 //   objects
       
  1036                 callback.call(undefined, Y, __imports__);
       
  1037             });
       
  1038         }
       
  1039         // Do not return the Y object. This makes it hard to follow this
       
  1040         // traditional pattern:
       
  1041         //   var Y = YUI().use(...);
       
  1042         // This is a good idea in the light of ES6 modules, to avoid working
       
  1043         // in the global scope.
       
  1044         // This also leaves the door open for returning a promise, once the
       
  1045         // YUI loader is based on the ES6 loader which uses
       
  1046         // loader.import(...).then(...)
       
  1047         this.use.apply(this, args);
       
  1048     },
       
  1049 
       
  1050     /**
       
  1051     Handles Loader notifications about attachment/load errors.
       
  1052 
       
  1053     @method _notify
       
  1054     @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
       
  1055     @param {Object} response Response returned from Loader.
       
  1056     @param {Array} args Arguments passed from Loader.
       
  1057     @private
       
  1058     **/
       
  1059     _notify: function(callback, response, args) {
       
  1060         if (!response.success && this.config.loadErrorFn) {
       
  1061             this.config.loadErrorFn.call(this, this, callback, response, args);
       
  1062         } else if (callback) {
       
  1063             if (this.Env._missed && this.Env._missed.length) {
       
  1064                 response.msg = 'Missing modules: ' + this.Env._missed.join();
       
  1065                 response.success = false;
       
  1066             }
       
  1067             if (this.config.throwFail) {
       
  1068                 callback(this, response);
       
  1069             } else {
       
  1070                 try {
       
  1071                     callback(this, response);
       
  1072                 } catch (e) {
       
  1073                     this.error('use callback error', e, args);
       
  1074                 }
       
  1075             }
       
  1076         }
       
  1077     },
       
  1078 
       
  1079     /**
       
  1080     Called from the `use` method queue to ensure that only one set of loading
       
  1081     logic is performed at a time.
       
  1082 
       
  1083     @method _use
       
  1084     @param {String} args* One or more modules to attach.
       
  1085     @param {Function} [callback] Function to call once all required modules have
       
  1086         been attached.
       
  1087     @private
       
  1088     **/
       
  1089     _use: function(args, callback) {
       
  1090 
       
  1091         if (!this.Array) {
       
  1092             this._attach(['yui-base']);
       
  1093         }
       
  1094 
       
  1095         var len, loader, handleBoot,
       
  1096             Y = this,
       
  1097             G_ENV = YUI.Env,
       
  1098             mods = G_ENV.mods,
       
  1099             Env = Y.Env,
       
  1100             used = Env._used,
       
  1101             aliases = G_ENV.aliases,
       
  1102             queue = G_ENV._loaderQueue,
       
  1103             firstArg = args[0],
       
  1104             YArray = Y.Array,
       
  1105             config = Y.config,
       
  1106             boot = config.bootstrap,
       
  1107             missing = [],
       
  1108             i,
       
  1109             r = [],
       
  1110             ret = true,
       
  1111             fetchCSS = config.fetchCSS,
       
  1112             process = function(names, skip) {
       
  1113 
       
  1114                 var i = 0, a = [], name, len, m, req, use;
       
  1115 
       
  1116                 if (!names.length) {
       
  1117                     return;
       
  1118                 }
       
  1119 
       
  1120                 if (aliases) {
       
  1121                     len = names.length;
       
  1122                     for (i = 0; i < len; i++) {
       
  1123                         if (aliases[names[i]] && !mods[names[i]]) {
       
  1124                             a = [].concat(a, aliases[names[i]]);
       
  1125                         } else {
       
  1126                             a.push(names[i]);
       
  1127                         }
       
  1128                     }
       
  1129                     names = a;
       
  1130                 }
       
  1131 
       
  1132                 len = names.length;
       
  1133 
       
  1134                 for (i = 0; i < len; i++) {
       
  1135                     name = names[i];
       
  1136                     if (!skip) {
       
  1137                         r.push(name);
       
  1138                     }
       
  1139 
       
  1140                     // only attach a module once
       
  1141                     if (used[name]) {
       
  1142                         continue;
       
  1143                     }
       
  1144 
       
  1145                     m = mods[name];
       
  1146                     req = null;
       
  1147                     use = null;
       
  1148 
       
  1149                     if (m) {
       
  1150                         used[name] = true;
       
  1151                         req = m.details.requires;
       
  1152                         use = m.details.use;
       
  1153                     } else {
       
  1154                         // CSS files don't register themselves, see if it has
       
  1155                         // been loaded
       
  1156                         if (!G_ENV._loaded[VERSION][name]) {
       
  1157                             missing.push(name);
       
  1158                         } else {
       
  1159                             used[name] = true; // probably css
       
  1160                         }
       
  1161                     }
       
  1162 
       
  1163                     // make sure requirements are attached
       
  1164                     if (req && req.length) {
       
  1165                         process(req);
       
  1166                     }
       
  1167 
       
  1168                     // make sure we grab the submodule dependencies too
       
  1169                     if (use && use.length) {
       
  1170                         process(use, 1);
       
  1171                     }
       
  1172                 }
       
  1173 
       
  1174             },
       
  1175 
       
  1176             handleLoader = function(fromLoader) {
       
  1177                 var response = fromLoader || {
       
  1178                         success: true,
       
  1179                         msg: 'not dynamic'
       
  1180                     },
       
  1181                     redo, origMissing,
       
  1182                     ret = true,
       
  1183                     data = response.data;
       
  1184 
       
  1185                 Y._loading = false;
       
  1186 
       
  1187                 if (data) {
       
  1188                     origMissing = missing;
       
  1189                     missing = [];
       
  1190                     r = [];
       
  1191                     process(data);
       
  1192                     redo = missing.length;
       
  1193                     if (redo) {
       
  1194                         if ([].concat(missing).sort().join() ==
       
  1195                                 origMissing.sort().join()) {
       
  1196                             redo = false;
       
  1197                         }
       
  1198                     }
       
  1199                 }
       
  1200 
       
  1201                 if (redo && data) {
       
  1202                     Y._loading = true;
       
  1203                     Y._use(missing, function() {
       
  1204                         if (Y._attach(data)) {
       
  1205                             Y._notify(callback, response, data);
       
  1206                         }
       
  1207                     });
       
  1208                 } else {
       
  1209                     if (data) {
       
  1210                         ret = Y._attach(data);
       
  1211                     }
       
  1212                     if (ret) {
       
  1213                         Y._notify(callback, response, args);
       
  1214                     }
       
  1215                 }
       
  1216 
       
  1217                 if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
       
  1218                     Y._use.apply(Y, Y._useQueue.next());
       
  1219                 }
       
  1220 
       
  1221             };
       
  1222 
       
  1223 
       
  1224         // YUI().use('*'); // bind everything available
       
  1225         if (firstArg === '*') {
       
  1226             args = [];
       
  1227             for (i in mods) {
       
  1228                 if (mods.hasOwnProperty(i)) {
       
  1229                     args.push(i);
       
  1230                 }
       
  1231             }
       
  1232             ret = Y._attach(args);
       
  1233             if (ret) {
       
  1234                 handleLoader();
       
  1235             }
       
  1236             return Y;
       
  1237         }
       
  1238 
       
  1239         if ((mods.loader || mods['loader-base']) && !Y.Loader) {
       
  1240             Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
       
  1241         }
       
  1242 
       
  1243 
       
  1244         // use loader to expand dependencies and sort the
       
  1245         // requirements if it is available.
       
  1246         if (boot && Y.Loader && args.length) {
       
  1247             loader = getLoader(Y);
       
  1248             loader.require(args);
       
  1249             loader.ignoreRegistered = true;
       
  1250             loader._boot = true;
       
  1251             loader.calculate(null, (fetchCSS) ? null : 'js');
       
  1252             args = loader.sorted;
       
  1253             loader._boot = false;
       
  1254         }
       
  1255 
       
  1256         process(args);
       
  1257 
       
  1258         len = missing.length;
       
  1259 
       
  1260 
       
  1261         if (len) {
       
  1262             missing = YArray.dedupe(missing);
       
  1263             len = missing.length;
       
  1264         }
       
  1265 
       
  1266 
       
  1267         // dynamic load
       
  1268         if (boot && len && Y.Loader) {
       
  1269             Y._loading = true;
       
  1270             loader = getLoader(Y);
       
  1271             loader.onEnd = handleLoader;
       
  1272             loader.context = Y;
       
  1273             loader.data = args;
       
  1274             loader.ignoreRegistered = false;
       
  1275             loader.require(missing);
       
  1276             loader.insert(null, (fetchCSS) ? null : 'js');
       
  1277 
       
  1278         } else if (boot && len && Y.Get && !Env.bootstrapped) {
       
  1279 
       
  1280             Y._loading = true;
       
  1281 
       
  1282             handleBoot = function() {
       
  1283                 Y._loading = false;
       
  1284                 queue.running = false;
       
  1285                 Env.bootstrapped = true;
       
  1286                 G_ENV._bootstrapping = false;
       
  1287                 if (Y._attach(['loader'])) {
       
  1288                     Y._use(args, callback);
       
  1289                 }
       
  1290             };
       
  1291 
       
  1292             if (G_ENV._bootstrapping) {
       
  1293                 queue.add(handleBoot);
       
  1294             } else {
       
  1295                 G_ENV._bootstrapping = true;
       
  1296                 Y.Get.script(config.base + config.loaderPath, {
       
  1297                     onEnd: handleBoot
       
  1298                 });
       
  1299             }
       
  1300 
       
  1301         } else {
       
  1302             ret = Y._attach(args);
       
  1303             if (ret) {
       
  1304                 handleLoader();
       
  1305             }
       
  1306         }
       
  1307 
       
  1308         return Y;
       
  1309     },
       
  1310 
       
  1311 
       
  1312     /**
       
  1313     Utility method for safely creating namespaces if they don't already exist.
       
  1314     May be called statically on the YUI global object or as a method on a YUI
       
  1315     instance.
       
  1316 
       
  1317     When called statically, a namespace will be created on the YUI global
       
  1318     object:
       
  1319 
       
  1320         // Create `YUI.your.namespace.here` as nested objects, preserving any
       
  1321         // objects that already exist instead of overwriting them.
       
  1322         YUI.namespace('your.namespace.here');
       
  1323 
       
  1324     When called as a method on a YUI instance, a namespace will be created on
       
  1325     that instance:
       
  1326 
       
  1327         // Creates `Y.property.package`.
       
  1328         Y.namespace('property.package');
       
  1329 
       
  1330     Dots in the input string cause `namespace` to create nested objects for each
       
  1331     token. If any part of the requested namespace already exists, the current
       
  1332     object will be left in place and will not be overwritten. This allows
       
  1333     multiple calls to `namespace` to preserve existing namespaced properties.
       
  1334 
       
  1335     If the first token in the namespace string is "YAHOO", that token is
       
  1336     discarded. This is legacy behavior for backwards compatibility with YUI 2.
       
  1337 
       
  1338     Be careful with namespace tokens. Reserved words may work in some browsers
       
  1339     and not others. For instance, the following will fail in some browsers
       
  1340     because the supported version of JavaScript reserves the word "long":
       
  1341 
       
  1342         Y.namespace('really.long.nested.namespace');
       
  1343 
       
  1344     Note: If you pass multiple arguments to create multiple namespaces, only the
       
  1345     last one created is returned from this function.
       
  1346 
       
  1347     @method namespace
       
  1348     @param {String} namespace* One or more namespaces to create.
       
  1349     @return {Object} Reference to the last namespace object created.
       
  1350     **/
       
  1351     namespace: function() {
       
  1352         var a = arguments, o, i = 0, j, d, arg;
       
  1353 
       
  1354         for (; i < a.length; i++) {
       
  1355             o = this; //Reset base object per argument or it will get reused from the last
       
  1356             arg = a[i];
       
  1357             if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
       
  1358                 d = arg.split(PERIOD);
       
  1359                 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
       
  1360                     o[d[j]] = o[d[j]] || {};
       
  1361                     o = o[d[j]];
       
  1362                 }
       
  1363             } else {
       
  1364                 o[arg] = o[arg] || {};
       
  1365                 o = o[arg]; //Reset base object to the new object so it's returned
       
  1366             }
       
  1367         }
       
  1368         return o;
       
  1369     },
       
  1370 
       
  1371     // this is replaced if the log module is included
       
  1372     log: NOOP,
       
  1373     message: NOOP,
       
  1374     // this is replaced if the dump module is included
       
  1375     dump: function (o) { return ''+o; },
       
  1376 
       
  1377     /**
       
  1378     Reports an error.
       
  1379 
       
  1380     The reporting mechanism is controlled by the `throwFail` configuration
       
  1381     attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
       
  1382     truthy, a JS exception is thrown.
       
  1383 
       
  1384     If an `errorFn` is specified in the config it must return `true` to indicate
       
  1385     that the exception was handled and keep it from being thrown.
       
  1386 
       
  1387     @method error
       
  1388     @param {String} msg Error message.
       
  1389     @param {Error|String} [e] JavaScript error object or an error string.
       
  1390     @param {String} [src] Source of the error (such as the name of the module in
       
  1391         which the error occurred).
       
  1392     @chainable
       
  1393     **/
       
  1394     error: function(msg, e, src) {
       
  1395         //TODO Add check for window.onerror here
       
  1396 
       
  1397         var Y = this, ret;
       
  1398 
       
  1399         if (Y.config.errorFn) {
       
  1400             ret = Y.config.errorFn.apply(Y, arguments);
       
  1401         }
       
  1402 
       
  1403         if (!ret) {
       
  1404             throw (e || new Error(msg));
       
  1405         } else {
       
  1406             Y.message(msg, 'error', ''+src); // don't scrub this one
       
  1407         }
       
  1408 
       
  1409         return Y;
       
  1410     },
       
  1411 
       
  1412     /**
       
  1413     Generates an id string that is unique among all YUI instances in this
       
  1414     execution context.
       
  1415 
       
  1416     @method guid
       
  1417     @param {String} [pre] Prefix.
       
  1418     @return {String} Unique id.
       
  1419     **/
       
  1420     guid: function(pre) {
       
  1421         var id = this.Env._guidp + '_' + (++this.Env._uidx);
       
  1422         return (pre) ? (pre + id) : id;
       
  1423     },
       
  1424 
       
  1425     /**
       
  1426     Returns a unique id associated with the given object and (if *readOnly* is
       
  1427     falsy) stamps the object with that id so it can be identified in the future.
       
  1428 
       
  1429     Stamping an object involves adding a `_yuid` property to it that contains
       
  1430     the object's id. One exception to this is that in Internet Explorer, DOM
       
  1431     nodes have a `uniqueID` property that contains a browser-generated unique
       
  1432     id, which will be used instead of a YUI-generated id when available.
       
  1433 
       
  1434     @method stamp
       
  1435     @param {Object} o Object to stamp.
       
  1436     @param {Boolean} readOnly If truthy and the given object has not already
       
  1437         been stamped, the object will not be modified and `null` will be
       
  1438         returned.
       
  1439     @return {String} Object's unique id, or `null` if *readOnly* was truthy and
       
  1440         the given object was not already stamped.
       
  1441     **/
       
  1442     stamp: function(o, readOnly) {
       
  1443         var uid;
       
  1444         if (!o) {
       
  1445             return o;
       
  1446         }
       
  1447 
       
  1448         // IE generates its own unique ID for dom nodes
       
  1449         // The uniqueID property of a document node returns a new ID
       
  1450         if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
       
  1451             uid = o.uniqueID;
       
  1452         } else {
       
  1453             uid = (typeof o === 'string') ? o : o._yuid;
       
  1454         }
       
  1455 
       
  1456         if (!uid) {
       
  1457             uid = this.guid();
       
  1458             if (!readOnly) {
       
  1459                 try {
       
  1460                     o._yuid = uid;
       
  1461                 } catch (e) {
       
  1462                     uid = null;
       
  1463                 }
       
  1464             }
       
  1465         }
       
  1466         return uid;
       
  1467     },
       
  1468 
       
  1469     /**
       
  1470     Destroys this YUI instance.
       
  1471 
       
  1472     @method destroy
       
  1473     @since 3.3.0
       
  1474     **/
       
  1475     destroy: function() {
       
  1476         var Y = this;
       
  1477         if (Y.Event) {
       
  1478             Y.Event._unload();
       
  1479         }
       
  1480         delete instances[Y.id];
       
  1481         delete Y.Env;
       
  1482         delete Y.config;
       
  1483     }
       
  1484 
       
  1485     /**
       
  1486     Safe `instanceof` wrapper that works around a memory leak in IE when the
       
  1487     object being tested is `window` or `document`.
       
  1488 
       
  1489     Unless you are testing objects that may be `window` or `document`, you
       
  1490     should use the native `instanceof` operator instead of this method.
       
  1491 
       
  1492     @method instanceOf
       
  1493     @param {Object} o Object to check.
       
  1494     @param {Object} type Class to check against.
       
  1495     @since 3.3.0
       
  1496     **/
       
  1497 };
       
  1498 
       
  1499     YUI.prototype = proto;
       
  1500 
       
  1501     // inheritance utilities are not available yet
       
  1502     for (prop in proto) {
       
  1503         if (proto.hasOwnProperty(prop)) {
       
  1504             YUI[prop] = proto[prop];
       
  1505         }
       
  1506     }
       
  1507 
       
  1508     /**
       
  1509     Applies a configuration to all YUI instances in this execution context.
       
  1510 
       
  1511     The main use case for this method is in "mashups" where several third-party
       
  1512     scripts need to write to a global YUI config, but cannot share a single
       
  1513     centrally-managed config object. This way they can all call
       
  1514     `YUI.applyConfig({})` instead of overwriting the single global config.
       
  1515 
       
  1516     @example
       
  1517 
       
  1518         YUI.applyConfig({
       
  1519             modules: {
       
  1520                 davglass: {
       
  1521                     fullpath: './davglass.js'
       
  1522                 }
       
  1523             }
       
  1524         });
       
  1525 
       
  1526         YUI.applyConfig({
       
  1527             modules: {
       
  1528                 foo: {
       
  1529                     fullpath: './foo.js'
       
  1530                 }
       
  1531             }
       
  1532         });
       
  1533 
       
  1534         YUI().use('davglass', function (Y) {
       
  1535             // Module davglass will be available here.
       
  1536         });
       
  1537 
       
  1538     @method applyConfig
       
  1539     @param {Object} o Configuration object to apply.
       
  1540     @static
       
  1541     @since 3.5.0
       
  1542     **/
       
  1543     YUI.applyConfig = function(o) {
       
  1544         if (!o) {
       
  1545             return;
       
  1546         }
       
  1547         //If there is a GlobalConfig, apply it first to set the defaults
       
  1548         if (YUI.GlobalConfig) {
       
  1549             this.prototype.applyConfig.call(this, YUI.GlobalConfig);
       
  1550         }
       
  1551         //Apply this config to it
       
  1552         this.prototype.applyConfig.call(this, o);
       
  1553         //Reset GlobalConfig to the combined config
       
  1554         YUI.GlobalConfig = this.config;
       
  1555     };
       
  1556 
       
  1557     // set up the environment
       
  1558     YUI._init();
       
  1559 
       
  1560     if (hasWin) {
       
  1561         add(doc, 'DOMContentLoaded', handleReady);
       
  1562 
       
  1563         // add a window load event at load time so we can capture
       
  1564         // the case where it fires before dynamic loading is
       
  1565         // complete.
       
  1566         add(window, 'load', handleLoad);
       
  1567     } else {
       
  1568         handleReady();
       
  1569         handleLoad();
       
  1570     }
       
  1571 
       
  1572     YUI.Env.add = add;
       
  1573     YUI.Env.remove = remove;
       
  1574 
       
  1575     /*global exports*/
       
  1576     // Support the CommonJS method for exporting our single global
       
  1577     if (typeof exports == 'object') {
       
  1578         exports.YUI = YUI;
       
  1579         /**
       
  1580         * Set a method to be called when `Get.script` is called in Node.js
       
  1581         * `Get` will open the file, then pass it's content and it's path
       
  1582         * to this method before attaching it. Commonly used for code coverage
       
  1583         * instrumentation. <strong>Calling this multiple times will only
       
  1584         * attach the last hook method</strong>. This method is only
       
  1585         * available in Node.js.
       
  1586         * @method setLoadHook
       
  1587         * @static
       
  1588         * @param {Function} fn The function to set
       
  1589         * @param {String} fn.data The content of the file
       
  1590         * @param {String} fn.path The file path of the file
       
  1591         */
       
  1592         YUI.setLoadHook = function(fn) {
       
  1593             YUI._getLoadHook = fn;
       
  1594         };
       
  1595         /**
       
  1596         * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
       
  1597         * @method _getLoadHook
       
  1598         * @private
       
  1599         * @param {String} data The content of the file
       
  1600         * @param {String} path The file path of the file
       
  1601         */
       
  1602         YUI._getLoadHook = null;
       
  1603     }
       
  1604 
       
  1605     YUI.Env[VERSION] = {};
       
  1606 }());
       
  1607 
       
  1608 
       
  1609 /**
       
  1610 Config object that contains all of the configuration options for
       
  1611 this `YUI` instance.
       
  1612 
       
  1613 This object is supplied by the implementer when instantiating YUI. Some
       
  1614 properties have default values if they are not supplied by the implementer.
       
  1615 
       
  1616 This object should not be updated directly because some values are cached. Use
       
  1617 `applyConfig()` to update the config object on a YUI instance that has already
       
  1618 been configured.
       
  1619 
       
  1620 @class config
       
  1621 @static
       
  1622 **/
       
  1623 
       
  1624 /**
       
  1625 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
       
  1626 if they're needed to load additional dependencies and aren't already available.
       
  1627 
       
  1628 Setting this to `false` will prevent YUI from automatically loading the Loader
       
  1629 and module metadata, so you will need to manually ensure that they're available
       
  1630 or handle dependency resolution yourself.
       
  1631 
       
  1632 @property {Boolean} bootstrap
       
  1633 @default true
       
  1634 **/
       
  1635 
       
  1636 /**
       
  1637 
       
  1638 @property {Object} filters
       
  1639 **/
       
  1640 
       
  1641 /**
       
  1642 If `true`, YUI will use a combo handler to load multiple modules in as few
       
  1643 requests as possible.
       
  1644 
       
  1645 The YUI CDN (which YUI uses by default) supports combo handling, but other
       
  1646 servers may not. If the server from which you're loading YUI does not support
       
  1647 combo handling, set this to `false`.
       
  1648 
       
  1649 Providing a value for the `base` config property will cause `combine` to default
       
  1650 to `false` instead of `true`.
       
  1651 
       
  1652 @property {Boolean} combine
       
  1653 @default true
       
  1654 */
       
  1655 
       
  1656 /**
       
  1657 Array of module names that should never be dynamically loaded.
       
  1658 
       
  1659 @property {String[]} ignore
       
  1660 **/
       
  1661 
       
  1662 /**
       
  1663 Array of module names that should always be loaded when required, even if
       
  1664 already present on the page.
       
  1665 
       
  1666 @property {String[]} force
       
  1667 **/
       
  1668 
       
  1669 /**
       
  1670 DOM element or id that should be used as the insertion point for dynamically
       
  1671 added `<script>` and `<link>` nodes.
       
  1672 
       
  1673 @property {HTMLElement|String} insertBefore
       
  1674 **/
       
  1675 
       
  1676 /**
       
  1677 Object hash containing attributes to add to dynamically added `<script>` nodes.
       
  1678 
       
  1679 @property {Object} jsAttributes
       
  1680 **/
       
  1681 
       
  1682 /**
       
  1683 Object hash containing attributes to add to dynamically added `<link>` nodes.
       
  1684 
       
  1685 @property {Object} cssAttributes
       
  1686 **/
       
  1687 
       
  1688 /**
       
  1689 Timeout in milliseconds before a dynamic JS or CSS request will be considered a
       
  1690 failure. If not set, no timeout will be enforced.
       
  1691 
       
  1692 @property {Number} timeout
       
  1693 **/
       
  1694 
       
  1695 /**
       
  1696 Callback for the 'CSSComplete' event. When dynamically loading YUI components
       
  1697 with CSS, this property fires when the CSS is finished loading.
       
  1698 
       
  1699 This provides an opportunity to enhance the presentation of a loading page a
       
  1700 little bit before the entire loading process is done.
       
  1701 
       
  1702 @property {Function} onCSS
       
  1703 **/
       
  1704 
       
  1705 /**
       
  1706 A hash of module definitions to add to the list of available YUI modules. These
       
  1707 modules can then be dynamically loaded via the `use()` method.
       
  1708 
       
  1709 This is a hash in which keys are module names and values are objects containing
       
  1710 module metadata.
       
  1711 
       
  1712 See `Loader.addModule()` for the supported module metadata fields. Also see
       
  1713 `groups`, which provides a way to configure the base and combo spec for a set of
       
  1714 modules.
       
  1715 
       
  1716 @example
       
  1717 
       
  1718     modules: {
       
  1719         mymod1: {
       
  1720             requires: ['node'],
       
  1721             fullpath: '/mymod1/mymod1.js'
       
  1722         },
       
  1723 
       
  1724         mymod2: {
       
  1725             requires: ['mymod1'],
       
  1726             fullpath: '/mymod2/mymod2.js'
       
  1727         },
       
  1728 
       
  1729         mymod3: '/js/mymod3.js',
       
  1730         mycssmod: '/css/mycssmod.css'
       
  1731     }
       
  1732 
       
  1733 @property {Object} modules
       
  1734 **/
       
  1735 
       
  1736 /**
       
  1737 Aliases are dynamic groups of modules that can be used as shortcuts.
       
  1738 
       
  1739 @example
       
  1740 
       
  1741     YUI({
       
  1742         aliases: {
       
  1743             davglass: [ 'node', 'yql', 'dd' ],
       
  1744             mine: [ 'davglass', 'autocomplete']
       
  1745         }
       
  1746     }).use('mine', function (Y) {
       
  1747         // Node, YQL, DD & AutoComplete available here.
       
  1748     });
       
  1749 
       
  1750 @property {Object} aliases
       
  1751 **/
       
  1752 
       
  1753 /**
       
  1754 A hash of module group definitions.
       
  1755 
       
  1756 For each group you can specify a list of modules and the base path and
       
  1757 combo spec to use when dynamically loading the modules.
       
  1758 
       
  1759 @example
       
  1760 
       
  1761     groups: {
       
  1762         yui2: {
       
  1763             // specify whether or not this group has a combo service
       
  1764             combine: true,
       
  1765 
       
  1766             // The comboSeperator to use with this group's combo handler
       
  1767             comboSep: ';',
       
  1768 
       
  1769             // The maxURLLength for this server
       
  1770             maxURLLength: 500,
       
  1771 
       
  1772             // the base path for non-combo paths
       
  1773             base: 'http://yui.yahooapis.com/2.8.0r4/build/',
       
  1774 
       
  1775             // the path to the combo service
       
  1776             comboBase: 'http://yui.yahooapis.com/combo?',
       
  1777 
       
  1778             // a fragment to prepend to the path attribute when
       
  1779             // when building combo urls
       
  1780             root: '2.8.0r4/build/',
       
  1781 
       
  1782             // the module definitions
       
  1783             modules:  {
       
  1784                 yui2_yde: {
       
  1785                     path: "yahoo-dom-event/yahoo-dom-event.js"
       
  1786                 },
       
  1787                 yui2_anim: {
       
  1788                     path: "animation/animation.js",
       
  1789                     requires: ['yui2_yde']
       
  1790                 }
       
  1791             }
       
  1792         }
       
  1793     }
       
  1794 
       
  1795 @property {Object} groups
       
  1796 **/
       
  1797 
       
  1798 /**
       
  1799 Path to the Loader JS file, relative to the `base` path.
       
  1800 
       
  1801 This is used to dynamically bootstrap the Loader when it's needed and isn't yet
       
  1802 available.
       
  1803 
       
  1804 @property {String} loaderPath
       
  1805 @default "loader/loader-min.js"
       
  1806 **/
       
  1807 
       
  1808 /**
       
  1809 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
       
  1810 `false` to prevent YUI from loading any CSS, or set it to the string `"force"`
       
  1811 to force CSS dependencies to be loaded even if their associated JS modules are
       
  1812 already loaded.
       
  1813 
       
  1814 @property {Boolean|String} fetchCSS
       
  1815 @default true
       
  1816 **/
       
  1817 
       
  1818 /**
       
  1819 Default gallery version used to build gallery module urls.
       
  1820 
       
  1821 @property {String} gallery
       
  1822 @since 3.1.0
       
  1823 **/
       
  1824 
       
  1825 /**
       
  1826 Default YUI 2 version used to build YUI 2 module urls.
       
  1827 
       
  1828 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
       
  1829 `2in3` config for pulling different revisions of the wrapped YUI 2 modules.
       
  1830 
       
  1831 @property {String} yui2
       
  1832 @default "2.9.0"
       
  1833 @since 3.1.0
       
  1834 **/
       
  1835 
       
  1836 /**
       
  1837 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
       
  1838 
       
  1839 @property {String} 2in3
       
  1840 @default "4"
       
  1841 @since 3.1.0
       
  1842 **/
       
  1843 
       
  1844 /**
       
  1845 Alternate console log function that should be used in environments without a
       
  1846 supported native console. This function is executed with the YUI instance as its
       
  1847 `this` object.
       
  1848 
       
  1849 @property {Function} logFn
       
  1850 @since 3.1.0
       
  1851 **/
       
  1852 
       
  1853 /**
       
  1854 The minimum log level to log messages for. Log levels are defined
       
  1855 incrementally. Messages greater than or equal to the level specified will
       
  1856 be shown. All others will be discarded. The order of log levels in
       
  1857 increasing priority is:
       
  1858 
       
  1859     debug
       
  1860     info
       
  1861     warn
       
  1862     error
       
  1863 
       
  1864 @property {String} logLevel
       
  1865 @default 'debug'
       
  1866 @since 3.10.0
       
  1867 **/
       
  1868 
       
  1869 /**
       
  1870 Callback to execute when `Y.error()` is called. It receives the error message
       
  1871 and a JavaScript error object if one was provided.
       
  1872 
       
  1873 This function is executed with the YUI instance as its `this` object.
       
  1874 
       
  1875 Returning `true` from this function will prevent an exception from being thrown.
       
  1876 
       
  1877 @property {Function} errorFn
       
  1878 @param {String} errorFn.msg Error message
       
  1879 @param {Object} [errorFn.err] Error object (if one was provided).
       
  1880 @since 3.2.0
       
  1881 **/
       
  1882 
       
  1883 /**
       
  1884 A callback to execute when Loader fails to load one or more resources.
       
  1885 
       
  1886 This could be because of a script load failure. It could also be because a
       
  1887 module fails to register itself when the `requireRegistration` config is `true`.
       
  1888 
       
  1889 If this function is defined, the `use()` callback will only be called when the
       
  1890 loader succeeds. Otherwise, `use()` will always executes unless there was a
       
  1891 JavaScript error when attaching a module.
       
  1892 
       
  1893 @property {Function} loadErrorFn
       
  1894 @since 3.3.0
       
  1895 **/
       
  1896 
       
  1897 /**
       
  1898 If `true`, Loader will expect all loaded scripts to be first-class YUI modules
       
  1899 that register themselves with the YUI global, and will trigger a failure if a
       
  1900 loaded script does not register a YUI module.
       
  1901 
       
  1902 @property {Boolean} requireRegistration
       
  1903 @default false
       
  1904 @since 3.3.0
       
  1905 **/
       
  1906 
       
  1907 /**
       
  1908 Cache serviced use() requests.
       
  1909 
       
  1910 @property {Boolean} cacheUse
       
  1911 @default true
       
  1912 @since 3.3.0
       
  1913 @deprecated No longer used.
       
  1914 **/
       
  1915 
       
  1916 /**
       
  1917 Whether or not YUI should use native ES5 functionality when available for
       
  1918 features like `Y.Array.each()`, `Y.Object()`, etc.
       
  1919 
       
  1920 When `false`, YUI will always use its own fallback implementations instead of
       
  1921 relying on ES5 functionality, even when ES5 functionality is available.
       
  1922 
       
  1923 @property {Boolean} useNativeES5
       
  1924 @default true
       
  1925 @since 3.5.0
       
  1926 **/
       
  1927 
       
  1928 /**
       
  1929  * Leverage native JSON stringify if the browser has a native
       
  1930  * implementation.  In general, this is a good idea.  See the Known Issues
       
  1931  * section in the JSON user guide for caveats.  The default value is true
       
  1932  * for browsers with native JSON support.
       
  1933  *
       
  1934  * @property useNativeJSONStringify
       
  1935  * @type Boolean
       
  1936  * @default true
       
  1937  * @since 3.8.0
       
  1938  */
       
  1939 
       
  1940  /**
       
  1941  * Leverage native JSON parse if the browser has a native implementation.
       
  1942  * In general, this is a good idea.  See the Known Issues section in the
       
  1943  * JSON user guide for caveats.  The default value is true for browsers with
       
  1944  * native JSON support.
       
  1945  *
       
  1946  * @property useNativeJSONParse
       
  1947  * @type Boolean
       
  1948  * @default true
       
  1949  * @since 3.8.0
       
  1950  */
       
  1951 
       
  1952 /**
       
  1953 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
       
  1954 
       
  1955 @property {Object|String} delayUntil
       
  1956 @since 3.6.0
       
  1957 @example
       
  1958 
       
  1959 You can use `load` or `domready` strings by default:
       
  1960 
       
  1961     YUI({
       
  1962         delayUntil: 'domready'
       
  1963     }, function (Y) {
       
  1964         // This will not execute until 'domeready' occurs.
       
  1965     });
       
  1966 
       
  1967 Or you can delay until a node is available (with `available` or `contentready`):
       
  1968 
       
  1969     YUI({
       
  1970         delayUntil: {
       
  1971             event: 'available',
       
  1972             args : '#foo'
       
  1973         }
       
  1974     }, function (Y) {
       
  1975         // This will not execute until a node matching the selector "#foo" is
       
  1976         // available in the DOM.
       
  1977     });
       
  1978 
       
  1979 **/
       
  1980 YUI.add('yui-base', function (Y, NAME) {
       
  1981 
       
  1982 /*
       
  1983  * YUI stub
       
  1984  * @module yui
       
  1985  * @submodule yui-base
       
  1986  */
       
  1987 /**
       
  1988  * The YUI module contains the components required for building the YUI
       
  1989  * seed file.  This includes the script loading mechanism, a simple queue,
       
  1990  * and the core utilities for the library.
       
  1991  * @module yui
       
  1992  * @submodule yui-base
       
  1993  */
       
  1994 
       
  1995 /**
       
  1996  * Provides core language utilites and extensions used throughout YUI.
       
  1997  *
       
  1998  * @class Lang
       
  1999  * @static
       
  2000  */
       
  2001 
       
  2002 var L = Y.Lang || (Y.Lang = {}),
       
  2003 
       
  2004 STRING_PROTO = String.prototype,
       
  2005 TOSTRING     = Object.prototype.toString,
       
  2006 
       
  2007 TYPES = {
       
  2008     'undefined'        : 'undefined',
       
  2009     'number'           : 'number',
       
  2010     'boolean'          : 'boolean',
       
  2011     'string'           : 'string',
       
  2012     '[object Function]': 'function',
       
  2013     '[object RegExp]'  : 'regexp',
       
  2014     '[object Array]'   : 'array',
       
  2015     '[object Date]'    : 'date',
       
  2016     '[object Error]'   : 'error'
       
  2017 },
       
  2018 
       
  2019 SUBREGEX         = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
       
  2020 
       
  2021 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",
       
  2022 WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
       
  2023 TRIM_LEFT_REGEX  = new RegExp("^" + WHITESPACE_CLASS),
       
  2024 TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
       
  2025 TRIMREGEX        = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
       
  2026 
       
  2027 NATIVE_FN_REGEX  = /\{\s*\[(?:native code|function)\]\s*\}/i;
       
  2028 
       
  2029 // -- Protected Methods --------------------------------------------------------
       
  2030 
       
  2031 /**
       
  2032 Returns `true` if the given function appears to be implemented in native code,
       
  2033 `false` otherwise. Will always return `false` -- even in ES5-capable browsers --
       
  2034 if the `useNativeES5` YUI config option is set to `false`.
       
  2035 
       
  2036 This isn't guaranteed to be 100% accurate and won't work for anything other than
       
  2037 functions, but it can be useful for determining whether a function like
       
  2038 `Array.prototype.forEach` is native or a JS shim provided by another library.
       
  2039 
       
  2040 There's a great article by @kangax discussing certain flaws with this technique:
       
  2041 <http://perfectionkills.com/detecting-built-in-host-methods/>
       
  2042 
       
  2043 While his points are valid, it's still possible to benefit from this function
       
  2044 as long as it's used carefully and sparingly, and in such a way that false
       
  2045 negatives have minimal consequences. It's used internally to avoid using
       
  2046 potentially broken non-native ES5 shims that have been added to the page by
       
  2047 other libraries.
       
  2048 
       
  2049 @method _isNative
       
  2050 @param {Function} fn Function to test.
       
  2051 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
       
  2052 @static
       
  2053 @protected
       
  2054 @since 3.5.0
       
  2055 **/
       
  2056 L._isNative = function (fn) {
       
  2057     return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
       
  2058 };
       
  2059 
       
  2060 // -- Public Methods -----------------------------------------------------------
       
  2061 
       
  2062 /**
       
  2063  * Determines whether or not the provided item is an array.
       
  2064  *
       
  2065  * Returns `false` for array-like collections such as the function `arguments`
       
  2066  * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
       
  2067  * test for an array-like collection.
       
  2068  *
       
  2069  * @method isArray
       
  2070  * @param o The object to test.
       
  2071  * @return {boolean} true if o is an array.
       
  2072  * @static
       
  2073  */
       
  2074 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
       
  2075     return L.type(o) === 'array';
       
  2076 };
       
  2077 
       
  2078 /**
       
  2079  * Determines whether or not the provided item is a boolean.
       
  2080  * @method isBoolean
       
  2081  * @static
       
  2082  * @param o The object to test.
       
  2083  * @return {boolean} true if o is a boolean.
       
  2084  */
       
  2085 L.isBoolean = function(o) {
       
  2086     return typeof o === 'boolean';
       
  2087 };
       
  2088 
       
  2089 /**
       
  2090  * Determines whether or not the supplied item is a date instance.
       
  2091  * @method isDate
       
  2092  * @static
       
  2093  * @param o The object to test.
       
  2094  * @return {boolean} true if o is a date.
       
  2095  */
       
  2096 L.isDate = function(o) {
       
  2097     return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
       
  2098 };
       
  2099 
       
  2100 /**
       
  2101  * <p>
       
  2102  * Determines whether or not the provided item is a function.
       
  2103  * Note: Internet Explorer thinks certain functions are objects:
       
  2104  * </p>
       
  2105  *
       
  2106  * <pre>
       
  2107  * var obj = document.createElement("object");
       
  2108  * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
       
  2109  * &nbsp;
       
  2110  * var input = document.createElement("input"); // append to body
       
  2111  * Y.Lang.isFunction(input.focus) // reports false in IE
       
  2112  * </pre>
       
  2113  *
       
  2114  * <p>
       
  2115  * You will have to implement additional tests if these functions
       
  2116  * matter to you.
       
  2117  * </p>
       
  2118  *
       
  2119  * @method isFunction
       
  2120  * @static
       
  2121  * @param o The object to test.
       
  2122  * @return {boolean} true if o is a function.
       
  2123  */
       
  2124 L.isFunction = function(o) {
       
  2125     return L.type(o) === 'function';
       
  2126 };
       
  2127 
       
  2128 /**
       
  2129  * Determines whether or not the provided item is null.
       
  2130  * @method isNull
       
  2131  * @static
       
  2132  * @param o The object to test.
       
  2133  * @return {boolean} true if o is null.
       
  2134  */
       
  2135 L.isNull = function(o) {
       
  2136     return o === null;
       
  2137 };
       
  2138 
       
  2139 /**
       
  2140  * Determines whether or not the provided item is a legal number.
       
  2141  * @method isNumber
       
  2142  * @static
       
  2143  * @param o The object to test.
       
  2144  * @return {boolean} true if o is a number.
       
  2145  */
       
  2146 L.isNumber = function(o) {
       
  2147     return typeof o === 'number' && isFinite(o);
       
  2148 };
       
  2149 
       
  2150 /**
       
  2151  * Determines whether or not the provided item is of type object
       
  2152  * or function. Note that arrays are also objects, so
       
  2153  * <code>Y.Lang.isObject([]) === true</code>.
       
  2154  * @method isObject
       
  2155  * @static
       
  2156  * @param o The object to test.
       
  2157  * @param failfn {boolean} fail if the input is a function.
       
  2158  * @return {boolean} true if o is an object.
       
  2159  * @see isPlainObject
       
  2160  */
       
  2161 L.isObject = function(o, failfn) {
       
  2162     var t = typeof o;
       
  2163     return (o && (t === 'object' ||
       
  2164         (!failfn && (t === 'function' || L.isFunction(o))))) || false;
       
  2165 };
       
  2166 
       
  2167 /**
       
  2168  * Determines whether or not the provided value is a regexp.
       
  2169  * @method isRegExp
       
  2170  * @static
       
  2171  * @param value The value or object to test.
       
  2172  * @return {boolean} true if value is a regexp.
       
  2173  */
       
  2174 L.isRegExp = function(value) {
       
  2175     return L.type(value) === 'regexp';
       
  2176 };
       
  2177 
       
  2178 /**
       
  2179  * Determines whether or not the provided item is a string.
       
  2180  * @method isString
       
  2181  * @static
       
  2182  * @param o The object to test.
       
  2183  * @return {boolean} true if o is a string.
       
  2184  */
       
  2185 L.isString = function(o) {
       
  2186     return typeof o === 'string';
       
  2187 };
       
  2188 
       
  2189 /**
       
  2190  * Determines whether or not the provided item is undefined.
       
  2191  * @method isUndefined
       
  2192  * @static
       
  2193  * @param o The object to test.
       
  2194  * @return {boolean} true if o is undefined.
       
  2195  */
       
  2196 L.isUndefined = function(o) {
       
  2197     return typeof o === 'undefined';
       
  2198 };
       
  2199 
       
  2200 /**
       
  2201  * A convenience method for detecting a legitimate non-null value.
       
  2202  * Returns false for null/undefined/NaN, true for other values,
       
  2203  * including 0/false/''
       
  2204  * @method isValue
       
  2205  * @static
       
  2206  * @param o The item to test.
       
  2207  * @return {boolean} true if it is not null/undefined/NaN || false.
       
  2208  */
       
  2209 L.isValue = function(o) {
       
  2210     var t = L.type(o);
       
  2211 
       
  2212     switch (t) {
       
  2213         case 'number':
       
  2214             return isFinite(o);
       
  2215 
       
  2216         case 'null': // fallthru
       
  2217         case 'undefined':
       
  2218             return false;
       
  2219 
       
  2220         default:
       
  2221             return !!t;
       
  2222     }
       
  2223 };
       
  2224 
       
  2225 /**
       
  2226  * Returns the current time in milliseconds.
       
  2227  *
       
  2228  * @method now
       
  2229  * @return {Number} Current time in milliseconds.
       
  2230  * @static
       
  2231  * @since 3.3.0
       
  2232  */
       
  2233 L.now = Date.now || function () {
       
  2234     return new Date().getTime();
       
  2235 };
       
  2236 
       
  2237 /**
       
  2238  * Performs `{placeholder}` substitution on a string. The object passed as the 
       
  2239  * second parameter provides values to replace the `{placeholder}`s.
       
  2240  * `{placeholder}` token names must match property names of the object. For example,
       
  2241  * 
       
  2242  *`var greeting = Y.Lang.sub("Hello, {who}!", { who: "World" });`
       
  2243  *
       
  2244  * `{placeholder}` tokens that are undefined on the object map will be left 
       
  2245  * in tact (leaving unsightly `{placeholder}`'s in the output string). 
       
  2246  *
       
  2247  * @method sub
       
  2248  * @param {string} s String to be modified.
       
  2249  * @param {object} o Object containing replacement values.
       
  2250  * @return {string} the substitute result.
       
  2251  * @static
       
  2252  * @since 3.2.0
       
  2253  */
       
  2254 L.sub = function(s, o) {
       
  2255     return s.replace ? s.replace(SUBREGEX, function (match, key) {
       
  2256         return L.isUndefined(o[key]) ? match : o[key];
       
  2257     }) : s;
       
  2258 };
       
  2259 
       
  2260 /**
       
  2261  * Returns a string without any leading or trailing whitespace.  If
       
  2262  * the input is not a string, the input will be returned untouched.
       
  2263  * @method trim
       
  2264  * @static
       
  2265  * @param s {string} the string to trim.
       
  2266  * @return {string} the trimmed string.
       
  2267  */
       
  2268 L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
       
  2269     return s && s.trim ? s.trim() : s;
       
  2270 } : function (s) {
       
  2271     try {
       
  2272         return s.replace(TRIMREGEX, '');
       
  2273     } catch (e) {
       
  2274         return s;
       
  2275     }
       
  2276 };
       
  2277 
       
  2278 /**
       
  2279  * Returns a string without any leading whitespace.
       
  2280  * @method trimLeft
       
  2281  * @static
       
  2282  * @param s {string} the string to trim.
       
  2283  * @return {string} the trimmed string.
       
  2284  */
       
  2285 L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
       
  2286     return s.trimLeft();
       
  2287 } : function (s) {
       
  2288     return s.replace(TRIM_LEFT_REGEX, '');
       
  2289 };
       
  2290 
       
  2291 /**
       
  2292  * Returns a string without any trailing whitespace.
       
  2293  * @method trimRight
       
  2294  * @static
       
  2295  * @param s {string} the string to trim.
       
  2296  * @return {string} the trimmed string.
       
  2297  */
       
  2298 L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
       
  2299     return s.trimRight();
       
  2300 } : function (s) {
       
  2301     return s.replace(TRIM_RIGHT_REGEX, '');
       
  2302 };
       
  2303 
       
  2304 /**
       
  2305 Returns one of the following strings, representing the type of the item passed
       
  2306 in:
       
  2307 
       
  2308  * "array"
       
  2309  * "boolean"
       
  2310  * "date"
       
  2311  * "error"
       
  2312  * "function"
       
  2313  * "null"
       
  2314  * "number"
       
  2315  * "object"
       
  2316  * "regexp"
       
  2317  * "string"
       
  2318  * "undefined"
       
  2319 
       
  2320 Known issues:
       
  2321 
       
  2322  * `typeof HTMLElementCollection` returns function in Safari, but
       
  2323     `Y.Lang.type()` reports "object", which could be a good thing --
       
  2324     but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
       
  2325 
       
  2326 @method type
       
  2327 @param o the item to test.
       
  2328 @return {string} the detected type.
       
  2329 @static
       
  2330 **/
       
  2331 L.type = function(o) {
       
  2332     return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
       
  2333 };
       
  2334 /**
       
  2335 @module yui
       
  2336 @submodule yui-base
       
  2337 */
       
  2338 
       
  2339 var Lang   = Y.Lang,
       
  2340     Native = Array.prototype,
       
  2341 
       
  2342     hasOwn = Object.prototype.hasOwnProperty;
       
  2343 
       
  2344 /**
       
  2345 Provides utility methods for working with arrays. Additional array helpers can
       
  2346 be found in the `collection` and `array-extras` modules.
       
  2347 
       
  2348 `Y.Array(thing)` returns a native array created from _thing_. Depending on
       
  2349 _thing_'s type, one of the following will happen:
       
  2350 
       
  2351   * Arrays are returned unmodified unless a non-zero _startIndex_ is
       
  2352     specified.
       
  2353   * Array-like collections (see `Array.test()`) are converted to arrays.
       
  2354   * For everything else, a new array is created with _thing_ as the sole
       
  2355     item.
       
  2356 
       
  2357 Note: elements that are also collections, such as `<form>` and `<select>`
       
  2358 elements, are not automatically converted to arrays. To force a conversion,
       
  2359 pass `true` as the value of the _force_ parameter.
       
  2360 
       
  2361 @class Array
       
  2362 @constructor
       
  2363 @param {Any} thing The thing to arrayify.
       
  2364 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
       
  2365   collection, a subset of items starting at the specified index will be
       
  2366   returned.
       
  2367 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
       
  2368   array-like collection no matter what.
       
  2369 @return {Array} A native array created from _thing_, according to the rules
       
  2370   described above.
       
  2371 **/
       
  2372 function YArray(thing, startIndex, force) {
       
  2373     var len, result;
       
  2374 
       
  2375     /*jshint expr: true*/
       
  2376     startIndex || (startIndex = 0);
       
  2377 
       
  2378     if (force || YArray.test(thing)) {
       
  2379         // IE throws when trying to slice HTMLElement collections.
       
  2380         try {
       
  2381             return Native.slice.call(thing, startIndex);
       
  2382         } catch (ex) {
       
  2383             result = [];
       
  2384 
       
  2385             for (len = thing.length; startIndex < len; ++startIndex) {
       
  2386                 result.push(thing[startIndex]);
       
  2387             }
       
  2388 
       
  2389             return result;
       
  2390         }
       
  2391     }
       
  2392 
       
  2393     return [thing];
       
  2394 }
       
  2395 
       
  2396 Y.Array = YArray;
       
  2397 
       
  2398 /**
       
  2399 Dedupes an array of strings, returning an array that's guaranteed to contain
       
  2400 only one copy of a given string.
       
  2401 
       
  2402 This method differs from `Array.unique()` in that it's optimized for use only
       
  2403 with arrays consisting entirely of strings or entirely of numbers, whereas
       
  2404 `unique` may be used with other value types (but is slower).
       
  2405 
       
  2406 Using `dedupe()` with values other than strings or numbers, or with arrays
       
  2407 containing a mix of strings and numbers, may result in unexpected behavior.
       
  2408 
       
  2409 @method dedupe
       
  2410 @param {String[]|Number[]} array Array of strings or numbers to dedupe.
       
  2411 @return {Array} Copy of _array_ containing no duplicate values.
       
  2412 @static
       
  2413 @since 3.4.0
       
  2414 **/
       
  2415 YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
       
  2416     var hash    = Object.create(null),
       
  2417         results = [],
       
  2418         i, item, len;
       
  2419 
       
  2420     for (i = 0, len = array.length; i < len; ++i) {
       
  2421         item = array[i];
       
  2422 
       
  2423         if (!hash[item]) {
       
  2424             hash[item] = 1;
       
  2425             results.push(item);
       
  2426         }
       
  2427     }
       
  2428 
       
  2429     return results;
       
  2430 } : function (array) {
       
  2431     var hash    = {},
       
  2432         results = [],
       
  2433         i, item, len;
       
  2434 
       
  2435     for (i = 0, len = array.length; i < len; ++i) {
       
  2436         item = array[i];
       
  2437 
       
  2438         if (!hasOwn.call(hash, item)) {
       
  2439             hash[item] = 1;
       
  2440             results.push(item);
       
  2441         }
       
  2442     }
       
  2443 
       
  2444     return results;
       
  2445 };
       
  2446 
       
  2447 /**
       
  2448 Executes the supplied function on each item in the array. This method wraps
       
  2449 the native ES5 `Array.forEach()` method if available.
       
  2450 
       
  2451 @method each
       
  2452 @param {Array} array Array to iterate.
       
  2453 @param {Function} fn Function to execute on each item in the array. The function
       
  2454   will receive the following arguments:
       
  2455     @param {Any} fn.item Current array item.
       
  2456     @param {Number} fn.index Current array index.
       
  2457     @param {Array} fn.array Array being iterated.
       
  2458 @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  2459 @return {YUI} The YUI instance.
       
  2460 @static
       
  2461 **/
       
  2462 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
       
  2463     Native.forEach.call(array || [], fn, thisObj || Y);
       
  2464     return Y;
       
  2465 } : function (array, fn, thisObj) {
       
  2466     for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
       
  2467         if (i in array) {
       
  2468             fn.call(thisObj || Y, array[i], i, array);
       
  2469         }
       
  2470     }
       
  2471 
       
  2472     return Y;
       
  2473 };
       
  2474 
       
  2475 /**
       
  2476 Alias for `each()`.
       
  2477 
       
  2478 @method forEach
       
  2479 @static
       
  2480 **/
       
  2481 
       
  2482 /**
       
  2483 Returns an object using the first array as keys and the second as values. If
       
  2484 the second array is not provided, or if it doesn't contain the same number of
       
  2485 values as the first array, then `true` will be used in place of the missing
       
  2486 values.
       
  2487 
       
  2488 @example
       
  2489 
       
  2490     Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
       
  2491     // => {a: 'foo', b: 'bar', c: true}
       
  2492 
       
  2493 @method hash
       
  2494 @param {String[]} keys Array of strings to use as keys.
       
  2495 @param {Array} [values] Array to use as values.
       
  2496 @return {Object} Hash using the first array as keys and the second as values.
       
  2497 @static
       
  2498 **/
       
  2499 YArray.hash = function (keys, values) {
       
  2500     var hash = {},
       
  2501         vlen = (values && values.length) || 0,
       
  2502         i, len;
       
  2503 
       
  2504     for (i = 0, len = keys.length; i < len; ++i) {
       
  2505         if (i in keys) {
       
  2506             hash[keys[i]] = vlen > i && i in values ? values[i] : true;
       
  2507         }
       
  2508     }
       
  2509 
       
  2510     return hash;
       
  2511 };
       
  2512 
       
  2513 /**
       
  2514 Returns the index of the first item in the array that's equal (using a strict
       
  2515 equality check) to the specified _value_, or `-1` if the value isn't found.
       
  2516 
       
  2517 This method wraps the native ES5 `Array.indexOf()` method if available.
       
  2518 
       
  2519 @method indexOf
       
  2520 @param {Array} array Array to search.
       
  2521 @param {Any} value Value to search for.
       
  2522 @param {Number} [from=0] The index at which to begin the search.
       
  2523 @return {Number} Index of the item strictly equal to _value_, or `-1` if not
       
  2524     found.
       
  2525 @static
       
  2526 **/
       
  2527 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
       
  2528     return Native.indexOf.call(array, value, from);
       
  2529 } : function (array, value, from) {
       
  2530     // http://es5.github.com/#x15.4.4.14
       
  2531     var len = array.length;
       
  2532 
       
  2533     from = +from || 0;
       
  2534     from = (from > 0 || -1) * Math.floor(Math.abs(from));
       
  2535 
       
  2536     if (from < 0) {
       
  2537         from += len;
       
  2538 
       
  2539         if (from < 0) {
       
  2540             from = 0;
       
  2541         }
       
  2542     }
       
  2543 
       
  2544     for (; from < len; ++from) {
       
  2545         if (from in array && array[from] === value) {
       
  2546             return from;
       
  2547         }
       
  2548     }
       
  2549 
       
  2550     return -1;
       
  2551 };
       
  2552 
       
  2553 /**
       
  2554 Numeric sort convenience function.
       
  2555 
       
  2556 The native `Array.prototype.sort()` function converts values to strings and
       
  2557 sorts them in lexicographic order, which is unsuitable for sorting numeric
       
  2558 values. Provide `Array.numericSort` as a custom sort function when you want
       
  2559 to sort values in numeric order.
       
  2560 
       
  2561 @example
       
  2562 
       
  2563     [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
       
  2564     // => [4, 8, 15, 16, 23, 42]
       
  2565 
       
  2566 @method numericSort
       
  2567 @param {Number} a First value to compare.
       
  2568 @param {Number} b Second value to compare.
       
  2569 @return {Number} Difference between _a_ and _b_.
       
  2570 @static
       
  2571 **/
       
  2572 YArray.numericSort = function (a, b) {
       
  2573     return a - b;
       
  2574 };
       
  2575 
       
  2576 /**
       
  2577 Executes the supplied function on each item in the array. Returning a truthy
       
  2578 value from the function will stop the processing of remaining items.
       
  2579 
       
  2580 @method some
       
  2581 @param {Array} array Array to iterate over.
       
  2582 @param {Function} fn Function to execute on each item. The function will receive
       
  2583   the following arguments:
       
  2584     @param {Any} fn.value Current array item.
       
  2585     @param {Number} fn.index Current array index.
       
  2586     @param {Array} fn.array Array being iterated over.
       
  2587 @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  2588 @return {Boolean} `true` if the function returns a truthy value on any of the
       
  2589   items in the array; `false` otherwise.
       
  2590 @static
       
  2591 **/
       
  2592 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
       
  2593     return Native.some.call(array, fn, thisObj);
       
  2594 } : function (array, fn, thisObj) {
       
  2595     for (var i = 0, len = array.length; i < len; ++i) {
       
  2596         if (i in array && fn.call(thisObj, array[i], i, array)) {
       
  2597             return true;
       
  2598         }
       
  2599     }
       
  2600 
       
  2601     return false;
       
  2602 };
       
  2603 
       
  2604 /**
       
  2605 Evaluates _obj_ to determine if it's an array, an array-like collection, or
       
  2606 something else. This is useful when working with the function `arguments`
       
  2607 collection and `HTMLElement` collections.
       
  2608 
       
  2609 Note: This implementation doesn't consider elements that are also
       
  2610 collections, such as `<form>` and `<select>`, to be array-like.
       
  2611 
       
  2612 @method test
       
  2613 @param {Object} obj Object to test.
       
  2614 @return {Number} A number indicating the results of the test:
       
  2615 
       
  2616   * 0: Neither an array nor an array-like collection.
       
  2617   * 1: Real array.
       
  2618   * 2: Array-like collection.
       
  2619 
       
  2620 @static
       
  2621 **/
       
  2622 YArray.test = function (obj) {
       
  2623     var result = 0;
       
  2624 
       
  2625     if (Lang.isArray(obj)) {
       
  2626         result = 1;
       
  2627     } else if (Lang.isObject(obj)) {
       
  2628         try {
       
  2629             // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
       
  2630             // or functions without apply/call (Safari
       
  2631             // HTMLElementCollection bug).
       
  2632             if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
       
  2633                 result = 2;
       
  2634             }
       
  2635         } catch (ex) {}
       
  2636     }
       
  2637 
       
  2638     return result;
       
  2639 };
       
  2640 /**
       
  2641  * The YUI module contains the components required for building the YUI
       
  2642  * seed file.  This includes the script loading mechanism, a simple queue,
       
  2643  * and the core utilities for the library.
       
  2644  * @module yui
       
  2645  * @submodule yui-base
       
  2646  */
       
  2647 
       
  2648 /**
       
  2649  * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
       
  2650  * removed using next().
       
  2651  *
       
  2652  * @class Queue
       
  2653  * @constructor
       
  2654  * @param {MIXED} item* 0..n items to seed the queue.
       
  2655  */
       
  2656 function Queue() {
       
  2657     this._init();
       
  2658     this.add.apply(this, arguments);
       
  2659 }
       
  2660 
       
  2661 Queue.prototype = {
       
  2662     /**
       
  2663      * Initialize the queue
       
  2664      *
       
  2665      * @method _init
       
  2666      * @protected
       
  2667      */
       
  2668     _init: function() {
       
  2669         /**
       
  2670          * The collection of enqueued items
       
  2671          *
       
  2672          * @property _q
       
  2673          * @type Array
       
  2674          * @protected
       
  2675          */
       
  2676         this._q = [];
       
  2677     },
       
  2678 
       
  2679     /**
       
  2680      * Get the next item in the queue. FIFO support
       
  2681      *
       
  2682      * @method next
       
  2683      * @return {MIXED} the next item in the queue.
       
  2684      */
       
  2685     next: function() {
       
  2686         return this._q.shift();
       
  2687     },
       
  2688 
       
  2689     /**
       
  2690      * Get the last in the queue. LIFO support.
       
  2691      *
       
  2692      * @method last
       
  2693      * @return {MIXED} the last item in the queue.
       
  2694      */
       
  2695     last: function() {
       
  2696         return this._q.pop();
       
  2697     },
       
  2698 
       
  2699     /**
       
  2700      * Add 0..n items to the end of the queue.
       
  2701      *
       
  2702      * @method add
       
  2703      * @param {MIXED} item* 0..n items.
       
  2704      * @return {object} this queue.
       
  2705      */
       
  2706     add: function() {
       
  2707         this._q.push.apply(this._q, arguments);
       
  2708 
       
  2709         return this;
       
  2710     },
       
  2711 
       
  2712     /**
       
  2713      * Returns the current number of queued items.
       
  2714      *
       
  2715      * @method size
       
  2716      * @return {Number} The size.
       
  2717      */
       
  2718     size: function() {
       
  2719         return this._q.length;
       
  2720     }
       
  2721 };
       
  2722 
       
  2723 Y.Queue = Queue;
       
  2724 
       
  2725 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
       
  2726 
       
  2727 /**
       
  2728 The YUI module contains the components required for building the YUI seed file.
       
  2729 This includes the script loading mechanism, a simple queue, and the core
       
  2730 utilities for the library.
       
  2731 
       
  2732 @module yui
       
  2733 @submodule yui-base
       
  2734 **/
       
  2735 
       
  2736 var CACHED_DELIMITER = '__',
       
  2737 
       
  2738     hasOwn   = Object.prototype.hasOwnProperty,
       
  2739     isObject = Y.Lang.isObject;
       
  2740 
       
  2741 /**
       
  2742 Returns a wrapper for a function which caches the return value of that function,
       
  2743 keyed off of the combined string representation of the argument values provided
       
  2744 when the wrapper is called.
       
  2745 
       
  2746 Calling this function again with the same arguments will return the cached value
       
  2747 rather than executing the wrapped function.
       
  2748 
       
  2749 Note that since the cache is keyed off of the string representation of arguments
       
  2750 passed to the wrapper function, arguments that aren't strings and don't provide
       
  2751 a meaningful `toString()` method may result in unexpected caching behavior. For
       
  2752 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
       
  2753 string `[object Object]` when used as a cache key.
       
  2754 
       
  2755 @method cached
       
  2756 @param {Function} source The function to memoize.
       
  2757 @param {Object} [cache={}] Object in which to store cached values. You may seed
       
  2758   this object with pre-existing cached values if desired.
       
  2759 @param {any} [refetch] If supplied, this value is compared with the cached value
       
  2760   using a `==` comparison. If the values are equal, the wrapped function is
       
  2761   executed again even though a cached value exists.
       
  2762 @return {Function} Wrapped function.
       
  2763 @for YUI
       
  2764 **/
       
  2765 Y.cached = function (source, cache, refetch) {
       
  2766     /*jshint expr: true*/
       
  2767     cache || (cache = {});
       
  2768 
       
  2769     return function (arg) {
       
  2770         var key = arguments.length > 1 ?
       
  2771                 Array.prototype.join.call(arguments, CACHED_DELIMITER) :
       
  2772                 String(arg);
       
  2773 
       
  2774         /*jshint eqeqeq: false*/
       
  2775         if (!(key in cache) || (refetch && cache[key] == refetch)) {
       
  2776             cache[key] = source.apply(source, arguments);
       
  2777         }
       
  2778 
       
  2779         return cache[key];
       
  2780     };
       
  2781 };
       
  2782 
       
  2783 /**
       
  2784 Returns the `location` object from the window/frame in which this YUI instance
       
  2785 operates, or `undefined` when executing in a non-browser environment
       
  2786 (e.g. Node.js).
       
  2787 
       
  2788 It is _not_ recommended to hold references to the `window.location` object
       
  2789 outside of the scope of a function in which its properties are being accessed or
       
  2790 its methods are being called. This is because of a nasty bug/issue that exists
       
  2791 in both Safari and MobileSafari browsers:
       
  2792 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
       
  2793 
       
  2794 @method getLocation
       
  2795 @return {location} The `location` object from the window/frame in which this YUI
       
  2796     instance operates.
       
  2797 @since 3.5.0
       
  2798 **/
       
  2799 Y.getLocation = function () {
       
  2800     // It is safer to look this up every time because yui-base is attached to a
       
  2801     // YUI instance before a user's config is applied; i.e. `Y.config.win` does
       
  2802     // not point the correct window object when this file is loaded.
       
  2803     var win = Y.config.win;
       
  2804 
       
  2805     // It is not safe to hold a reference to the `location` object outside the
       
  2806     // scope in which it is being used. The WebKit engine used in Safari and
       
  2807     // MobileSafari will "disconnect" the `location` object from the `window`
       
  2808     // when a page is restored from back/forward history cache.
       
  2809     return win && win.location;
       
  2810 };
       
  2811 
       
  2812 /**
       
  2813 Returns a new object containing all of the properties of all the supplied
       
  2814 objects. The properties from later objects will overwrite those in earlier
       
  2815 objects.
       
  2816 
       
  2817 Passing in a single object will create a shallow copy of it. For a deep copy,
       
  2818 use `clone()`.
       
  2819 
       
  2820 @method merge
       
  2821 @param {Object} objects* One or more objects to merge.
       
  2822 @return {Object} A new merged object.
       
  2823 **/
       
  2824 Y.merge = function () {
       
  2825     var i      = 0,
       
  2826         len    = arguments.length,
       
  2827         result = {},
       
  2828         key,
       
  2829         obj;
       
  2830 
       
  2831     for (; i < len; ++i) {
       
  2832         obj = arguments[i];
       
  2833 
       
  2834         for (key in obj) {
       
  2835             if (hasOwn.call(obj, key)) {
       
  2836                 result[key] = obj[key];
       
  2837             }
       
  2838         }
       
  2839     }
       
  2840 
       
  2841     return result;
       
  2842 };
       
  2843 
       
  2844 /**
       
  2845 Mixes _supplier_'s properties into _receiver_.
       
  2846 
       
  2847 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
       
  2848 shadowed unless the _overwrite_ parameter is `true`, and will not be merged
       
  2849 unless the _merge_ parameter is `true`.
       
  2850 
       
  2851 In the default mode (0), only properties the supplier owns are copied (prototype
       
  2852 properties are not copied). The following copying modes are available:
       
  2853 
       
  2854   * `0`: _Default_. Object to object.
       
  2855   * `1`: Prototype to prototype.
       
  2856   * `2`: Prototype to prototype and object to object.
       
  2857   * `3`: Prototype to object.
       
  2858   * `4`: Object to prototype.
       
  2859 
       
  2860 @method mix
       
  2861 @param {Function|Object} receiver The object or function to receive the mixed
       
  2862   properties.
       
  2863 @param {Function|Object} supplier The object or function supplying the
       
  2864   properties to be mixed.
       
  2865 @param {Boolean} [overwrite=false] If `true`, properties that already exist
       
  2866   on the receiver will be overwritten with properties from the supplier.
       
  2867 @param {String[]} [whitelist] An array of property names to copy. If
       
  2868   specified, only the whitelisted properties will be copied, and all others
       
  2869   will be ignored.
       
  2870 @param {Number} [mode=0] Mix mode to use. See above for available modes.
       
  2871 @param {Boolean} [merge=false] If `true`, objects and arrays that already
       
  2872   exist on the receiver will have the corresponding object/array from the
       
  2873   supplier merged into them, rather than being skipped or overwritten. When
       
  2874   both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
       
  2875 @return {Function|Object|YUI} The receiver, or the YUI instance if the
       
  2876   specified receiver is falsy.
       
  2877 **/
       
  2878 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
       
  2879     var alwaysOverwrite, exists, from, i, key, len, to;
       
  2880 
       
  2881     // If no supplier is given, we return the receiver. If no receiver is given,
       
  2882     // we return Y. Returning Y doesn't make much sense to me, but it's
       
  2883     // grandfathered in for backcompat reasons.
       
  2884     if (!receiver || !supplier) {
       
  2885         return receiver || Y;
       
  2886     }
       
  2887 
       
  2888     if (mode) {
       
  2889         // In mode 2 (prototype to prototype and object to object), we recurse
       
  2890         // once to do the proto to proto mix. The object to object mix will be
       
  2891         // handled later on.
       
  2892         if (mode === 2) {
       
  2893             Y.mix(receiver.prototype, supplier.prototype, overwrite,
       
  2894                     whitelist, 0, merge);
       
  2895         }
       
  2896 
       
  2897         // Depending on which mode is specified, we may be copying from or to
       
  2898         // the prototypes of the supplier and receiver.
       
  2899         from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
       
  2900         to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
       
  2901 
       
  2902         // If either the supplier or receiver doesn't actually have a
       
  2903         // prototype property, then we could end up with an undefined `from`
       
  2904         // or `to`. If that happens, we abort and return the receiver.
       
  2905         if (!from || !to) {
       
  2906             return receiver;
       
  2907         }
       
  2908     } else {
       
  2909         from = supplier;
       
  2910         to   = receiver;
       
  2911     }
       
  2912 
       
  2913     // If `overwrite` is truthy and `merge` is falsy, then we can skip a
       
  2914     // property existence check on each iteration and save some time.
       
  2915     alwaysOverwrite = overwrite && !merge;
       
  2916 
       
  2917     if (whitelist) {
       
  2918         for (i = 0, len = whitelist.length; i < len; ++i) {
       
  2919             key = whitelist[i];
       
  2920 
       
  2921             // We call `Object.prototype.hasOwnProperty` instead of calling
       
  2922             // `hasOwnProperty` on the object itself, since the object's
       
  2923             // `hasOwnProperty` method may have been overridden or removed.
       
  2924             // Also, some native objects don't implement a `hasOwnProperty`
       
  2925             // method.
       
  2926             if (!hasOwn.call(from, key)) {
       
  2927                 continue;
       
  2928             }
       
  2929 
       
  2930             // The `key in to` check here is (sadly) intentional for backwards
       
  2931             // compatibility reasons. It prevents undesired shadowing of
       
  2932             // prototype members on `to`.
       
  2933             exists = alwaysOverwrite ? false : key in to;
       
  2934 
       
  2935             if (merge && exists && isObject(to[key], true)
       
  2936                     && isObject(from[key], true)) {
       
  2937                 // If we're in merge mode, and the key is present on both
       
  2938                 // objects, and the value on both objects is either an object or
       
  2939                 // an array (but not a function), then we recurse to merge the
       
  2940                 // `from` value into the `to` value instead of overwriting it.
       
  2941                 //
       
  2942                 // Note: It's intentional that the whitelist isn't passed to the
       
  2943                 // recursive call here. This is legacy behavior that lots of
       
  2944                 // code still depends on.
       
  2945                 Y.mix(to[key], from[key], overwrite, null, 0, merge);
       
  2946             } else if (overwrite || !exists) {
       
  2947                 // We're not in merge mode, so we'll only copy the `from` value
       
  2948                 // to the `to` value if we're in overwrite mode or if the
       
  2949                 // current key doesn't exist on the `to` object.
       
  2950                 to[key] = from[key];
       
  2951             }
       
  2952         }
       
  2953     } else {
       
  2954         for (key in from) {
       
  2955             // The code duplication here is for runtime performance reasons.
       
  2956             // Combining whitelist and non-whitelist operations into a single
       
  2957             // loop or breaking the shared logic out into a function both result
       
  2958             // in worse performance, and Y.mix is critical enough that the byte
       
  2959             // tradeoff is worth it.
       
  2960             if (!hasOwn.call(from, key)) {
       
  2961                 continue;
       
  2962             }
       
  2963 
       
  2964             // The `key in to` check here is (sadly) intentional for backwards
       
  2965             // compatibility reasons. It prevents undesired shadowing of
       
  2966             // prototype members on `to`.
       
  2967             exists = alwaysOverwrite ? false : key in to;
       
  2968 
       
  2969             if (merge && exists && isObject(to[key], true)
       
  2970                     && isObject(from[key], true)) {
       
  2971                 Y.mix(to[key], from[key], overwrite, null, 0, merge);
       
  2972             } else if (overwrite || !exists) {
       
  2973                 to[key] = from[key];
       
  2974             }
       
  2975         }
       
  2976 
       
  2977         // If this is an IE browser with the JScript enumeration bug, force
       
  2978         // enumeration of the buggy properties by making a recursive call with
       
  2979         // the buggy properties as the whitelist.
       
  2980         if (Y.Object._hasEnumBug) {
       
  2981             Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
       
  2982         }
       
  2983     }
       
  2984 
       
  2985     return receiver;
       
  2986 };
       
  2987 /**
       
  2988  * The YUI module contains the components required for building the YUI
       
  2989  * seed file.  This includes the script loading mechanism, a simple queue,
       
  2990  * and the core utilities for the library.
       
  2991  * @module yui
       
  2992  * @submodule yui-base
       
  2993  */
       
  2994 
       
  2995 /**
       
  2996  * Adds utilities to the YUI instance for working with objects.
       
  2997  *
       
  2998  * @class Object
       
  2999  */
       
  3000 
       
  3001 var Lang   = Y.Lang,
       
  3002     hasOwn = Object.prototype.hasOwnProperty,
       
  3003 
       
  3004     UNDEFINED, // <-- Note the comma. We're still declaring vars.
       
  3005 
       
  3006 /**
       
  3007  * Returns a new object that uses _obj_ as its prototype. This method wraps the
       
  3008  * native ES5 `Object.create()` method if available, but doesn't currently
       
  3009  * pass through `Object.create()`'s second argument (properties) in order to
       
  3010  * ensure compatibility with older browsers.
       
  3011  *
       
  3012  * @method ()
       
  3013  * @param {Object} obj Prototype object.
       
  3014  * @return {Object} New object using _obj_ as its prototype.
       
  3015  * @static
       
  3016  */
       
  3017 O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
       
  3018     // We currently wrap the native Object.create instead of simply aliasing it
       
  3019     // to ensure consistency with our fallback shim, which currently doesn't
       
  3020     // support Object.create()'s second argument (properties). Once we have a
       
  3021     // safe fallback for the properties arg, we can stop wrapping
       
  3022     // Object.create().
       
  3023     return Object.create(obj);
       
  3024 } : (function () {
       
  3025     // Reusable constructor function for the Object.create() shim.
       
  3026     function F() {}
       
  3027 
       
  3028     // The actual shim.
       
  3029     return function (obj) {
       
  3030         F.prototype = obj;
       
  3031         return new F();
       
  3032     };
       
  3033 }()),
       
  3034 
       
  3035 /**
       
  3036  * Property names that IE doesn't enumerate in for..in loops, even when they
       
  3037  * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
       
  3038  * manually enumerate these properties.
       
  3039  *
       
  3040  * @property _forceEnum
       
  3041  * @type String[]
       
  3042  * @protected
       
  3043  * @static
       
  3044  */
       
  3045 forceEnum = O._forceEnum = [
       
  3046     'hasOwnProperty',
       
  3047     'isPrototypeOf',
       
  3048     'propertyIsEnumerable',
       
  3049     'toString',
       
  3050     'toLocaleString',
       
  3051     'valueOf'
       
  3052 ],
       
  3053 
       
  3054 /**
       
  3055  * `true` if this browser has the JScript enumeration bug that prevents
       
  3056  * enumeration of the properties named in the `_forceEnum` array, `false`
       
  3057  * otherwise.
       
  3058  *
       
  3059  * See:
       
  3060  *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
       
  3061  *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
       
  3062  *
       
  3063  * @property _hasEnumBug
       
  3064  * @type Boolean
       
  3065  * @protected
       
  3066  * @static
       
  3067  */
       
  3068 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
       
  3069 
       
  3070 /**
       
  3071  * `true` if this browser incorrectly considers the `prototype` property of
       
  3072  * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
       
  3073  *
       
  3074  * @property _hasProtoEnumBug
       
  3075  * @type Boolean
       
  3076  * @protected
       
  3077  * @static
       
  3078  */
       
  3079 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
       
  3080 
       
  3081 /**
       
  3082  * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
       
  3083  * exists only on _obj_'s prototype. This is essentially a safer version of
       
  3084  * `obj.hasOwnProperty()`.
       
  3085  *
       
  3086  * @method owns
       
  3087  * @param {Object} obj Object to test.
       
  3088  * @param {String} key Property name to look for.
       
  3089  * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
       
  3090  * @static
       
  3091  */
       
  3092 owns = O.owns = function (obj, key) {
       
  3093     return !!obj && hasOwn.call(obj, key);
       
  3094 }; // <-- End of var declarations.
       
  3095 
       
  3096 /**
       
  3097  * Alias for `owns()`.
       
  3098  *
       
  3099  * @method hasKey
       
  3100  * @param {Object} obj Object to test.
       
  3101  * @param {String} key Property name to look for.
       
  3102  * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
       
  3103  * @static
       
  3104  */
       
  3105 O.hasKey = owns;
       
  3106 
       
  3107 /**
       
  3108  * Returns an array containing the object's enumerable keys. Does not include
       
  3109  * prototype keys or non-enumerable keys.
       
  3110  *
       
  3111  * Note that keys are returned in enumeration order (that is, in the same order
       
  3112  * that they would be enumerated by a `for-in` loop), which may not be the same
       
  3113  * as the order in which they were defined.
       
  3114  *
       
  3115  * This method is an alias for the native ES5 `Object.keys()` method if
       
  3116  * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of
       
  3117  * `Object.keys()` have an inconsistency as they consider `prototype` to be
       
  3118  * enumerable, so a non-native shim is used to rectify the difference.
       
  3119  *
       
  3120  * @example
       
  3121  *
       
  3122  *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
       
  3123  *     // => ['a', 'b', 'c']
       
  3124  *
       
  3125  * @method keys
       
  3126  * @param {Object} obj An object.
       
  3127  * @return {String[]} Array of keys.
       
  3128  * @static
       
  3129  */
       
  3130 O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
       
  3131     if (!Lang.isObject(obj)) {
       
  3132         throw new TypeError('Object.keys called on a non-object');
       
  3133     }
       
  3134 
       
  3135     var keys = [],
       
  3136         i, key, len;
       
  3137 
       
  3138     if (hasProtoEnumBug && typeof obj === 'function') {
       
  3139         for (key in obj) {
       
  3140             if (owns(obj, key) && key !== 'prototype') {
       
  3141                 keys.push(key);
       
  3142             }
       
  3143         }
       
  3144     } else {
       
  3145         for (key in obj) {
       
  3146             if (owns(obj, key)) {
       
  3147                 keys.push(key);
       
  3148             }
       
  3149         }
       
  3150     }
       
  3151 
       
  3152     if (hasEnumBug) {
       
  3153         for (i = 0, len = forceEnum.length; i < len; ++i) {
       
  3154             key = forceEnum[i];
       
  3155 
       
  3156             if (owns(obj, key)) {
       
  3157                 keys.push(key);
       
  3158             }
       
  3159         }
       
  3160     }
       
  3161 
       
  3162     return keys;
       
  3163 };
       
  3164 
       
  3165 /**
       
  3166  * Returns an array containing the values of the object's enumerable keys.
       
  3167  *
       
  3168  * Note that values are returned in enumeration order (that is, in the same
       
  3169  * order that they would be enumerated by a `for-in` loop), which may not be the
       
  3170  * same as the order in which they were defined.
       
  3171  *
       
  3172  * @example
       
  3173  *
       
  3174  *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
       
  3175  *     // => ['foo', 'bar', 'baz']
       
  3176  *
       
  3177  * @method values
       
  3178  * @param {Object} obj An object.
       
  3179  * @return {Array} Array of values.
       
  3180  * @static
       
  3181  */
       
  3182 O.values = function (obj) {
       
  3183     var keys   = O.keys(obj),
       
  3184         i      = 0,
       
  3185         len    = keys.length,
       
  3186         values = [];
       
  3187 
       
  3188     for (; i < len; ++i) {
       
  3189         values.push(obj[keys[i]]);
       
  3190     }
       
  3191 
       
  3192     return values;
       
  3193 };
       
  3194 
       
  3195 /**
       
  3196  * Returns the number of enumerable keys owned by an object.
       
  3197  *
       
  3198  * @method size
       
  3199  * @param {Object} obj An object.
       
  3200  * @return {Number} The object's size.
       
  3201  * @static
       
  3202  */
       
  3203 O.size = function (obj) {
       
  3204     try {
       
  3205         return O.keys(obj).length;
       
  3206     } catch (ex) {
       
  3207         return 0; // Legacy behavior for non-objects.
       
  3208     }
       
  3209 };
       
  3210 
       
  3211 /**
       
  3212  * Returns `true` if the object owns an enumerable property with the specified
       
  3213  * value.
       
  3214  *
       
  3215  * @method hasValue
       
  3216  * @param {Object} obj An object.
       
  3217  * @param {any} value The value to search for.
       
  3218  * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
       
  3219  * @static
       
  3220  */
       
  3221 O.hasValue = function (obj, value) {
       
  3222     return Y.Array.indexOf(O.values(obj), value) > -1;
       
  3223 };
       
  3224 
       
  3225 /**
       
  3226  * Executes a function on each enumerable property in _obj_. The function
       
  3227  * receives the value, the key, and the object itself as parameters (in that
       
  3228  * order).
       
  3229  *
       
  3230  * By default, only properties owned by _obj_ are enumerated. To include
       
  3231  * prototype properties, set the _proto_ parameter to `true`.
       
  3232  *
       
  3233  * @method each
       
  3234  * @param {Object} obj Object to enumerate.
       
  3235  * @param {Function} fn Function to execute on each enumerable property.
       
  3236  *   @param {mixed} fn.value Value of the current property.
       
  3237  *   @param {String} fn.key Key of the current property.
       
  3238  *   @param {Object} fn.obj Object being enumerated.
       
  3239  * @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  3240  * @param {Boolean} [proto=false] Include prototype properties.
       
  3241  * @return {YUI} the YUI instance.
       
  3242  * @chainable
       
  3243  * @static
       
  3244  */
       
  3245 O.each = function (obj, fn, thisObj, proto) {
       
  3246     var key;
       
  3247 
       
  3248     for (key in obj) {
       
  3249         if (proto || owns(obj, key)) {
       
  3250             fn.call(thisObj || Y, obj[key], key, obj);
       
  3251         }
       
  3252     }
       
  3253 
       
  3254     return Y;
       
  3255 };
       
  3256 
       
  3257 /**
       
  3258  * Executes a function on each enumerable property in _obj_, but halts if the
       
  3259  * function returns a truthy value. The function receives the value, the key,
       
  3260  * and the object itself as paramters (in that order).
       
  3261  *
       
  3262  * By default, only properties owned by _obj_ are enumerated. To include
       
  3263  * prototype properties, set the _proto_ parameter to `true`.
       
  3264  *
       
  3265  * @method some
       
  3266  * @param {Object} obj Object to enumerate.
       
  3267  * @param {Function} fn Function to execute on each enumerable property.
       
  3268  *   @param {mixed} fn.value Value of the current property.
       
  3269  *   @param {String} fn.key Key of the current property.
       
  3270  *   @param {Object} fn.obj Object being enumerated.
       
  3271  * @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  3272  * @param {Boolean} [proto=false] Include prototype properties.
       
  3273  * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
       
  3274  *   `false` otherwise.
       
  3275  * @static
       
  3276  */
       
  3277 O.some = function (obj, fn, thisObj, proto) {
       
  3278     var key;
       
  3279 
       
  3280     for (key in obj) {
       
  3281         if (proto || owns(obj, key)) {
       
  3282             if (fn.call(thisObj || Y, obj[key], key, obj)) {
       
  3283                 return true;
       
  3284             }
       
  3285         }
       
  3286     }
       
  3287 
       
  3288     return false;
       
  3289 };
       
  3290 
       
  3291 /**
       
  3292  * Retrieves the sub value at the provided path,
       
  3293  * from the value object provided.
       
  3294  *
       
  3295  * @method getValue
       
  3296  * @static
       
  3297  * @param o The object from which to extract the property value.
       
  3298  * @param path {Array} A path array, specifying the object traversal path
       
  3299  * from which to obtain the sub value.
       
  3300  * @return {Any} The value stored in the path, undefined if not found,
       
  3301  * undefined if the source is not an object.  Returns the source object
       
  3302  * if an empty path is provided.
       
  3303  */
       
  3304 O.getValue = function(o, path) {
       
  3305     if (!Lang.isObject(o)) {
       
  3306         return UNDEFINED;
       
  3307     }
       
  3308 
       
  3309     var i,
       
  3310         p = Y.Array(path),
       
  3311         l = p.length;
       
  3312 
       
  3313     for (i = 0; o !== UNDEFINED && i < l; i++) {
       
  3314         o = o[p[i]];
       
  3315     }
       
  3316 
       
  3317     return o;
       
  3318 };
       
  3319 
       
  3320 /**
       
  3321  * Sets the sub-attribute value at the provided path on the
       
  3322  * value object.  Returns the modified value object, or
       
  3323  * undefined if the path is invalid.
       
  3324  *
       
  3325  * @method setValue
       
  3326  * @static
       
  3327  * @param o             The object on which to set the sub value.
       
  3328  * @param path {Array}  A path array, specifying the object traversal path
       
  3329  *                      at which to set the sub value.
       
  3330  * @param val {Any}     The new value for the sub-attribute.
       
  3331  * @return {Object}     The modified object, with the new sub value set, or
       
  3332  *                      undefined, if the path was invalid.
       
  3333  */
       
  3334 O.setValue = function(o, path, val) {
       
  3335     var i,
       
  3336         p = Y.Array(path),
       
  3337         leafIdx = p.length - 1,
       
  3338         ref = o;
       
  3339 
       
  3340     if (leafIdx >= 0) {
       
  3341         for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
       
  3342             ref = ref[p[i]];
       
  3343         }
       
  3344 
       
  3345         if (ref !== UNDEFINED) {
       
  3346             ref[p[i]] = val;
       
  3347         } else {
       
  3348             return UNDEFINED;
       
  3349         }
       
  3350     }
       
  3351 
       
  3352     return o;
       
  3353 };
       
  3354 
       
  3355 /**
       
  3356  * Returns `true` if the object has no enumerable properties of its own.
       
  3357  *
       
  3358  * @method isEmpty
       
  3359  * @param {Object} obj An object.
       
  3360  * @return {Boolean} `true` if the object is empty.
       
  3361  * @static
       
  3362  * @since 3.2.0
       
  3363  */
       
  3364 O.isEmpty = function (obj) {
       
  3365     return !O.keys(Object(obj)).length;
       
  3366 };
       
  3367 /**
       
  3368  * The YUI module contains the components required for building the YUI seed
       
  3369  * file.  This includes the script loading mechanism, a simple queue, and the
       
  3370  * core utilities for the library.
       
  3371  * @module yui
       
  3372  * @submodule yui-base
       
  3373  */
       
  3374 
       
  3375 /**
       
  3376  * YUI user agent detection.
       
  3377  * Do not fork for a browser if it can be avoided.  Use feature detection when
       
  3378  * you can.  Use the user agent as a last resort.  For all fields listed
       
  3379  * as @type float, UA stores a version number for the browser engine,
       
  3380  * 0 otherwise.  This value may or may not map to the version number of
       
  3381  * the browser using the engine.  The value is presented as a float so
       
  3382  * that it can easily be used for boolean evaluation as well as for
       
  3383  * looking for a particular range of versions.  Because of this,
       
  3384  * some of the granularity of the version info may be lost.  The fields that
       
  3385  * are @type string default to null.  The API docs list the values that
       
  3386  * these fields can have.
       
  3387  * @class UA
       
  3388  * @static
       
  3389  */
       
  3390 
       
  3391 /**
       
  3392 * Static method on `YUI.Env` for parsing a UA string.  Called at instantiation
       
  3393 * to populate `Y.UA`.
       
  3394 *
       
  3395 * @static
       
  3396 * @method parseUA
       
  3397 * @param {String} [subUA=navigator.userAgent] UA string to parse
       
  3398 * @return {Object} The Y.UA object
       
  3399 */
       
  3400 YUI.Env.parseUA = function(subUA) {
       
  3401 
       
  3402     var numberify = function(s) {
       
  3403             var c = 0;
       
  3404             return parseFloat(s.replace(/\./g, function() {
       
  3405                 return (c++ === 1) ? '' : '.';
       
  3406             }));
       
  3407         },
       
  3408 
       
  3409         win = Y.config.win,
       
  3410 
       
  3411         nav = win && win.navigator,
       
  3412 
       
  3413         o = {
       
  3414 
       
  3415         /**
       
  3416          * Internet Explorer version number or 0.  Example: 6
       
  3417          * @property ie
       
  3418          * @type float
       
  3419          * @static
       
  3420          */
       
  3421         ie: 0,
       
  3422 
       
  3423         /**
       
  3424          * Opera version number or 0.  Example: 9.2
       
  3425          * @property opera
       
  3426          * @type float
       
  3427          * @static
       
  3428          */
       
  3429         opera: 0,
       
  3430 
       
  3431         /**
       
  3432          * Gecko engine revision number.  Will evaluate to 1 if Gecko
       
  3433          * is detected but the revision could not be found. Other browsers
       
  3434          * will be 0.  Example: 1.8
       
  3435          * <pre>
       
  3436          * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
       
  3437          * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
       
  3438          * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
       
  3439          * Firefox 3.0   <-- 1.9
       
  3440          * Firefox 3.5   <-- 1.91
       
  3441          * </pre>
       
  3442          * @property gecko
       
  3443          * @type float
       
  3444          * @static
       
  3445          */
       
  3446         gecko: 0,
       
  3447 
       
  3448         /**
       
  3449          * AppleWebKit version.  KHTML browsers that are not WebKit browsers
       
  3450          * will evaluate to 1, other browsers 0.  Example: 418.9
       
  3451          * <pre>
       
  3452          * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
       
  3453          *                                   latest available for Mac OSX 10.3.
       
  3454          * Safari 2.0.2:         416     <-- hasOwnProperty introduced
       
  3455          * Safari 2.0.4:         418     <-- preventDefault fixed
       
  3456          * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
       
  3457          *                                   different versions of webkit
       
  3458          * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
       
  3459          *                                   updated, but not updated
       
  3460          *                                   to the latest patch.
       
  3461          * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
       
  3462          * SVG and many major issues fixed).
       
  3463          * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
       
  3464          * update from 2.x via the 10.4.11 OS patch.
       
  3465          * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
       
  3466          *                                   yahoo.com user agent hack removed.
       
  3467          * </pre>
       
  3468          * http://en.wikipedia.org/wiki/Safari_version_history
       
  3469          * @property webkit
       
  3470          * @type float
       
  3471          * @static
       
  3472          */
       
  3473         webkit: 0,
       
  3474 
       
  3475         /**
       
  3476          * Safari will be detected as webkit, but this property will also
       
  3477          * be populated with the Safari version number
       
  3478          * @property safari
       
  3479          * @type float
       
  3480          * @static
       
  3481          */
       
  3482         safari: 0,
       
  3483 
       
  3484         /**
       
  3485          * Chrome will be detected as webkit, but this property will also
       
  3486          * be populated with the Chrome version number
       
  3487          * @property chrome
       
  3488          * @type float
       
  3489          * @static
       
  3490          */
       
  3491         chrome: 0,
       
  3492 
       
  3493         /**
       
  3494          * The mobile property will be set to a string containing any relevant
       
  3495          * user agent information when a modern mobile browser is detected.
       
  3496          * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
       
  3497          * devices with the WebKit-based browser, and Opera Mini.
       
  3498          * @property mobile
       
  3499          * @type string
       
  3500          * @default null
       
  3501          * @static
       
  3502          */
       
  3503         mobile: null,
       
  3504 
       
  3505         /**
       
  3506          * Adobe AIR version number or 0.  Only populated if webkit is detected.
       
  3507          * Example: 1.0
       
  3508          * @property air
       
  3509          * @type float
       
  3510          */
       
  3511         air: 0,
       
  3512         /**
       
  3513          * PhantomJS version number or 0.  Only populated if webkit is detected.
       
  3514          * Example: 1.0
       
  3515          * @property phantomjs
       
  3516          * @type float
       
  3517          */
       
  3518         phantomjs: 0,
       
  3519         /**
       
  3520          * Detects Apple iPad's OS version
       
  3521          * @property ipad
       
  3522          * @type float
       
  3523          * @static
       
  3524          */
       
  3525         ipad: 0,
       
  3526         /**
       
  3527          * Detects Apple iPhone's OS version
       
  3528          * @property iphone
       
  3529          * @type float
       
  3530          * @static
       
  3531          */
       
  3532         iphone: 0,
       
  3533         /**
       
  3534          * Detects Apples iPod's OS version
       
  3535          * @property ipod
       
  3536          * @type float
       
  3537          * @static
       
  3538          */
       
  3539         ipod: 0,
       
  3540         /**
       
  3541          * General truthy check for iPad, iPhone or iPod
       
  3542          * @property ios
       
  3543          * @type Boolean
       
  3544          * @default null
       
  3545          * @static
       
  3546          */
       
  3547         ios: null,
       
  3548         /**
       
  3549          * Detects Googles Android OS version
       
  3550          * @property android
       
  3551          * @type float
       
  3552          * @static
       
  3553          */
       
  3554         android: 0,
       
  3555         /**
       
  3556          * Detects Kindle Silk
       
  3557          * @property silk
       
  3558          * @type float
       
  3559          * @static
       
  3560          */
       
  3561         silk: 0,
       
  3562         /**
       
  3563          * Detects Kindle Silk Acceleration
       
  3564          * @property accel
       
  3565          * @type Boolean
       
  3566          * @static
       
  3567          */
       
  3568         accel: false,
       
  3569         /**
       
  3570          * Detects Palms WebOS version
       
  3571          * @property webos
       
  3572          * @type float
       
  3573          * @static
       
  3574          */
       
  3575         webos: 0,
       
  3576 
       
  3577         /**
       
  3578          * Google Caja version number or 0.
       
  3579          * @property caja
       
  3580          * @type float
       
  3581          */
       
  3582         caja: nav && nav.cajaVersion,
       
  3583 
       
  3584         /**
       
  3585          * Set to true if the page appears to be in SSL
       
  3586          * @property secure
       
  3587          * @type boolean
       
  3588          * @static
       
  3589          */
       
  3590         secure: false,
       
  3591 
       
  3592         /**
       
  3593          * The operating system.  Currently only detecting windows or macintosh
       
  3594          * @property os
       
  3595          * @type string
       
  3596          * @default null
       
  3597          * @static
       
  3598          */
       
  3599         os: null,
       
  3600 
       
  3601         /**
       
  3602          * The Nodejs Version
       
  3603          * @property nodejs
       
  3604          * @type float
       
  3605          * @default 0
       
  3606          * @static
       
  3607          */
       
  3608         nodejs: 0,
       
  3609         /**
       
  3610         * Window8/IE10 Application host environment
       
  3611         * @property winjs
       
  3612         * @type Boolean
       
  3613         * @static
       
  3614         */
       
  3615         winjs: !!((typeof Windows !== "undefined") && Windows.System),
       
  3616         /**
       
  3617         * Are touch/msPointer events available on this device
       
  3618         * @property touchEnabled
       
  3619         * @type Boolean
       
  3620         * @static
       
  3621         */
       
  3622         touchEnabled: false
       
  3623     },
       
  3624 
       
  3625     ua = subUA || nav && nav.userAgent,
       
  3626 
       
  3627     loc = win && win.location,
       
  3628 
       
  3629     href = loc && loc.href,
       
  3630 
       
  3631     m;
       
  3632 
       
  3633     /**
       
  3634     * The User Agent string that was parsed
       
  3635     * @property userAgent
       
  3636     * @type String
       
  3637     * @static
       
  3638     */
       
  3639     o.userAgent = ua;
       
  3640 
       
  3641 
       
  3642     o.secure = href && (href.toLowerCase().indexOf('https') === 0);
       
  3643 
       
  3644     if (ua) {
       
  3645 
       
  3646         if ((/windows|win32/i).test(ua)) {
       
  3647             o.os = 'windows';
       
  3648         } else if ((/macintosh|mac_powerpc/i).test(ua)) {
       
  3649             o.os = 'macintosh';
       
  3650         } else if ((/android/i).test(ua)) {
       
  3651             o.os = 'android';
       
  3652         } else if ((/symbos/i).test(ua)) {
       
  3653             o.os = 'symbos';
       
  3654         } else if ((/linux/i).test(ua)) {
       
  3655             o.os = 'linux';
       
  3656         } else if ((/rhino/i).test(ua)) {
       
  3657             o.os = 'rhino';
       
  3658         }
       
  3659 
       
  3660         // Modern KHTML browsers should qualify as Safari X-Grade
       
  3661         if ((/KHTML/).test(ua)) {
       
  3662             o.webkit = 1;
       
  3663         }
       
  3664         if ((/IEMobile|XBLWP7/).test(ua)) {
       
  3665             o.mobile = 'windows';
       
  3666         }
       
  3667         if ((/Fennec/).test(ua)) {
       
  3668             o.mobile = 'gecko';
       
  3669         }
       
  3670         // Modern WebKit browsers are at least X-Grade
       
  3671         m = ua.match(/AppleWebKit\/([^\s]*)/);
       
  3672         if (m && m[1]) {
       
  3673             o.webkit = numberify(m[1]);
       
  3674             o.safari = o.webkit;
       
  3675 
       
  3676             if (/PhantomJS/.test(ua)) {
       
  3677                 m = ua.match(/PhantomJS\/([^\s]*)/);
       
  3678                 if (m && m[1]) {
       
  3679                     o.phantomjs = numberify(m[1]);
       
  3680                 }
       
  3681             }
       
  3682 
       
  3683             // Mobile browser check
       
  3684             if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
       
  3685                 o.mobile = 'Apple'; // iPhone or iPod Touch
       
  3686 
       
  3687                 m = ua.match(/OS ([^\s]*)/);
       
  3688                 if (m && m[1]) {
       
  3689                     m = numberify(m[1].replace('_', '.'));
       
  3690                 }
       
  3691                 o.ios = m;
       
  3692                 o.os = 'ios';
       
  3693                 o.ipad = o.ipod = o.iphone = 0;
       
  3694 
       
  3695                 m = ua.match(/iPad|iPod|iPhone/);
       
  3696                 if (m && m[0]) {
       
  3697                     o[m[0].toLowerCase()] = o.ios;
       
  3698                 }
       
  3699             } else {
       
  3700                 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
       
  3701                 if (m) {
       
  3702                     // Nokia N-series, webOS, ex: NokiaN95
       
  3703                     o.mobile = m[0];
       
  3704                 }
       
  3705                 if (/webOS/.test(ua)) {
       
  3706                     o.mobile = 'WebOS';
       
  3707                     m = ua.match(/webOS\/([^\s]*);/);
       
  3708                     if (m && m[1]) {
       
  3709                         o.webos = numberify(m[1]);
       
  3710                     }
       
  3711                 }
       
  3712                 if (/ Android/.test(ua)) {
       
  3713                     if (/Mobile/.test(ua)) {
       
  3714                         o.mobile = 'Android';
       
  3715                     }
       
  3716                     m = ua.match(/Android ([^\s]*);/);
       
  3717                     if (m && m[1]) {
       
  3718                         o.android = numberify(m[1]);
       
  3719                     }
       
  3720 
       
  3721                 }
       
  3722                 if (/Silk/.test(ua)) {
       
  3723                     m = ua.match(/Silk\/([^\s]*)/);
       
  3724                     if (m && m[1]) {
       
  3725                         o.silk = numberify(m[1]);
       
  3726                     }
       
  3727                     if (!o.android) {
       
  3728                         o.android = 2.34; //Hack for desktop mode in Kindle
       
  3729                         o.os = 'Android';
       
  3730                     }
       
  3731                     if (/Accelerated=true/.test(ua)) {
       
  3732                         o.accel = true;
       
  3733                     }
       
  3734                 }
       
  3735             }
       
  3736 
       
  3737             m = ua.match(/OPR\/(\d+\.\d+)/);
       
  3738 
       
  3739             if (m && m[1]) {
       
  3740                 // Opera 15+ with Blink (pretends to be both Chrome and Safari)
       
  3741                 o.opera = numberify(m[1]);
       
  3742             } else {
       
  3743                 m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
       
  3744 
       
  3745                 if (m && m[1] && m[2]) {
       
  3746                     o.chrome = numberify(m[2]); // Chrome
       
  3747                     o.safari = 0; //Reset safari back to 0
       
  3748                     if (m[1] === 'CrMo') {
       
  3749                         o.mobile = 'chrome';
       
  3750                     }
       
  3751                 } else {
       
  3752                     m = ua.match(/AdobeAIR\/([^\s]*)/);
       
  3753                     if (m) {
       
  3754                         o.air = m[0]; // Adobe AIR 1.0 or better
       
  3755                     }
       
  3756                 }
       
  3757             }
       
  3758         }
       
  3759 
       
  3760         if (!o.webkit) { // not webkit
       
  3761 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
       
  3762             if (/Opera/.test(ua)) {
       
  3763                 m = ua.match(/Opera[\s\/]([^\s]*)/);
       
  3764                 if (m && m[1]) {
       
  3765                     o.opera = numberify(m[1]);
       
  3766                 }
       
  3767                 m = ua.match(/Version\/([^\s]*)/);
       
  3768                 if (m && m[1]) {
       
  3769                     o.opera = numberify(m[1]); // opera 10+
       
  3770                 }
       
  3771 
       
  3772                 if (/Opera Mobi/.test(ua)) {
       
  3773                     o.mobile = 'opera';
       
  3774                     m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
       
  3775                     if (m && m[1]) {
       
  3776                         o.opera = numberify(m[1]);
       
  3777                     }
       
  3778                 }
       
  3779                 m = ua.match(/Opera Mini[^;]*/);
       
  3780 
       
  3781                 if (m) {
       
  3782                     o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
       
  3783                 }
       
  3784             } else { // not opera or webkit
       
  3785                 m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
       
  3786 
       
  3787                 if (m && (m[1] || m[2])) {
       
  3788                     o.ie = numberify(m[1] || m[2]);
       
  3789                 } else { // not opera, webkit, or ie
       
  3790                     m = ua.match(/Gecko\/([^\s]*)/);
       
  3791 
       
  3792                     if (m) {
       
  3793                         o.gecko = 1; // Gecko detected, look for revision
       
  3794                         m = ua.match(/rv:([^\s\)]*)/);
       
  3795                         if (m && m[1]) {
       
  3796                             o.gecko = numberify(m[1]);
       
  3797                             if (/Mobile|Tablet/.test(ua)) {
       
  3798                                 o.mobile = "ffos";
       
  3799                             }
       
  3800                         }
       
  3801                     }
       
  3802                 }
       
  3803             }
       
  3804         }
       
  3805     }
       
  3806 
       
  3807     //Check for known properties to tell if touch events are enabled on this device or if
       
  3808     //the number of MSPointer touchpoints on this device is greater than 0.
       
  3809     if (win && nav && !(o.chrome && o.chrome < 6)) {
       
  3810         o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
       
  3811     }
       
  3812 
       
  3813     //It was a parsed UA, do not assign the global value.
       
  3814     if (!subUA) {
       
  3815 
       
  3816         if (typeof process === 'object') {
       
  3817 
       
  3818             if (process.versions && process.versions.node) {
       
  3819                 //NodeJS
       
  3820                 o.os = process.platform;
       
  3821                 o.nodejs = numberify(process.versions.node);
       
  3822             }
       
  3823         }
       
  3824 
       
  3825         YUI.Env.UA = o;
       
  3826 
       
  3827     }
       
  3828 
       
  3829     return o;
       
  3830 };
       
  3831 
       
  3832 
       
  3833 Y.UA = YUI.Env.UA || YUI.Env.parseUA();
       
  3834 
       
  3835 /**
       
  3836 Performs a simple comparison between two version numbers, accounting for
       
  3837 standard versioning logic such as the fact that "535.8" is a lower version than
       
  3838 "535.24", even though a simple numerical comparison would indicate that it's
       
  3839 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
       
  3840 considered equivalent.
       
  3841 
       
  3842 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
       
  3843 1 if _a_ is higher than _b_.
       
  3844 
       
  3845 Versions may be numbers or strings containing numbers and dots. For example,
       
  3846 both `535` and `"535.8.10"` are acceptable. A version string containing
       
  3847 non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
       
  3848 
       
  3849 @method compareVersions
       
  3850 @param {Number|String} a First version number to compare.
       
  3851 @param {Number|String} b Second version number to compare.
       
  3852 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
       
  3853     higher than _b_.
       
  3854 **/
       
  3855 Y.UA.compareVersions = function (a, b) {
       
  3856     var aPart, aParts, bPart, bParts, i, len;
       
  3857 
       
  3858     if (a === b) {
       
  3859         return 0;
       
  3860     }
       
  3861 
       
  3862     aParts = (a + '').split('.');
       
  3863     bParts = (b + '').split('.');
       
  3864 
       
  3865     for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
       
  3866         aPart = parseInt(aParts[i], 10);
       
  3867         bPart = parseInt(bParts[i], 10);
       
  3868 
       
  3869         /*jshint expr: true*/
       
  3870         isNaN(aPart) && (aPart = 0);
       
  3871         isNaN(bPart) && (bPart = 0);
       
  3872 
       
  3873         if (aPart < bPart) {
       
  3874             return -1;
       
  3875         }
       
  3876 
       
  3877         if (aPart > bPart) {
       
  3878             return 1;
       
  3879         }
       
  3880     }
       
  3881 
       
  3882     return 0;
       
  3883 };
       
  3884 YUI.Env.aliases = {
       
  3885     "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
       
  3886     "anim-shape-transform": ["anim-shape"],
       
  3887     "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","model-sync-local","router","view","view-node-map"],
       
  3888     "attribute": ["attribute-base","attribute-complex"],
       
  3889     "attribute-events": ["attribute-observable"],
       
  3890     "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
       
  3891     "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
       
  3892     "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
       
  3893     "base": ["base-base","base-pluginhost","base-build"],
       
  3894     "cache": ["cache-base","cache-offline","cache-plugin"],
       
  3895     "charts": ["charts-base"],
       
  3896     "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
       
  3897     "color": ["color-base","color-hsl","color-harmony"],
       
  3898     "controller": ["router"],
       
  3899     "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
       
  3900     "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
       
  3901     "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
       
  3902     "datatype": ["datatype-date","datatype-number","datatype-xml"],
       
  3903     "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
       
  3904     "datatype-number": ["datatype-number-parse","datatype-number-format"],
       
  3905     "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
       
  3906     "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
       
  3907     "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
       
  3908     "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
       
  3909     "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"],
       
  3910     "event-custom": ["event-custom-base","event-custom-complex"],
       
  3911     "event-gestures": ["event-flick","event-move"],
       
  3912     "handlebars": ["handlebars-compiler"],
       
  3913     "highlight": ["highlight-base","highlight-accentfold"],
       
  3914     "history": ["history-base","history-hash","history-html5"],
       
  3915     "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
       
  3916     "json": ["json-parse","json-stringify"],
       
  3917     "loader": ["loader-base","loader-rollup","loader-yui3"],
       
  3918     "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
       
  3919     "pluginhost": ["pluginhost-base","pluginhost-config"],
       
  3920     "querystring": ["querystring-parse","querystring-stringify"],
       
  3921     "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
       
  3922     "resize": ["resize-base","resize-proxy","resize-constrain"],
       
  3923     "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
       
  3924     "template": ["template-base","template-micro"],
       
  3925     "text": ["text-accentfold","text-wordbreak"],
       
  3926     "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
       
  3927 };
       
  3928 
       
  3929 
       
  3930 }, '@VERSION@', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
       
  3931 YUI.add('get', function (Y, NAME) {
       
  3932 
       
  3933 /*jslint boss:true, expr:true, laxbreak: true */
       
  3934 
       
  3935 /**
       
  3936 Provides dynamic loading of remote JavaScript and CSS resources.
       
  3937 
       
  3938 @module get
       
  3939 @class Get
       
  3940 @static
       
  3941 **/
       
  3942 
       
  3943 var Lang = Y.Lang,
       
  3944 
       
  3945     CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
       
  3946 
       
  3947     Get, Transaction;
       
  3948 
       
  3949 Y.Get = Get = {
       
  3950     // -- Public Properties ----------------------------------------------------
       
  3951 
       
  3952     /**
       
  3953     Default options for CSS requests. Options specified here will override
       
  3954     global defaults for CSS requests.
       
  3955 
       
  3956     See the `options` property for all available options.
       
  3957 
       
  3958     @property cssOptions
       
  3959     @type Object
       
  3960     @static
       
  3961     @since 3.5.0
       
  3962     **/
       
  3963     cssOptions: {
       
  3964         attributes: {
       
  3965             rel: 'stylesheet'
       
  3966         },
       
  3967 
       
  3968         doc         : Y.config.linkDoc || Y.config.doc,
       
  3969         pollInterval: 50
       
  3970     },
       
  3971 
       
  3972     /**
       
  3973     Default options for JS requests. Options specified here will override global
       
  3974     defaults for JS requests.
       
  3975 
       
  3976     See the `options` property for all available options.
       
  3977 
       
  3978     @property jsOptions
       
  3979     @type Object
       
  3980     @static
       
  3981     @since 3.5.0
       
  3982     **/
       
  3983     jsOptions: {
       
  3984         autopurge: true,
       
  3985         doc      : Y.config.scriptDoc || Y.config.doc
       
  3986     },
       
  3987 
       
  3988     /**
       
  3989     Default options to use for all requests.
       
  3990 
       
  3991     Note that while all available options are documented here for ease of
       
  3992     discovery, some options (like callback functions) only make sense at the
       
  3993     transaction level.
       
  3994 
       
  3995     Callback functions specified via the options object or the `options`
       
  3996     parameter of the `css()`, `js()`, or `load()` methods will receive the
       
  3997     transaction object as a parameter. See `Y.Get.Transaction` for details on
       
  3998     the properties and methods available on transactions.
       
  3999 
       
  4000     @static
       
  4001     @since 3.5.0
       
  4002     @property {Object} options
       
  4003 
       
  4004     @property {Boolean} [options.async=false] Whether or not to load scripts
       
  4005         asynchronously, meaning they're requested in parallel and execution
       
  4006         order is not guaranteed. Has no effect on CSS, since CSS is always
       
  4007         loaded asynchronously.
       
  4008 
       
  4009     @property {Object} [options.attributes] HTML attribute name/value pairs that
       
  4010         should be added to inserted nodes. By default, the `charset` attribute
       
  4011         will be set to "utf-8" and nodes will be given an auto-generated `id`
       
  4012         attribute, but you can override these with your own values if desired.
       
  4013 
       
  4014     @property {Boolean} [options.autopurge] Whether or not to automatically
       
  4015         purge inserted nodes after the purge threshold is reached. This is
       
  4016         `true` by default for JavaScript, but `false` for CSS since purging a
       
  4017         CSS node will also remove any styling applied by the referenced file.
       
  4018 
       
  4019     @property {Object} [options.context] `this` object to use when calling
       
  4020         callback functions. Defaults to the transaction object.
       
  4021 
       
  4022     @property {Mixed} [options.data] Arbitrary data object to pass to "on*"
       
  4023         callbacks.
       
  4024 
       
  4025     @property {Document} [options.doc] Document into which nodes should be
       
  4026         inserted. By default, the current document is used.
       
  4027 
       
  4028     @property {HTMLElement|String} [options.insertBefore] HTML element or id
       
  4029         string of an element before which all generated nodes should be
       
  4030         inserted. If not specified, Get will automatically determine the best
       
  4031         place to insert nodes for maximum compatibility.
       
  4032 
       
  4033     @property {Function} [options.onEnd] Callback to execute after a transaction
       
  4034         is complete, regardless of whether it succeeded or failed.
       
  4035 
       
  4036     @property {Function} [options.onFailure] Callback to execute after a
       
  4037         transaction fails, times out, or is aborted.
       
  4038 
       
  4039     @property {Function} [options.onProgress] Callback to execute after each
       
  4040         individual request in a transaction either succeeds or fails.
       
  4041 
       
  4042     @property {Function} [options.onSuccess] Callback to execute after a
       
  4043         transaction completes successfully with no errors. Note that in browsers
       
  4044         that don't support the `error` event on CSS `<link>` nodes, a failed CSS
       
  4045         request may still be reported as a success because in these browsers
       
  4046         it can be difficult or impossible to distinguish between success and
       
  4047         failure for CSS resources.
       
  4048 
       
  4049     @property {Function} [options.onTimeout] Callback to execute after a
       
  4050         transaction times out.
       
  4051 
       
  4052     @property {Number} [options.pollInterval=50] Polling interval (in
       
  4053         milliseconds) for detecting CSS load completion in browsers that don't
       
  4054         support the `load` event on `<link>` nodes. This isn't used for
       
  4055         JavaScript.
       
  4056 
       
  4057     @property {Number} [options.purgethreshold=20] Number of nodes to insert
       
  4058         before triggering an automatic purge when `autopurge` is `true`.
       
  4059 
       
  4060     @property {Number} [options.timeout] Number of milliseconds to wait before
       
  4061         aborting a transaction. When a timeout occurs, the `onTimeout` callback
       
  4062         is called, followed by `onFailure` and finally `onEnd`. By default,
       
  4063         there is no timeout.
       
  4064 
       
  4065     @property {String} [options.type] Resource type ("css" or "js"). This option
       
  4066         is set automatically by the `css()` and `js()` functions and will be
       
  4067         ignored there, but may be useful when using the `load()` function. If
       
  4068         not specified, the type will be inferred from the URL, defaulting to
       
  4069         "js" if the URL doesn't contain a recognizable file extension.
       
  4070     **/
       
  4071     options: {
       
  4072         attributes: {
       
  4073             charset: 'utf-8'
       
  4074         },
       
  4075 
       
  4076         purgethreshold: 20
       
  4077     },
       
  4078 
       
  4079     // -- Protected Properties -------------------------------------------------
       
  4080 
       
  4081     /**
       
  4082     Regex that matches a CSS URL. Used to guess the file type when it's not
       
  4083     specified.
       
  4084 
       
  4085     @property REGEX_CSS
       
  4086     @type RegExp
       
  4087     @final
       
  4088     @protected
       
  4089     @static
       
  4090     @since 3.5.0
       
  4091     **/
       
  4092     REGEX_CSS: /\.css(?:[?;].*)?$/i,
       
  4093 
       
  4094     /**
       
  4095     Regex that matches a JS URL. Used to guess the file type when it's not
       
  4096     specified.
       
  4097 
       
  4098     @property REGEX_JS
       
  4099     @type RegExp
       
  4100     @final
       
  4101     @protected
       
  4102     @static
       
  4103     @since 3.5.0
       
  4104     **/
       
  4105     REGEX_JS : /\.js(?:[?;].*)?$/i,
       
  4106 
       
  4107     /**
       
  4108     Contains information about the current environment, such as what script and
       
  4109     link injection features it supports.
       
  4110 
       
  4111     This object is created and populated the first time the `_getEnv()` method
       
  4112     is called.
       
  4113 
       
  4114     @property _env
       
  4115     @type Object
       
  4116     @protected
       
  4117     @static
       
  4118     @since 3.5.0
       
  4119     **/
       
  4120 
       
  4121     /**
       
  4122     Mapping of document _yuid strings to <head> or <base> node references so we
       
  4123     don't have to look the node up each time we want to insert a request node.
       
  4124 
       
  4125     @property _insertCache
       
  4126     @type Object
       
  4127     @protected
       
  4128     @static
       
  4129     @since 3.5.0
       
  4130     **/
       
  4131     _insertCache: {},
       
  4132 
       
  4133     /**
       
  4134     Information about the currently pending transaction, if any.
       
  4135 
       
  4136     This is actually an object with two properties: `callback`, containing the
       
  4137     optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
       
  4138     containing the actual transaction instance.
       
  4139 
       
  4140     @property _pending
       
  4141     @type Object
       
  4142     @protected
       
  4143     @static
       
  4144     @since 3.5.0
       
  4145     **/
       
  4146     _pending: null,
       
  4147 
       
  4148     /**
       
  4149     HTML nodes eligible to be purged next time autopurge is triggered.
       
  4150 
       
  4151     @property _purgeNodes
       
  4152     @type HTMLElement[]
       
  4153     @protected
       
  4154     @static
       
  4155     @since 3.5.0
       
  4156     **/
       
  4157     _purgeNodes: [],
       
  4158 
       
  4159     /**
       
  4160     Queued transactions and associated callbacks.
       
  4161 
       
  4162     @property _queue
       
  4163     @type Object[]
       
  4164     @protected
       
  4165     @static
       
  4166     @since 3.5.0
       
  4167     **/
       
  4168     _queue: [],
       
  4169 
       
  4170     // -- Public Methods -------------------------------------------------------
       
  4171 
       
  4172     /**
       
  4173     Aborts the specified transaction.
       
  4174 
       
  4175     This will cause the transaction's `onFailure` callback to be called and
       
  4176     will prevent any new script and link nodes from being added to the document,
       
  4177     but any resources that have already been requested will continue loading
       
  4178     (there's no safe way to prevent this, unfortunately).
       
  4179 
       
  4180     *Note:* This method is deprecated as of 3.5.0, and will be removed in a
       
  4181     future version of YUI. Use the transaction-level `abort()` method instead.
       
  4182 
       
  4183     @method abort
       
  4184     @param {Get.Transaction} transaction Transaction to abort.
       
  4185     @deprecated Use the `abort()` method on the transaction instead.
       
  4186     @static
       
  4187     **/
       
  4188     abort: function (transaction) {
       
  4189         var i, id, item, len, pending;
       
  4190 
       
  4191 
       
  4192         if (!transaction.abort) {
       
  4193             id          = transaction;
       
  4194             pending     = this._pending;
       
  4195             transaction = null;
       
  4196 
       
  4197             if (pending && pending.transaction.id === id) {
       
  4198                 transaction   = pending.transaction;
       
  4199                 this._pending = null;
       
  4200             } else {
       
  4201                 for (i = 0, len = this._queue.length; i < len; ++i) {
       
  4202                     item = this._queue[i].transaction;
       
  4203 
       
  4204                     if (item.id === id) {
       
  4205                         transaction = item;
       
  4206                         this._queue.splice(i, 1);
       
  4207                         break;
       
  4208                     }
       
  4209                 }
       
  4210             }
       
  4211         }
       
  4212 
       
  4213         transaction && transaction.abort();
       
  4214     },
       
  4215 
       
  4216     /**
       
  4217     Loads one or more CSS files.
       
  4218 
       
  4219     The _urls_ parameter may be provided as a URL string, a request object,
       
  4220     or an array of URL strings and/or request objects.
       
  4221 
       
  4222     A request object is just an object that contains a `url` property and zero
       
  4223     or more options that should apply specifically to that request.
       
  4224     Request-specific options take priority over transaction-level options and
       
  4225     default options.
       
  4226 
       
  4227     URLs may be relative or absolute, and do not have to have the same origin
       
  4228     as the current page.
       
  4229 
       
  4230     The `options` parameter may be omitted completely and a callback passed in
       
  4231     its place, if desired.
       
  4232 
       
  4233     @example
       
  4234 
       
  4235         // Load a single CSS file and log a message on completion.
       
  4236         Y.Get.css('foo.css', function (err) {
       
  4237             if (err) {
       
  4238             } else {
       
  4239             }
       
  4240         });
       
  4241 
       
  4242         // Load multiple CSS files and log a message when all have finished
       
  4243         // loading.
       
  4244         var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
       
  4245 
       
  4246         Y.Get.css(urls, function (err) {
       
  4247             if (err) {
       
  4248             } else {
       
  4249             }
       
  4250         });
       
  4251 
       
  4252         // Specify transaction-level options, which will apply to all requests
       
  4253         // within the transaction.
       
  4254         Y.Get.css(urls, {
       
  4255             attributes: {'class': 'my-css'},
       
  4256             timeout   : 5000
       
  4257         });
       
  4258 
       
  4259         // Specify per-request options, which override transaction-level and
       
  4260         // default options.
       
  4261         Y.Get.css([
       
  4262             {url: 'foo.css', attributes: {id: 'foo'}},
       
  4263             {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
       
  4264         ]);
       
  4265 
       
  4266     @method css
       
  4267     @param {String|Object|Array} urls URL string, request object, or array
       
  4268         of URLs and/or request objects to load.
       
  4269     @param {Object} [options] Options for this transaction. See the
       
  4270         `Y.Get.options` property for a complete list of available options.
       
  4271     @param {Function} [callback] Callback function to be called on completion.
       
  4272         This is a general callback and will be called before any more granular
       
  4273         callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
       
  4274         object.
       
  4275 
       
  4276         @param {Array|null} callback.err Array of errors that occurred during
       
  4277             the transaction, or `null` on success.
       
  4278         @param {Get.Transaction} callback.transaction Transaction object.
       
  4279 
       
  4280     @return {Get.Transaction} Transaction object.
       
  4281     @static
       
  4282     **/
       
  4283     css: function (urls, options, callback) {
       
  4284         return this._load('css', urls, options, callback);
       
  4285     },
       
  4286 
       
  4287     /**
       
  4288     Loads one or more JavaScript resources.
       
  4289 
       
  4290     The _urls_ parameter may be provided as a URL string, a request object,
       
  4291     or an array of URL strings and/or request objects.
       
  4292 
       
  4293     A request object is just an object that contains a `url` property and zero
       
  4294     or more options that should apply specifically to that request.
       
  4295     Request-specific options take priority over transaction-level options and
       
  4296     default options.
       
  4297 
       
  4298     URLs may be relative or absolute, and do not have to have the same origin
       
  4299     as the current page.
       
  4300 
       
  4301     The `options` parameter may be omitted completely and a callback passed in
       
  4302     its place, if desired.
       
  4303 
       
  4304     Scripts will be executed in the order they're specified unless the `async`
       
  4305     option is `true`, in which case they'll be loaded in parallel and executed
       
  4306     in whatever order they finish loading.
       
  4307 
       
  4308     @example
       
  4309 
       
  4310         // Load a single JS file and log a message on completion.
       
  4311         Y.Get.js('foo.js', function (err) {
       
  4312             if (err) {
       
  4313             } else {
       
  4314             }
       
  4315         });
       
  4316 
       
  4317         // Load multiple JS files, execute them in order, and log a message when
       
  4318         // all have finished loading.
       
  4319         var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
       
  4320 
       
  4321         Y.Get.js(urls, function (err) {
       
  4322             if (err) {
       
  4323             } else {
       
  4324             }
       
  4325         });
       
  4326 
       
  4327         // Specify transaction-level options, which will apply to all requests
       
  4328         // within the transaction.
       
  4329         Y.Get.js(urls, {
       
  4330             attributes: {'class': 'my-js'},
       
  4331             timeout   : 5000
       
  4332         });
       
  4333 
       
  4334         // Specify per-request options, which override transaction-level and
       
  4335         // default options.
       
  4336         Y.Get.js([
       
  4337             {url: 'foo.js', attributes: {id: 'foo'}},
       
  4338             {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
       
  4339         ]);
       
  4340 
       
  4341     @method js
       
  4342     @param {String|Object|Array} urls URL string, request object, or array
       
  4343         of URLs and/or request objects to load.
       
  4344     @param {Object} [options] Options for this transaction. See the
       
  4345         `Y.Get.options` property for a complete list of available options.
       
  4346     @param {Function} [callback] Callback function to be called on completion.
       
  4347         This is a general callback and will be called before any more granular
       
  4348         callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
       
  4349         object.
       
  4350 
       
  4351         @param {Array|null} callback.err Array of errors that occurred during
       
  4352             the transaction, or `null` on success.
       
  4353         @param {Get.Transaction} callback.transaction Transaction object.
       
  4354 
       
  4355     @return {Get.Transaction} Transaction object.
       
  4356     @since 3.5.0
       
  4357     @static
       
  4358     **/
       
  4359     js: function (urls, options, callback) {
       
  4360         return this._load('js', urls, options, callback);
       
  4361     },
       
  4362 
       
  4363     /**
       
  4364     Loads one or more CSS and/or JavaScript resources in the same transaction.
       
  4365 
       
  4366     Use this method when you want to load both CSS and JavaScript in a single
       
  4367     transaction and be notified when all requested URLs have finished loading,
       
  4368     regardless of type.
       
  4369 
       
  4370     Behavior and options are the same as for the `css()` and `js()` methods. If
       
  4371     a resource type isn't specified in per-request options or transaction-level
       
  4372     options, Get will guess the file type based on the URL's extension (`.css`
       
  4373     or `.js`, with or without a following query string). If the file type can't
       
  4374     be guessed from the URL, a warning will be logged and Get will assume the
       
  4375     URL is a JavaScript resource.
       
  4376 
       
  4377     @example
       
  4378 
       
  4379         // Load both CSS and JS files in a single transaction, and log a message
       
  4380         // when all files have finished loading.
       
  4381         Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
       
  4382             if (err) {
       
  4383             } else {
       
  4384             }
       
  4385         });
       
  4386 
       
  4387     @method load
       
  4388     @param {String|Object|Array} urls URL string, request object, or array
       
  4389         of URLs and/or request objects to load.
       
  4390     @param {Object} [options] Options for this transaction. See the
       
  4391         `Y.Get.options` property for a complete list of available options.
       
  4392     @param {Function} [callback] Callback function to be called on completion.
       
  4393         This is a general callback and will be called before any more granular
       
  4394         callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
       
  4395         object.
       
  4396 
       
  4397         @param {Array|null} err Array of errors that occurred during the
       
  4398             transaction, or `null` on success.
       
  4399         @param {Get.Transaction} Transaction object.
       
  4400 
       
  4401     @return {Get.Transaction} Transaction object.
       
  4402     @since 3.5.0
       
  4403     @static
       
  4404     **/
       
  4405     load: function (urls, options, callback) {
       
  4406         return this._load(null, urls, options, callback);
       
  4407     },
       
  4408 
       
  4409     // -- Protected Methods ----------------------------------------------------
       
  4410 
       
  4411     /**
       
  4412     Triggers an automatic purge if the purge threshold has been reached.
       
  4413 
       
  4414     @method _autoPurge
       
  4415     @param {Number} threshold Purge threshold to use, in milliseconds.
       
  4416     @protected
       
  4417     @since 3.5.0
       
  4418     @static
       
  4419     **/
       
  4420     _autoPurge: function (threshold) {
       
  4421         if (threshold && this._purgeNodes.length >= threshold) {
       
  4422             this._purge(this._purgeNodes);
       
  4423         }
       
  4424     },
       
  4425 
       
  4426     /**
       
  4427     Populates the `_env` property with information about the current
       
  4428     environment.
       
  4429 
       
  4430     @method _getEnv
       
  4431     @return {Object} Environment information.
       
  4432     @protected
       
  4433     @since 3.5.0
       
  4434     @static
       
  4435     **/
       
  4436     _getEnv: function () {
       
  4437         var doc = Y.config.doc,
       
  4438             ua  = Y.UA;
       
  4439 
       
  4440         // Note: some of these checks require browser sniffs since it's not
       
  4441         // feasible to load test files on every pageview just to perform a
       
  4442         // feature test. I'm sorry if this makes you sad.
       
  4443         return (this._env = {
       
  4444 
       
  4445             // True if this is a browser that supports disabling async mode on
       
  4446             // dynamically created script nodes. See
       
  4447             // https://developer.mozilla.org/En/HTML/Element/Script#Attributes
       
  4448 
       
  4449             // IE10 doesn't return true for the MDN feature test, so setting it explicitly,
       
  4450             // because it is async by default, and allows you to disable async by setting it to false
       
  4451             async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10),
       
  4452 
       
  4453             // True if this browser fires an event when a dynamically injected
       
  4454             // link node fails to load. This is currently true for Firefox 9+
       
  4455             // and WebKit 535.24+
       
  4456             cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0,
       
  4457 
       
  4458             // True if this browser fires an event when a dynamically injected
       
  4459             // link node finishes loading. This is currently true for IE, Opera,
       
  4460             // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
       
  4461             // DOM 0 "onload" event, but not "load". All versions of IE fire
       
  4462             // "onload".
       
  4463             // davglass: Seems that Chrome on Android needs this to be false.
       
  4464             cssLoad: (
       
  4465                     (!ua.gecko && !ua.webkit) || ua.gecko >= 9 ||
       
  4466                     ua.compareVersions(ua.webkit, 535.24) >= 0
       
  4467                 ) && !(ua.chrome && ua.chrome <= 18),
       
  4468 
       
  4469             // True if this browser preserves script execution order while
       
  4470             // loading scripts in parallel as long as the script node's `async`
       
  4471             // attribute is set to false to explicitly disable async execution.
       
  4472             preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10))
       
  4473         });
       
  4474     },
       
  4475 
       
  4476     _getTransaction: function (urls, options) {
       
  4477         var requests = [],
       
  4478             i, len, req, url;
       
  4479 
       
  4480         if (!Lang.isArray(urls)) {
       
  4481             urls = [urls];
       
  4482         }
       
  4483 
       
  4484         options = Y.merge(this.options, options);
       
  4485 
       
  4486         // Clone the attributes object so we don't end up modifying it by ref.
       
  4487         options.attributes = Y.merge(this.options.attributes,
       
  4488                 options.attributes);
       
  4489 
       
  4490         for (i = 0, len = urls.length; i < len; ++i) {
       
  4491             url = urls[i];
       
  4492             req = {attributes: {}};
       
  4493 
       
  4494             // If `url` is a string, we create a URL object for it, then mix in
       
  4495             // global options and request-specific options. If it's an object
       
  4496             // with a "url" property, we assume it's a request object containing
       
  4497             // URL-specific options.
       
  4498             if (typeof url === 'string') {
       
  4499                 req.url = url;
       
  4500             } else if (url.url) {
       
  4501                 // URL-specific options override both global defaults and
       
  4502                 // request-specific options.
       
  4503                 Y.mix(req, url, false, null, 0, true);
       
  4504                 url = url.url; // Make url a string so we can use it later.
       
  4505             } else {
       
  4506                 continue;
       
  4507             }
       
  4508 
       
  4509             Y.mix(req, options, false, null, 0, true);
       
  4510 
       
  4511             // If we didn't get an explicit type for this URL either in the
       
  4512             // request options or the URL-specific options, try to determine
       
  4513             // one from the file extension.
       
  4514             if (!req.type) {
       
  4515                 if (this.REGEX_CSS.test(url)) {
       
  4516                     req.type = 'css';
       
  4517                 } else {
       
  4518                     if (!this.REGEX_JS.test(url)) {
       
  4519                     }
       
  4520 
       
  4521                     req.type = 'js';
       
  4522                 }
       
  4523             }
       
  4524 
       
  4525             // Mix in type-specific default options, but don't overwrite any
       
  4526             // options that have already been set.
       
  4527             Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
       
  4528                 false, null, 0, true);
       
  4529 
       
  4530             // Give the node an id attribute if it doesn't already have one.
       
  4531             req.attributes.id || (req.attributes.id = Y.guid());
       
  4532 
       
  4533             // Backcompat for <3.5.0 behavior.
       
  4534             if (req.win) {
       
  4535                 req.doc = req.win.document;
       
  4536             } else {
       
  4537                 req.win = req.doc.defaultView || req.doc.parentWindow;
       
  4538             }
       
  4539 
       
  4540             if (req.charset) {
       
  4541                 req.attributes.charset = req.charset;
       
  4542             }
       
  4543 
       
  4544             requests.push(req);
       
  4545         }
       
  4546 
       
  4547         return new Transaction(requests, options);
       
  4548     },
       
  4549 
       
  4550     _load: function (type, urls, options, callback) {
       
  4551         var transaction;
       
  4552 
       
  4553         // Allow callback as third param.
       
  4554         if (typeof options === 'function') {
       
  4555             callback = options;
       
  4556             options  = {};
       
  4557         }
       
  4558 
       
  4559         options || (options = {});
       
  4560         options.type = type;
       
  4561 
       
  4562         options._onFinish = Get._onTransactionFinish;
       
  4563 
       
  4564         if (!this._env) {
       
  4565             this._getEnv();
       
  4566         }
       
  4567 
       
  4568         transaction = this._getTransaction(urls, options);
       
  4569 
       
  4570         this._queue.push({
       
  4571             callback   : callback,
       
  4572             transaction: transaction
       
  4573         });
       
  4574 
       
  4575         this._next();
       
  4576 
       
  4577         return transaction;
       
  4578     },
       
  4579 
       
  4580     _onTransactionFinish : function() {
       
  4581         Get._pending = null;
       
  4582         Get._next();
       
  4583     },
       
  4584 
       
  4585     _next: function () {
       
  4586         var item;
       
  4587 
       
  4588         if (this._pending) {
       
  4589             return;
       
  4590         }
       
  4591 
       
  4592         item = this._queue.shift();
       
  4593 
       
  4594         if (item) {
       
  4595             this._pending = item;
       
  4596             item.transaction.execute(item.callback);
       
  4597         }
       
  4598     },
       
  4599 
       
  4600     _purge: function (nodes) {
       
  4601         var purgeNodes    = this._purgeNodes,
       
  4602             isTransaction = nodes !== purgeNodes,
       
  4603             index, node;
       
  4604 
       
  4605         while (node = nodes.pop()) { // assignment
       
  4606             // Don't purge nodes that haven't finished loading (or errored out),
       
  4607             // since this can hang the transaction.
       
  4608             if (!node._yuiget_finished) {
       
  4609                 continue;
       
  4610             }
       
  4611 
       
  4612             node.parentNode && node.parentNode.removeChild(node);
       
  4613 
       
  4614             // If this is a transaction-level purge and this node also exists in
       
  4615             // the Get-level _purgeNodes array, we need to remove it from
       
  4616             // _purgeNodes to avoid creating a memory leak. The indexOf lookup
       
  4617             // sucks, but until we get WeakMaps, this is the least troublesome
       
  4618             // way to do this (we can't just hold onto node ids because they may
       
  4619             // not be in the same document).
       
  4620             if (isTransaction) {
       
  4621                 index = Y.Array.indexOf(purgeNodes, node);
       
  4622 
       
  4623                 if (index > -1) {
       
  4624                     purgeNodes.splice(index, 1);
       
  4625                 }
       
  4626             }
       
  4627         }
       
  4628     }
       
  4629 };
       
  4630 
       
  4631 /**
       
  4632 Alias for `js()`.
       
  4633 
       
  4634 @method script
       
  4635 @static
       
  4636 **/
       
  4637 Get.script = Get.js;
       
  4638 
       
  4639 /**
       
  4640 Represents a Get transaction, which may contain requests for one or more JS or
       
  4641 CSS files.
       
  4642 
       
  4643 This class should not be instantiated manually. Instances will be created and
       
  4644 returned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
       
  4645 
       
  4646 @class Get.Transaction
       
  4647 @constructor
       
  4648 @since 3.5.0
       
  4649 **/
       
  4650 Get.Transaction = Transaction = function (requests, options) {
       
  4651     var self = this;
       
  4652 
       
  4653     self.id       = Transaction._lastId += 1;
       
  4654     self.data     = options.data;
       
  4655     self.errors   = [];
       
  4656     self.nodes    = [];
       
  4657     self.options  = options;
       
  4658     self.requests = requests;
       
  4659 
       
  4660     self._callbacks = []; // callbacks to call after execution finishes
       
  4661     self._queue     = [];
       
  4662     self._reqsWaiting   = 0;
       
  4663 
       
  4664     // Deprecated pre-3.5.0 properties.
       
  4665     self.tId = self.id; // Use `id` instead.
       
  4666     self.win = options.win || Y.config.win;
       
  4667 };
       
  4668 
       
  4669 /**
       
  4670 Arbitrary data object associated with this transaction.
       
  4671 
       
  4672 This object comes from the options passed to `Get.css()`, `Get.js()`, or
       
  4673 `Get.load()`, and will be `undefined` if no data object was specified.
       
  4674 
       
  4675 @property {Object} data
       
  4676 **/
       
  4677 
       
  4678 /**
       
  4679 Array of errors that have occurred during this transaction, if any. Each error
       
  4680 object has the following properties:
       
  4681 `errors.error`: Error message.
       
  4682 `errors.request`: Request object related to the error.
       
  4683 
       
  4684 @since 3.5.0
       
  4685 @property {Object[]} errors
       
  4686 **/
       
  4687 
       
  4688 /**
       
  4689 Numeric id for this transaction, unique among all transactions within the same
       
  4690 YUI sandbox in the current pageview.
       
  4691 
       
  4692 @property {Number} id
       
  4693 @since 3.5.0
       
  4694 **/
       
  4695 
       
  4696 /**
       
  4697 HTMLElement nodes (native ones, not YUI Node instances) that have been inserted
       
  4698 during the current transaction.
       
  4699 
       
  4700 @property {HTMLElement[]} nodes
       
  4701 **/
       
  4702 
       
  4703 /**
       
  4704 Options associated with this transaction.
       
  4705 
       
  4706 See `Get.options` for the full list of available options.
       
  4707 
       
  4708 @property {Object} options
       
  4709 @since 3.5.0
       
  4710 **/
       
  4711 
       
  4712 /**
       
  4713 Request objects contained in this transaction. Each request object represents
       
  4714 one CSS or JS URL that will be (or has been) requested and loaded into the page.
       
  4715 
       
  4716 @property {Object} requests
       
  4717 @since 3.5.0
       
  4718 **/
       
  4719 
       
  4720 /**
       
  4721 Id of the most recent transaction.
       
  4722 
       
  4723 @property _lastId
       
  4724 @type Number
       
  4725 @protected
       
  4726 @static
       
  4727 **/
       
  4728 Transaction._lastId = 0;
       
  4729 
       
  4730 Transaction.prototype = {
       
  4731     // -- Public Properties ----------------------------------------------------
       
  4732 
       
  4733     /**
       
  4734     Current state of this transaction. One of "new", "executing", or "done".
       
  4735 
       
  4736     @property _state
       
  4737     @type String
       
  4738     @protected
       
  4739     **/
       
  4740     _state: 'new', // "new", "executing", or "done"
       
  4741 
       
  4742     // -- Public Methods -------------------------------------------------------
       
  4743 
       
  4744     /**
       
  4745     Aborts this transaction.
       
  4746 
       
  4747     This will cause the transaction's `onFailure` callback to be called and
       
  4748     will prevent any new script and link nodes from being added to the document,
       
  4749     but any resources that have already been requested will continue loading
       
  4750     (there's no safe way to prevent this, unfortunately).
       
  4751 
       
  4752     @method abort
       
  4753     @param {String} [msg="Aborted."] Optional message to use in the `errors`
       
  4754         array describing why the transaction was aborted.
       
  4755     **/
       
  4756     abort: function (msg) {
       
  4757         this._pending    = null;
       
  4758         this._pendingCSS = null;
       
  4759         this._pollTimer  = clearTimeout(this._pollTimer);
       
  4760         this._queue      = [];
       
  4761         this._reqsWaiting    = 0;
       
  4762 
       
  4763         this.errors.push({error: msg || 'Aborted'});
       
  4764         this._finish();
       
  4765     },
       
  4766 
       
  4767     /**
       
  4768     Begins execting the transaction.
       
  4769 
       
  4770     There's usually no reason to call this manually, since Get will call it
       
  4771     automatically when other pending transactions have finished. If you really
       
  4772     want to execute your transaction before Get does, you can, but be aware that
       
  4773     this transaction's scripts may end up executing before the scripts in other
       
  4774     pending transactions.
       
  4775 
       
  4776     If the transaction is already executing, the specified callback (if any)
       
  4777     will be queued and called after execution finishes. If the transaction has
       
  4778     already finished, the callback will be called immediately (the transaction
       
  4779     will not be executed again).
       
  4780 
       
  4781     @method execute
       
  4782     @param {Function} callback Callback function to execute after all requests
       
  4783         in the transaction are complete, or after the transaction is aborted.
       
  4784     **/
       
  4785     execute: function (callback) {
       
  4786         var self     = this,
       
  4787             requests = self.requests,
       
  4788             state    = self._state,
       
  4789             i, len, queue, req;
       
  4790 
       
  4791         if (state === 'done') {
       
  4792             callback && callback(self.errors.length ? self.errors : null, self);
       
  4793             return;
       
  4794         } else {
       
  4795             callback && self._callbacks.push(callback);
       
  4796 
       
  4797             if (state === 'executing') {
       
  4798                 return;
       
  4799             }
       
  4800         }
       
  4801 
       
  4802         self._state = 'executing';
       
  4803         self._queue = queue = [];
       
  4804 
       
  4805         if (self.options.timeout) {
       
  4806             self._timeout = setTimeout(function () {
       
  4807                 self.abort('Timeout');
       
  4808             }, self.options.timeout);
       
  4809         }
       
  4810 
       
  4811         self._reqsWaiting = requests.length;
       
  4812 
       
  4813         for (i = 0, len = requests.length; i < len; ++i) {
       
  4814             req = requests[i];
       
  4815 
       
  4816             if (req.async || req.type === 'css') {
       
  4817                 // No need to queue CSS or fully async JS.
       
  4818                 self._insert(req);
       
  4819             } else {
       
  4820                 queue.push(req);
       
  4821             }
       
  4822         }
       
  4823 
       
  4824         self._next();
       
  4825     },
       
  4826 
       
  4827     /**
       
  4828     Manually purges any `<script>` or `<link>` nodes this transaction has
       
  4829     created.
       
  4830 
       
  4831     Be careful when purging a transaction that contains CSS requests, since
       
  4832     removing `<link>` nodes will also remove any styles they applied.
       
  4833 
       
  4834     @method purge
       
  4835     **/
       
  4836     purge: function () {
       
  4837         Get._purge(this.nodes);
       
  4838     },
       
  4839 
       
  4840     // -- Protected Methods ----------------------------------------------------
       
  4841     _createNode: function (name, attrs, doc) {
       
  4842         var node = doc.createElement(name),
       
  4843             attr, testEl;
       
  4844 
       
  4845         if (!CUSTOM_ATTRS) {
       
  4846             // IE6 and IE7 expect property names rather than attribute names for
       
  4847             // certain attributes. Rather than sniffing, we do a quick feature
       
  4848             // test the first time _createNode() runs to determine whether we
       
  4849             // need to provide a workaround.
       
  4850             testEl = doc.createElement('div');
       
  4851             testEl.setAttribute('class', 'a');
       
  4852 
       
  4853             CUSTOM_ATTRS = testEl.className === 'a' ? {} : {
       
  4854                 'for'  : 'htmlFor',
       
  4855                 'class': 'className'
       
  4856             };
       
  4857         }
       
  4858 
       
  4859         for (attr in attrs) {
       
  4860             if (attrs.hasOwnProperty(attr)) {
       
  4861                 node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
       
  4862             }
       
  4863         }
       
  4864 
       
  4865         return node;
       
  4866     },
       
  4867 
       
  4868     _finish: function () {
       
  4869         var errors  = this.errors.length ? this.errors : null,
       
  4870             options = this.options,
       
  4871             thisObj = options.context || this,
       
  4872             data, i, len;
       
  4873 
       
  4874         if (this._state === 'done') {
       
  4875             return;
       
  4876         }
       
  4877 
       
  4878         this._state = 'done';
       
  4879 
       
  4880         for (i = 0, len = this._callbacks.length; i < len; ++i) {
       
  4881             this._callbacks[i].call(thisObj, errors, this);
       
  4882         }
       
  4883 
       
  4884         data = this._getEventData();
       
  4885 
       
  4886         if (errors) {
       
  4887             if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
       
  4888                 options.onTimeout.call(thisObj, data);
       
  4889             }
       
  4890 
       
  4891             if (options.onFailure) {
       
  4892                 options.onFailure.call(thisObj, data);
       
  4893             }
       
  4894         } else if (options.onSuccess) {
       
  4895             options.onSuccess.call(thisObj, data);
       
  4896         }
       
  4897 
       
  4898         if (options.onEnd) {
       
  4899             options.onEnd.call(thisObj, data);
       
  4900         }
       
  4901 
       
  4902         if (options._onFinish) {
       
  4903             options._onFinish();
       
  4904         }
       
  4905     },
       
  4906 
       
  4907     _getEventData: function (req) {
       
  4908         if (req) {
       
  4909             // This merge is necessary for backcompat. I hate it.
       
  4910             return Y.merge(this, {
       
  4911                 abort  : this.abort, // have to copy these because the prototype isn't preserved
       
  4912                 purge  : this.purge,
       
  4913                 request: req,
       
  4914                 url    : req.url,
       
  4915                 win    : req.win
       
  4916             });
       
  4917         } else {
       
  4918             return this;
       
  4919         }
       
  4920     },
       
  4921 
       
  4922     _getInsertBefore: function (req) {
       
  4923         var doc = req.doc,
       
  4924             el  = req.insertBefore,
       
  4925             cache, docStamp;
       
  4926 
       
  4927         if (el) {
       
  4928             return typeof el === 'string' ? doc.getElementById(el) : el;
       
  4929         }
       
  4930 
       
  4931         cache    = Get._insertCache;
       
  4932         docStamp = Y.stamp(doc);
       
  4933 
       
  4934         if ((el = cache[docStamp])) { // assignment
       
  4935             return el;
       
  4936         }
       
  4937 
       
  4938         // Inserting before a <base> tag apparently works around an IE bug
       
  4939         // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
       
  4940         // bug that is, exactly. Better safe than sorry?
       
  4941         if ((el = doc.getElementsByTagName('base')[0])) { // assignment
       
  4942             return (cache[docStamp] = el);
       
  4943         }
       
  4944 
       
  4945         // Look for a <head> element.
       
  4946         el = doc.head || doc.getElementsByTagName('head')[0];
       
  4947 
       
  4948         if (el) {
       
  4949             // Create a marker node at the end of <head> to use as an insertion
       
  4950             // point. Inserting before this node will ensure that all our CSS
       
  4951             // gets inserted in the correct order, to maintain style precedence.
       
  4952             el.appendChild(doc.createTextNode(''));
       
  4953             return (cache[docStamp] = el.lastChild);
       
  4954         }
       
  4955 
       
  4956         // If all else fails, just insert before the first script node on the
       
  4957         // page, which is virtually guaranteed to exist.
       
  4958         return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
       
  4959     },
       
  4960 
       
  4961     _insert: function (req) {
       
  4962         var env          = Get._env,
       
  4963             insertBefore = this._getInsertBefore(req),
       
  4964             isScript     = req.type === 'js',
       
  4965             node         = req.node,
       
  4966             self         = this,
       
  4967             ua           = Y.UA,
       
  4968             cssTimeout, nodeType;
       
  4969 
       
  4970         if (!node) {
       
  4971             if (isScript) {
       
  4972                 nodeType = 'script';
       
  4973             } else if (!env.cssLoad && ua.gecko) {
       
  4974                 nodeType = 'style';
       
  4975             } else {
       
  4976                 nodeType = 'link';
       
  4977             }
       
  4978 
       
  4979             node = req.node = this._createNode(nodeType, req.attributes,
       
  4980                 req.doc);
       
  4981         }
       
  4982 
       
  4983         function onError() {
       
  4984             self._progress('Failed to load ' + req.url, req);
       
  4985         }
       
  4986 
       
  4987         function onLoad() {
       
  4988             if (cssTimeout) {
       
  4989                 clearTimeout(cssTimeout);
       
  4990             }
       
  4991 
       
  4992             self._progress(null, req);
       
  4993         }
       
  4994 
       
  4995         // Deal with script asynchronicity.
       
  4996         if (isScript) {
       
  4997             node.setAttribute('src', req.url);
       
  4998 
       
  4999             if (req.async) {
       
  5000                 // Explicitly indicate that we want the browser to execute this
       
  5001                 // script asynchronously. This is necessary for older browsers
       
  5002                 // like Firefox <4.
       
  5003                 node.async = true;
       
  5004             } else {
       
  5005                 if (env.async) {
       
  5006                     // This browser treats injected scripts as async by default
       
  5007                     // (standard HTML5 behavior) but asynchronous loading isn't
       
  5008                     // desired, so tell the browser not to mark this script as
       
  5009                     // async.
       
  5010                     node.async = false;
       
  5011                 }
       
  5012 
       
  5013                 // If this browser doesn't preserve script execution order based
       
  5014                 // on insertion order, we'll need to avoid inserting other
       
  5015                 // scripts until this one finishes loading.
       
  5016                 if (!env.preservesScriptOrder) {
       
  5017                     this._pending = req;
       
  5018                 }
       
  5019             }
       
  5020         } else {
       
  5021             if (!env.cssLoad && ua.gecko) {
       
  5022                 // In Firefox <9, we can import the requested URL into a <style>
       
  5023                 // node and poll for the existence of node.sheet.cssRules. This
       
  5024                 // gives us a reliable way to determine CSS load completion that
       
  5025                 // also works for cross-domain stylesheets.
       
  5026                 //
       
  5027                 // Props to Zach Leatherman for calling my attention to this
       
  5028                 // technique.
       
  5029                 node.innerHTML = (req.attributes.charset ?
       
  5030                     '@charset "' + req.attributes.charset + '";' : '') +
       
  5031                     '@import "' + req.url + '";';
       
  5032             } else {
       
  5033                 node.setAttribute('href', req.url);
       
  5034             }
       
  5035         }
       
  5036 
       
  5037         // Inject the node.
       
  5038         if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) {
       
  5039             // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode.
       
  5040             node.onreadystatechange = function () {
       
  5041                 if (/loaded|complete/.test(node.readyState)) {
       
  5042                     node.onreadystatechange = null;
       
  5043                     onLoad();
       
  5044                 }
       
  5045             };
       
  5046         } else if (!isScript && !env.cssLoad) {
       
  5047             // CSS on Firefox <9 or WebKit.
       
  5048             this._poll(req);
       
  5049         } else {
       
  5050             // Script or CSS on everything else. Using DOM 0 events because that
       
  5051             // evens the playing field with older IEs.
       
  5052 
       
  5053             if (ua.ie >= 10) {
       
  5054 
       
  5055                 // We currently need to introduce a timeout for IE10, since it
       
  5056                 // calls onerror/onload synchronously for 304s - messing up existing
       
  5057                 // program flow.
       
  5058 
       
  5059                 // Remove this block if the following bug gets fixed by GA
       
  5060                 /*jshint maxlen: 1500 */
       
  5061                 // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload
       
  5062                 node.onerror = function() { setTimeout(onError, 0); };
       
  5063                 node.onload  = function() { setTimeout(onLoad, 0); };
       
  5064             } else {
       
  5065                 node.onerror = onError;
       
  5066                 node.onload  = onLoad;
       
  5067             }
       
  5068 
       
  5069             // If this browser doesn't fire an event when CSS fails to load,
       
  5070             // fail after a timeout to avoid blocking the transaction queue.
       
  5071             if (!env.cssFail && !isScript) {
       
  5072                 cssTimeout = setTimeout(onError, req.timeout || 3000);
       
  5073             }
       
  5074         }
       
  5075 
       
  5076         this.nodes.push(node);
       
  5077         insertBefore.parentNode.insertBefore(node, insertBefore);
       
  5078     },
       
  5079 
       
  5080     _next: function () {
       
  5081         if (this._pending) {
       
  5082             return;
       
  5083         }
       
  5084 
       
  5085         // If there are requests in the queue, insert the next queued request.
       
  5086         // Otherwise, if we're waiting on already-inserted requests to finish,
       
  5087         // wait longer. If there are no queued requests and we're not waiting
       
  5088         // for anything to load, then we're done!
       
  5089         if (this._queue.length) {
       
  5090             this._insert(this._queue.shift());
       
  5091         } else if (!this._reqsWaiting) {
       
  5092             this._finish();
       
  5093         }
       
  5094     },
       
  5095 
       
  5096     _poll: function (newReq) {
       
  5097         var self       = this,
       
  5098             pendingCSS = self._pendingCSS,
       
  5099             isWebKit   = Y.UA.webkit,
       
  5100             i, hasRules, j, nodeHref, req, sheets;
       
  5101 
       
  5102         if (newReq) {
       
  5103             pendingCSS || (pendingCSS = self._pendingCSS = []);
       
  5104             pendingCSS.push(newReq);
       
  5105 
       
  5106             if (self._pollTimer) {
       
  5107                 // A poll timeout is already pending, so no need to create a
       
  5108                 // new one.
       
  5109                 return;
       
  5110             }
       
  5111         }
       
  5112 
       
  5113         self._pollTimer = null;
       
  5114 
       
  5115         // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
       
  5116         // will still be treated as a success. There's no good workaround for
       
  5117         // this.
       
  5118 
       
  5119         for (i = 0; i < pendingCSS.length; ++i) {
       
  5120             req = pendingCSS[i];
       
  5121 
       
  5122             if (isWebKit) {
       
  5123                 // Look for a stylesheet matching the pending URL.
       
  5124                 sheets   = req.doc.styleSheets;
       
  5125                 j        = sheets.length;
       
  5126                 nodeHref = req.node.href;
       
  5127 
       
  5128                 while (--j >= 0) {
       
  5129                     if (sheets[j].href === nodeHref) {
       
  5130                         pendingCSS.splice(i, 1);
       
  5131                         i -= 1;
       
  5132                         self._progress(null, req);
       
  5133                         break;
       
  5134                     }
       
  5135                 }
       
  5136             } else {
       
  5137                 // Many thanks to Zach Leatherman for calling my attention to
       
  5138                 // the @import-based cross-domain technique used here, and to
       
  5139                 // Oleg Slobodskoi for an earlier same-domain implementation.
       
  5140                 //
       
  5141                 // See Zach's blog for more details:
       
  5142                 // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
       
  5143                 try {
       
  5144                     // We don't really need to store this value since we never
       
  5145                     // use it again, but if we don't store it, Closure Compiler
       
  5146                     // assumes the code is useless and removes it.
       
  5147                     hasRules = !!req.node.sheet.cssRules;
       
  5148 
       
  5149                     // If we get here, the stylesheet has loaded.
       
  5150                     pendingCSS.splice(i, 1);
       
  5151                     i -= 1;
       
  5152                     self._progress(null, req);
       
  5153                 } catch (ex) {
       
  5154                     // An exception means the stylesheet is still loading.
       
  5155                 }
       
  5156             }
       
  5157         }
       
  5158 
       
  5159         if (pendingCSS.length) {
       
  5160             self._pollTimer = setTimeout(function () {
       
  5161                 self._poll.call(self);
       
  5162             }, self.options.pollInterval);
       
  5163         }
       
  5164     },
       
  5165 
       
  5166     _progress: function (err, req) {
       
  5167         var options = this.options;
       
  5168 
       
  5169         if (err) {
       
  5170             req.error = err;
       
  5171 
       
  5172             this.errors.push({
       
  5173                 error  : err,
       
  5174                 request: req
       
  5175             });
       
  5176 
       
  5177         }
       
  5178 
       
  5179         req.node._yuiget_finished = req.finished = true;
       
  5180 
       
  5181         if (options.onProgress) {
       
  5182             options.onProgress.call(options.context || this,
       
  5183                 this._getEventData(req));
       
  5184         }
       
  5185 
       
  5186         if (req.autopurge) {
       
  5187             // Pre-3.5.0 Get always excludes the most recent node from an
       
  5188             // autopurge. I find this odd, but I'm keeping that behavior for
       
  5189             // the sake of backcompat.
       
  5190             Get._autoPurge(this.options.purgethreshold);
       
  5191             Get._purgeNodes.push(req.node);
       
  5192         }
       
  5193 
       
  5194         if (this._pending === req) {
       
  5195             this._pending = null;
       
  5196         }
       
  5197 
       
  5198         this._reqsWaiting -= 1;
       
  5199 
       
  5200         this._next();
       
  5201     }
       
  5202 };
       
  5203 
       
  5204 
       
  5205 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5206 YUI.add('features', function (Y, NAME) {
       
  5207 
       
  5208 var feature_tests = {};
       
  5209 
       
  5210 /**
       
  5211 Contains the core of YUI's feature test architecture.
       
  5212 @module features
       
  5213 */
       
  5214 
       
  5215 /**
       
  5216 * Feature detection
       
  5217 * @class Features
       
  5218 * @static
       
  5219 */
       
  5220 
       
  5221 Y.mix(Y.namespace('Features'), {
       
  5222 
       
  5223     /**
       
  5224     * Object hash of all registered feature tests
       
  5225     * @property tests
       
  5226     * @type Object
       
  5227     */
       
  5228     tests: feature_tests,
       
  5229 
       
  5230     /**
       
  5231     * Add a test to the system
       
  5232     *
       
  5233     *   ```
       
  5234     *   Y.Features.add("load", "1", {});
       
  5235     *   ```
       
  5236     *
       
  5237     * @method add
       
  5238     * @param {String} cat The category, right now only 'load' is supported
       
  5239     * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
       
  5240     * @param {Object} o Object containing test properties
       
  5241     * @param {String} o.name The name of the test
       
  5242     * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
       
  5243     * @param {String} o.trigger The module that triggers this test.
       
  5244     */
       
  5245     add: function(cat, name, o) {
       
  5246         feature_tests[cat] = feature_tests[cat] || {};
       
  5247         feature_tests[cat][name] = o;
       
  5248     },
       
  5249     /**
       
  5250     * Execute all tests of a given category and return the serialized results
       
  5251     *
       
  5252     *   ```
       
  5253     *   caps=1:1;2:1;3:0
       
  5254     *   ```
       
  5255     * @method all
       
  5256     * @param {String} cat The category to execute
       
  5257     * @param {Array} args The arguments to pass to the test function
       
  5258     * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
       
  5259     */
       
  5260     all: function(cat, args) {
       
  5261         var cat_o = feature_tests[cat],
       
  5262             // results = {};
       
  5263             result = [];
       
  5264         if (cat_o) {
       
  5265             Y.Object.each(cat_o, function(v, k) {
       
  5266                 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
       
  5267             });
       
  5268         }
       
  5269 
       
  5270         return (result.length) ? result.join(';') : '';
       
  5271     },
       
  5272     /**
       
  5273     * Run a sepecific test and return a Boolean response.
       
  5274     *
       
  5275     *   ```
       
  5276     *   Y.Features.test("load", "1");
       
  5277     *   ```
       
  5278     *
       
  5279     * @method test
       
  5280     * @param {String} cat The category of the test to run
       
  5281     * @param {String} name The name of the test to run
       
  5282     * @param {Array} args The arguments to pass to the test function
       
  5283     * @return {Boolean} True or false if the test passed/failed.
       
  5284     */
       
  5285     test: function(cat, name, args) {
       
  5286         args = args || [];
       
  5287         var result, ua, test,
       
  5288             cat_o = feature_tests[cat],
       
  5289             feature = cat_o && cat_o[name];
       
  5290 
       
  5291         if (!feature) {
       
  5292         } else {
       
  5293 
       
  5294             result = feature.result;
       
  5295 
       
  5296             if (Y.Lang.isUndefined(result)) {
       
  5297 
       
  5298                 ua = feature.ua;
       
  5299                 if (ua) {
       
  5300                     result = (Y.UA[ua]);
       
  5301                 }
       
  5302 
       
  5303                 test = feature.test;
       
  5304                 if (test && ((!ua) || result)) {
       
  5305                     result = test.apply(Y, args);
       
  5306                 }
       
  5307 
       
  5308                 feature.result = result;
       
  5309             }
       
  5310         }
       
  5311 
       
  5312         return result;
       
  5313     }
       
  5314 });
       
  5315 
       
  5316 // Y.Features.add("load", "1", {});
       
  5317 // Y.Features.test("load", "1");
       
  5318 // caps=1:1;2:0;3:1;
       
  5319 
       
  5320 /* This file is auto-generated by (yogi loader --yes --mix --start ../) */
       
  5321 /*jshint maxlen:900, eqeqeq: false */
       
  5322 var add = Y.Features.add;
       
  5323 // app-transitions-native
       
  5324 add('load', '0', {
       
  5325     "name": "app-transitions-native",
       
  5326     "test": function (Y) {
       
  5327     var doc  = Y.config.doc,
       
  5328         node = doc ? doc.documentElement : null;
       
  5329 
       
  5330     if (node && node.style) {
       
  5331         return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  5332     }
       
  5333 
       
  5334     return false;
       
  5335 },
       
  5336     "trigger": "app-transitions"
       
  5337 });
       
  5338 // autocomplete-list-keys
       
  5339 add('load', '1', {
       
  5340     "name": "autocomplete-list-keys",
       
  5341     "test": function (Y) {
       
  5342     // Only add keyboard support to autocomplete-list if this doesn't appear to
       
  5343     // be an iOS or Android-based mobile device.
       
  5344     //
       
  5345     // There's currently no feasible way to actually detect whether a device has
       
  5346     // a hardware keyboard, so this sniff will have to do. It can easily be
       
  5347     // overridden by manually loading the autocomplete-list-keys module.
       
  5348     //
       
  5349     // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
       
  5350     // doesn't fire the keyboard events used by AutoCompleteList, so there's
       
  5351     // no point loading the -keys module even when a bluetooth keyboard may be
       
  5352     // available.
       
  5353     return !(Y.UA.ios || Y.UA.android);
       
  5354 },
       
  5355     "trigger": "autocomplete-list"
       
  5356 });
       
  5357 // dd-gestures
       
  5358 add('load', '2', {
       
  5359     "name": "dd-gestures",
       
  5360     "trigger": "dd-drag",
       
  5361     "ua": "touchEnabled"
       
  5362 });
       
  5363 // dom-style-ie
       
  5364 add('load', '3', {
       
  5365     "name": "dom-style-ie",
       
  5366     "test": function (Y) {
       
  5367 
       
  5368     var testFeature = Y.Features.test,
       
  5369         addFeature = Y.Features.add,
       
  5370         WINDOW = Y.config.win,
       
  5371         DOCUMENT = Y.config.doc,
       
  5372         DOCUMENT_ELEMENT = 'documentElement',
       
  5373         ret = false;
       
  5374 
       
  5375     addFeature('style', 'computedStyle', {
       
  5376         test: function() {
       
  5377             return WINDOW && 'getComputedStyle' in WINDOW;
       
  5378         }
       
  5379     });
       
  5380 
       
  5381     addFeature('style', 'opacity', {
       
  5382         test: function() {
       
  5383             return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
       
  5384         }
       
  5385     });
       
  5386 
       
  5387     ret =  (!testFeature('style', 'opacity') &&
       
  5388             !testFeature('style', 'computedStyle'));
       
  5389 
       
  5390     return ret;
       
  5391 },
       
  5392     "trigger": "dom-style"
       
  5393 });
       
  5394 // editor-para-ie
       
  5395 add('load', '4', {
       
  5396     "name": "editor-para-ie",
       
  5397     "trigger": "editor-para",
       
  5398     "ua": "ie",
       
  5399     "when": "instead"
       
  5400 });
       
  5401 // event-base-ie
       
  5402 add('load', '5', {
       
  5403     "name": "event-base-ie",
       
  5404     "test": function(Y) {
       
  5405     var imp = Y.config.doc && Y.config.doc.implementation;
       
  5406     return (imp && (!imp.hasFeature('Events', '2.0')));
       
  5407 },
       
  5408     "trigger": "node-base"
       
  5409 });
       
  5410 // graphics-canvas
       
  5411 add('load', '6', {
       
  5412     "name": "graphics-canvas",
       
  5413     "test": function(Y) {
       
  5414     var DOCUMENT = Y.config.doc,
       
  5415         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  5416 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5417         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5418     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  5419 },
       
  5420     "trigger": "graphics"
       
  5421 });
       
  5422 // graphics-canvas-default
       
  5423 add('load', '7', {
       
  5424     "name": "graphics-canvas-default",
       
  5425     "test": function(Y) {
       
  5426     var DOCUMENT = Y.config.doc,
       
  5427         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  5428 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5429         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5430     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  5431 },
       
  5432     "trigger": "graphics"
       
  5433 });
       
  5434 // graphics-svg
       
  5435 add('load', '8', {
       
  5436     "name": "graphics-svg",
       
  5437     "test": function(Y) {
       
  5438     var DOCUMENT = Y.config.doc,
       
  5439         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  5440 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5441         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5442     
       
  5443     return svg && (useSVG || !canvas);
       
  5444 },
       
  5445     "trigger": "graphics"
       
  5446 });
       
  5447 // graphics-svg-default
       
  5448 add('load', '9', {
       
  5449     "name": "graphics-svg-default",
       
  5450     "test": function(Y) {
       
  5451     var DOCUMENT = Y.config.doc,
       
  5452         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  5453 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5454         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5455     
       
  5456     return svg && (useSVG || !canvas);
       
  5457 },
       
  5458     "trigger": "graphics"
       
  5459 });
       
  5460 // graphics-vml
       
  5461 add('load', '10', {
       
  5462     "name": "graphics-vml",
       
  5463     "test": function(Y) {
       
  5464     var DOCUMENT = Y.config.doc,
       
  5465 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  5466     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  5467 },
       
  5468     "trigger": "graphics"
       
  5469 });
       
  5470 // graphics-vml-default
       
  5471 add('load', '11', {
       
  5472     "name": "graphics-vml-default",
       
  5473     "test": function(Y) {
       
  5474     var DOCUMENT = Y.config.doc,
       
  5475 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  5476     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  5477 },
       
  5478     "trigger": "graphics"
       
  5479 });
       
  5480 // history-hash-ie
       
  5481 add('load', '12', {
       
  5482     "name": "history-hash-ie",
       
  5483     "test": function (Y) {
       
  5484     var docMode = Y.config.doc && Y.config.doc.documentMode;
       
  5485 
       
  5486     return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
       
  5487             !docMode || docMode < 8);
       
  5488 },
       
  5489     "trigger": "history-hash"
       
  5490 });
       
  5491 // io-nodejs
       
  5492 add('load', '13', {
       
  5493     "name": "io-nodejs",
       
  5494     "trigger": "io-base",
       
  5495     "ua": "nodejs"
       
  5496 });
       
  5497 // json-parse-shim
       
  5498 add('load', '14', {
       
  5499     "name": "json-parse-shim",
       
  5500     "test": function (Y) {
       
  5501     var _JSON = Y.config.global.JSON,
       
  5502         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  5503         nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
       
  5504 
       
  5505     function workingNative( k, v ) {
       
  5506         return k === "ok" ? true : v;
       
  5507     }
       
  5508     
       
  5509     // Double check basic functionality.  This is mainly to catch early broken
       
  5510     // implementations of the JSON API in Firefox 3.1 beta1 and beta2
       
  5511     if ( nativeSupport ) {
       
  5512         try {
       
  5513             nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
       
  5514         }
       
  5515         catch ( e ) {
       
  5516             nativeSupport = false;
       
  5517         }
       
  5518     }
       
  5519 
       
  5520     return !nativeSupport;
       
  5521 },
       
  5522     "trigger": "json-parse"
       
  5523 });
       
  5524 // json-stringify-shim
       
  5525 add('load', '15', {
       
  5526     "name": "json-stringify-shim",
       
  5527     "test": function (Y) {
       
  5528     var _JSON = Y.config.global.JSON,
       
  5529         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  5530         nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
       
  5531 
       
  5532     // Double check basic native functionality.  This is primarily to catch broken
       
  5533     // early JSON API implementations in Firefox 3.1 beta1 and beta2.
       
  5534     if ( nativeSupport ) {
       
  5535         try {
       
  5536             nativeSupport = ( '0' === Native.stringify(0) );
       
  5537         } catch ( e ) {
       
  5538             nativeSupport = false;
       
  5539         }
       
  5540     }
       
  5541 
       
  5542 
       
  5543     return !nativeSupport;
       
  5544 },
       
  5545     "trigger": "json-stringify"
       
  5546 });
       
  5547 // scrollview-base-ie
       
  5548 add('load', '16', {
       
  5549     "name": "scrollview-base-ie",
       
  5550     "trigger": "scrollview-base",
       
  5551     "ua": "ie"
       
  5552 });
       
  5553 // selector-css2
       
  5554 add('load', '17', {
       
  5555     "name": "selector-css2",
       
  5556     "test": function (Y) {
       
  5557     var DOCUMENT = Y.config.doc,
       
  5558         ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
       
  5559 
       
  5560     return ret;
       
  5561 },
       
  5562     "trigger": "selector"
       
  5563 });
       
  5564 // transition-timer
       
  5565 add('load', '18', {
       
  5566     "name": "transition-timer",
       
  5567     "test": function (Y) {
       
  5568     var DOCUMENT = Y.config.doc,
       
  5569         node = (DOCUMENT) ? DOCUMENT.documentElement: null,
       
  5570         ret = true;
       
  5571 
       
  5572     if (node && node.style) {
       
  5573         ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  5574     }
       
  5575 
       
  5576     return ret;
       
  5577 },
       
  5578     "trigger": "transition"
       
  5579 });
       
  5580 // widget-base-ie
       
  5581 add('load', '19', {
       
  5582     "name": "widget-base-ie",
       
  5583     "trigger": "widget-base",
       
  5584     "ua": "ie"
       
  5585 });
       
  5586 // yql-jsonp
       
  5587 add('load', '20', {
       
  5588     "name": "yql-jsonp",
       
  5589     "test": function (Y) {
       
  5590     /* Only load the JSONP module when not in nodejs or winjs
       
  5591     TODO Make the winjs module a CORS module
       
  5592     */
       
  5593     return (!Y.UA.nodejs && !Y.UA.winjs);
       
  5594 },
       
  5595     "trigger": "yql",
       
  5596     "when": "after"
       
  5597 });
       
  5598 // yql-nodejs
       
  5599 add('load', '21', {
       
  5600     "name": "yql-nodejs",
       
  5601     "trigger": "yql",
       
  5602     "ua": "nodejs",
       
  5603     "when": "after"
       
  5604 });
       
  5605 // yql-winjs
       
  5606 add('load', '22', {
       
  5607     "name": "yql-winjs",
       
  5608     "trigger": "yql",
       
  5609     "ua": "winjs",
       
  5610     "when": "after"
       
  5611 });
       
  5612 
       
  5613 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5614 YUI.add('intl-base', function (Y, NAME) {
       
  5615 
       
  5616 /**
       
  5617  * The Intl utility provides a central location for managing sets of
       
  5618  * localized resources (strings and formatting patterns).
       
  5619  *
       
  5620  * @class Intl
       
  5621  * @uses EventTarget
       
  5622  * @static
       
  5623  */
       
  5624 
       
  5625 var SPLIT_REGEX = /[, ]/;
       
  5626 
       
  5627 Y.mix(Y.namespace('Intl'), {
       
  5628 
       
  5629  /**
       
  5630     * Returns the language among those available that
       
  5631     * best matches the preferred language list, using the Lookup
       
  5632     * algorithm of BCP 47.
       
  5633     * If none of the available languages meets the user's preferences,
       
  5634     * then "" is returned.
       
  5635     * Extended language ranges are not supported.
       
  5636     *
       
  5637     * @method lookupBestLang
       
  5638     * @param {String[] | String} preferredLanguages The list of preferred
       
  5639     * languages in descending preference order, represented as BCP 47
       
  5640     * language tags. A string array or a comma-separated list.
       
  5641     * @param {String[]} availableLanguages The list of languages
       
  5642     * that the application supports, represented as BCP 47 language
       
  5643     * tags.
       
  5644     *
       
  5645     * @return {String} The available language that best matches the
       
  5646     * preferred language list, or "".
       
  5647     * @since 3.1.0
       
  5648     */
       
  5649     lookupBestLang: function(preferredLanguages, availableLanguages) {
       
  5650 
       
  5651         var i, language, result, index;
       
  5652 
       
  5653         // check whether the list of available languages contains language;
       
  5654         // if so return it
       
  5655         function scan(language) {
       
  5656             var i;
       
  5657             for (i = 0; i < availableLanguages.length; i += 1) {
       
  5658                 if (language.toLowerCase() ===
       
  5659                             availableLanguages[i].toLowerCase()) {
       
  5660                     return availableLanguages[i];
       
  5661                 }
       
  5662             }
       
  5663         }
       
  5664 
       
  5665         if (Y.Lang.isString(preferredLanguages)) {
       
  5666             preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
       
  5667         }
       
  5668 
       
  5669         for (i = 0; i < preferredLanguages.length; i += 1) {
       
  5670             language = preferredLanguages[i];
       
  5671             if (!language || language === '*') {
       
  5672                 continue;
       
  5673             }
       
  5674             // check the fallback sequence for one language
       
  5675             while (language.length > 0) {
       
  5676                 result = scan(language);
       
  5677                 if (result) {
       
  5678                     return result;
       
  5679                 } else {
       
  5680                     index = language.lastIndexOf('-');
       
  5681                     if (index >= 0) {
       
  5682                         language = language.substring(0, index);
       
  5683                         // one-character subtags get cut along with the
       
  5684                         // following subtag
       
  5685                         if (index >= 2 && language.charAt(index - 2) === '-') {
       
  5686                             language = language.substring(0, index - 2);
       
  5687                         }
       
  5688                     } else {
       
  5689                         // nothing available for this language
       
  5690                         break;
       
  5691                     }
       
  5692                 }
       
  5693             }
       
  5694         }
       
  5695 
       
  5696         return '';
       
  5697     }
       
  5698 });
       
  5699 
       
  5700 
       
  5701 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5702 YUI.add('yui-log', function (Y, NAME) {
       
  5703 
       
  5704 /**
       
  5705  * Provides console log capability and exposes a custom event for
       
  5706  * console implementations. This module is a `core` YUI module,
       
  5707  * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
       
  5708  *
       
  5709  * @module yui
       
  5710  * @submodule yui-log
       
  5711  */
       
  5712 
       
  5713 var INSTANCE = Y,
       
  5714     LOGEVENT = 'yui:log',
       
  5715     UNDEFINED = 'undefined',
       
  5716     LEVELS = { debug: 1,
       
  5717                info: 2,
       
  5718                warn: 4,
       
  5719                error: 8 };
       
  5720 
       
  5721 /**
       
  5722  * If the 'debug' config is true, a 'yui:log' event will be
       
  5723  * dispatched, which the Console widget and anything else
       
  5724  * can consume.  If the 'useBrowserConsole' config is true, it will
       
  5725  * write to the browser console if available.  YUI-specific log
       
  5726  * messages will only be present in the -debug versions of the
       
  5727  * JS files.  The build system is supposed to remove log statements
       
  5728  * from the raw and minified versions of the files.
       
  5729  *
       
  5730  * @method log
       
  5731  * @for YUI
       
  5732  * @param  {String}  msg  The message to log.
       
  5733  * @param  {String}  cat  The log category for the message.  Default
       
  5734  *                        categories are "info", "warn", "error", "debug".
       
  5735  *                        Custom categories can be used as well. (opt).
       
  5736  * @param  {String}  src  The source of the the message (opt).
       
  5737  * @param  {boolean} silent If true, the log event won't fire.
       
  5738  * @return {YUI}      YUI instance.
       
  5739  */
       
  5740 INSTANCE.log = function(msg, cat, src, silent) {
       
  5741     var bail, excl, incl, m, f, minlevel,
       
  5742         Y = INSTANCE,
       
  5743         c = Y.config,
       
  5744         publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
       
  5745     // suppress log message if the config is off or the event stack
       
  5746     // or the event call stack contains a consumer of the yui:log event
       
  5747     if (c.debug) {
       
  5748         // apply source filters
       
  5749         src = src || "";
       
  5750         if (typeof src !== "undefined") {
       
  5751             excl = c.logExclude;
       
  5752             incl = c.logInclude;
       
  5753             if (incl && !(src in incl)) {
       
  5754                 bail = 1;
       
  5755             } else if (incl && (src in incl)) {
       
  5756                 bail = !incl[src];
       
  5757             } else if (excl && (src in excl)) {
       
  5758                 bail = excl[src];
       
  5759             }
       
  5760 
       
  5761             // Set a default category of info if the category was not defined or was not
       
  5762             // a real category.
       
  5763             if ((typeof cat === 'undefined') || !(cat in LEVELS)) {
       
  5764                 cat = 'info';
       
  5765             }
       
  5766 
       
  5767             // Determine the current minlevel as defined in configuration
       
  5768             Y.config.logLevel = Y.config.logLevel || 'debug';
       
  5769             minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
       
  5770 
       
  5771             if (cat in LEVELS && LEVELS[cat] < minlevel) {
       
  5772                 // Skip this message if the we don't meet the defined minlevel
       
  5773                 bail = 1;
       
  5774             }
       
  5775         }
       
  5776         if (!bail) {
       
  5777             if (c.useBrowserConsole) {
       
  5778                 m = (src) ? src + ': ' + msg : msg;
       
  5779                 if (Y.Lang.isFunction(c.logFn)) {
       
  5780                     c.logFn.call(Y, msg, cat, src);
       
  5781                 } else if (typeof console !== UNDEFINED && console.log) {
       
  5782                     f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
       
  5783                     console[f](m);
       
  5784                 } else if (typeof opera !== UNDEFINED) {
       
  5785                     opera.postError(m);
       
  5786                 }
       
  5787             }
       
  5788 
       
  5789             if (publisher && !silent) {
       
  5790 
       
  5791                 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
       
  5792                     publisher.publish(LOGEVENT, {
       
  5793                         broadcast: 2
       
  5794                     });
       
  5795                 }
       
  5796 
       
  5797                 publisher.fire(LOGEVENT, {
       
  5798                     msg: msg,
       
  5799                     cat: cat,
       
  5800                     src: src
       
  5801                 });
       
  5802             }
       
  5803         }
       
  5804     }
       
  5805 
       
  5806     return Y;
       
  5807 };
       
  5808 
       
  5809 /**
       
  5810  * Write a system message.  This message will be preserved in the
       
  5811  * minified and raw versions of the YUI files, unlike log statements.
       
  5812  * @method message
       
  5813  * @for YUI
       
  5814  * @param  {String}  msg  The message to log.
       
  5815  * @param  {String}  cat  The log category for the message.  Default
       
  5816  *                        categories are "info", "warn", "error", "debug".
       
  5817  *                        Custom categories can be used as well. (opt).
       
  5818  * @param  {String}  src  The source of the the message (opt).
       
  5819  * @param  {boolean} silent If true, the log event won't fire.
       
  5820  * @return {YUI}      YUI instance.
       
  5821  */
       
  5822 INSTANCE.message = function() {
       
  5823     return INSTANCE.log.apply(INSTANCE, arguments);
       
  5824 };
       
  5825 
       
  5826 
       
  5827 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5828 YUI.add('yui-later', function (Y, NAME) {
       
  5829 
       
  5830 /**
       
  5831  * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module,
       
  5832  * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
       
  5833  *
       
  5834  * @module yui
       
  5835  * @submodule yui-later
       
  5836  */
       
  5837 
       
  5838 var NO_ARGS = [];
       
  5839 
       
  5840 /**
       
  5841  * Executes the supplied function in the context of the supplied
       
  5842  * object 'when' milliseconds later.  Executes the function a
       
  5843  * single time unless periodic is set to true.
       
  5844  * @for YUI
       
  5845  * @method later
       
  5846  * @param when {Number} the number of milliseconds to wait until the fn
       
  5847  * is executed.
       
  5848  * @param o the context object.
       
  5849  * @param fn {Function|String} the function to execute or the name of
       
  5850  * the method in the 'o' object to execute.
       
  5851  * @param data [Array] data that is provided to the function.  This
       
  5852  * accepts either a single item or an array.  If an array is provided,
       
  5853  * the function is executed with one parameter for each array item.
       
  5854  * If you need to pass a single array parameter, it needs to be wrapped
       
  5855  * in an array [myarray].
       
  5856  *
       
  5857  * Note: native methods in IE may not have the call and apply methods.
       
  5858  * In this case, it will work, but you are limited to four arguments.
       
  5859  *
       
  5860  * @param periodic {boolean} if true, executes continuously at supplied
       
  5861  * interval until canceled.
       
  5862  * @return {object} a timer object. Call the cancel() method on this
       
  5863  * object to stop the timer.
       
  5864  */
       
  5865 Y.later = function(when, o, fn, data, periodic) {
       
  5866     when = when || 0;
       
  5867     data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
       
  5868     o = o || Y.config.win || Y;
       
  5869 
       
  5870     var cancelled = false,
       
  5871         method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
       
  5872         wrapper = function() {
       
  5873             // IE 8- may execute a setInterval callback one last time
       
  5874             // after clearInterval was called, so in order to preserve
       
  5875             // the cancel() === no more runny-run, we have to jump through
       
  5876             // an extra hoop.
       
  5877             if (!cancelled) {
       
  5878                 if (!method.apply) {
       
  5879                     method(data[0], data[1], data[2], data[3]);
       
  5880                 } else {
       
  5881                     method.apply(o, data || NO_ARGS);
       
  5882                 }
       
  5883             }
       
  5884         },
       
  5885         id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
       
  5886 
       
  5887     return {
       
  5888         id: id,
       
  5889         interval: periodic,
       
  5890         cancel: function() {
       
  5891             cancelled = true;
       
  5892             if (this.interval) {
       
  5893                 clearInterval(id);
       
  5894             } else {
       
  5895                 clearTimeout(id);
       
  5896             }
       
  5897         }
       
  5898     };
       
  5899 };
       
  5900 
       
  5901 Y.Lang.later = Y.later;
       
  5902 
       
  5903 
       
  5904 
       
  5905 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5906 YUI.add('yui', function (Y, NAME) {}, '@VERSION@', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});