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