src/cm/media/js/lib/yui/yui_3.10.3/build/simpleyui/simpleyui.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 = '@VERSION@',
       
   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 }, '@VERSION@', {"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 }, '@VERSION@', {"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 }, '@VERSION@', {"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 }, '@VERSION@', {"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 }, '@VERSION@', {"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 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5638 YUI.add('yui', function (Y, NAME) {}, '@VERSION@', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
       
  5639 YUI.add('oop', function (Y, NAME) {
       
  5640 
       
  5641 /**
       
  5642 Adds object inheritance and manipulation utilities to the YUI instance. This
       
  5643 module is required by most YUI components.
       
  5644 
       
  5645 @module oop
       
  5646 **/
       
  5647 
       
  5648 var L            = Y.Lang,
       
  5649     A            = Y.Array,
       
  5650     OP           = Object.prototype,
       
  5651     CLONE_MARKER = '_~yuim~_',
       
  5652 
       
  5653     hasOwn   = OP.hasOwnProperty,
       
  5654     toString = OP.toString;
       
  5655 
       
  5656 function dispatch(o, f, c, proto, action) {
       
  5657     if (o && o[action] && o !== Y) {
       
  5658         return o[action].call(o, f, c);
       
  5659     } else {
       
  5660         switch (A.test(o)) {
       
  5661             case 1:
       
  5662                 return A[action](o, f, c);
       
  5663             case 2:
       
  5664                 return A[action](Y.Array(o, 0, true), f, c);
       
  5665             default:
       
  5666                 return Y.Object[action](o, f, c, proto);
       
  5667         }
       
  5668     }
       
  5669 }
       
  5670 
       
  5671 /**
       
  5672 Augments the _receiver_ with prototype properties from the _supplier_. The
       
  5673 receiver may be a constructor function or an object. The supplier must be a
       
  5674 constructor function.
       
  5675 
       
  5676 If the _receiver_ is an object, then the _supplier_ constructor will be called
       
  5677 immediately after _receiver_ is augmented, with _receiver_ as the `this` object.
       
  5678 
       
  5679 If the _receiver_ is a constructor function, then all prototype methods of
       
  5680 _supplier_ that are copied to _receiver_ will be sequestered, and the
       
  5681 _supplier_ constructor will not be called immediately. The first time any
       
  5682 sequestered method is called on the _receiver_'s prototype, all sequestered
       
  5683 methods will be immediately copied to the _receiver_'s prototype, the
       
  5684 _supplier_'s constructor will be executed, and finally the newly unsequestered
       
  5685 method that was called will be executed.
       
  5686 
       
  5687 This sequestering logic sounds like a bunch of complicated voodoo, but it makes
       
  5688 it cheap to perform frequent augmentation by ensuring that suppliers'
       
  5689 constructors are only called if a supplied method is actually used. If none of
       
  5690 the supplied methods is ever used, then there's no need to take the performance
       
  5691 hit of calling the _supplier_'s constructor.
       
  5692 
       
  5693 @method augment
       
  5694 @param {Function|Object} receiver Object or function to be augmented.
       
  5695 @param {Function} supplier Function that supplies the prototype properties with
       
  5696   which to augment the _receiver_.
       
  5697 @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
       
  5698   will be overwritten if found on the supplier's prototype.
       
  5699 @param {String[]} [whitelist] An array of property names. If specified,
       
  5700   only the whitelisted prototype properties will be applied to the receiver, and
       
  5701   all others will be ignored.
       
  5702 @param {Array|any} [args] Argument or array of arguments to pass to the
       
  5703   supplier's constructor when initializing.
       
  5704 @return {Function} Augmented object.
       
  5705 @for YUI
       
  5706 **/
       
  5707 Y.augment = function (receiver, supplier, overwrite, whitelist, args) {
       
  5708     var rProto    = receiver.prototype,
       
  5709         sequester = rProto && supplier,
       
  5710         sProto    = supplier.prototype,
       
  5711         to        = rProto || receiver,
       
  5712 
       
  5713         copy,
       
  5714         newPrototype,
       
  5715         replacements,
       
  5716         sequestered,
       
  5717         unsequester;
       
  5718 
       
  5719     args = args ? Y.Array(args) : [];
       
  5720 
       
  5721     if (sequester) {
       
  5722         newPrototype = {};
       
  5723         replacements = {};
       
  5724         sequestered  = {};
       
  5725 
       
  5726         copy = function (value, key) {
       
  5727             if (overwrite || !(key in rProto)) {
       
  5728                 if (toString.call(value) === '[object Function]') {
       
  5729                     sequestered[key] = value;
       
  5730 
       
  5731                     newPrototype[key] = replacements[key] = function () {
       
  5732                         return unsequester(this, value, arguments);
       
  5733                     };
       
  5734                 } else {
       
  5735                     newPrototype[key] = value;
       
  5736                 }
       
  5737             }
       
  5738         };
       
  5739 
       
  5740         unsequester = function (instance, fn, fnArgs) {
       
  5741             // Unsequester all sequestered functions.
       
  5742             for (var key in sequestered) {
       
  5743                 if (hasOwn.call(sequestered, key)
       
  5744                         && instance[key] === replacements[key]) {
       
  5745 
       
  5746                     instance[key] = sequestered[key];
       
  5747                 }
       
  5748             }
       
  5749 
       
  5750             // Execute the supplier constructor.
       
  5751             supplier.apply(instance, args);
       
  5752 
       
  5753             // Finally, execute the original sequestered function.
       
  5754             return fn.apply(instance, fnArgs);
       
  5755         };
       
  5756 
       
  5757         if (whitelist) {
       
  5758             Y.Array.each(whitelist, function (name) {
       
  5759                 if (name in sProto) {
       
  5760                     copy(sProto[name], name);
       
  5761                 }
       
  5762             });
       
  5763         } else {
       
  5764             Y.Object.each(sProto, copy, null, true);
       
  5765         }
       
  5766     }
       
  5767 
       
  5768     Y.mix(to, newPrototype || sProto, overwrite, whitelist);
       
  5769 
       
  5770     if (!sequester) {
       
  5771         supplier.apply(to, args);
       
  5772     }
       
  5773 
       
  5774     return receiver;
       
  5775 };
       
  5776 
       
  5777 /**
       
  5778  * Copies object properties from the supplier to the receiver. If the target has
       
  5779  * the property, and the property is an object, the target object will be
       
  5780  * augmented with the supplier's value.
       
  5781  *
       
  5782  * @method aggregate
       
  5783  * @param {Object} receiver Object to receive the augmentation.
       
  5784  * @param {Object} supplier Object that supplies the properties with which to
       
  5785  *     augment the receiver.
       
  5786  * @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
       
  5787  *     will be overwritten if found on the supplier.
       
  5788  * @param {String[]} [whitelist] Whitelist. If supplied, only properties in this
       
  5789  *     list will be applied to the receiver.
       
  5790  * @return {Object} Augmented object.
       
  5791  */
       
  5792 Y.aggregate = function(r, s, ov, wl) {
       
  5793     return Y.mix(r, s, ov, wl, 0, true);
       
  5794 };
       
  5795 
       
  5796 /**
       
  5797  * Utility to set up the prototype, constructor and superclass properties to
       
  5798  * support an inheritance strategy that can chain constructors and methods.
       
  5799  * Static members will not be inherited.
       
  5800  *
       
  5801  * @method extend
       
  5802  * @param {function} r   the object to modify.
       
  5803  * @param {function} s the object to inherit.
       
  5804  * @param {object} px prototype properties to add/override.
       
  5805  * @param {object} sx static properties to add/override.
       
  5806  * @return {object} the extended object.
       
  5807  */
       
  5808 Y.extend = function(r, s, px, sx) {
       
  5809     if (!s || !r) {
       
  5810         Y.error('extend failed, verify dependencies');
       
  5811     }
       
  5812 
       
  5813     var sp = s.prototype, rp = Y.Object(sp);
       
  5814     r.prototype = rp;
       
  5815 
       
  5816     rp.constructor = r;
       
  5817     r.superclass = sp;
       
  5818 
       
  5819     // assign constructor property
       
  5820     if (s != Object && sp.constructor == OP.constructor) {
       
  5821         sp.constructor = s;
       
  5822     }
       
  5823 
       
  5824     // add prototype overrides
       
  5825     if (px) {
       
  5826         Y.mix(rp, px, true);
       
  5827     }
       
  5828 
       
  5829     // add object overrides
       
  5830     if (sx) {
       
  5831         Y.mix(r, sx, true);
       
  5832     }
       
  5833 
       
  5834     return r;
       
  5835 };
       
  5836 
       
  5837 /**
       
  5838  * Executes the supplied function for each item in
       
  5839  * a collection.  Supports arrays, objects, and
       
  5840  * NodeLists
       
  5841  * @method each
       
  5842  * @param {object} o the object to iterate.
       
  5843  * @param {function} f the function to execute.  This function
       
  5844  * receives the value, key, and object as parameters.
       
  5845  * @param {object} c the execution context for the function.
       
  5846  * @param {boolean} proto if true, prototype properties are
       
  5847  * iterated on objects.
       
  5848  * @return {YUI} the YUI instance.
       
  5849  */
       
  5850 Y.each = function(o, f, c, proto) {
       
  5851     return dispatch(o, f, c, proto, 'each');
       
  5852 };
       
  5853 
       
  5854 /**
       
  5855  * Executes the supplied function for each item in
       
  5856  * a collection.  The operation stops if the function
       
  5857  * returns true. Supports arrays, objects, and
       
  5858  * NodeLists.
       
  5859  * @method some
       
  5860  * @param {object} o the object to iterate.
       
  5861  * @param {function} f the function to execute.  This function
       
  5862  * receives the value, key, and object as parameters.
       
  5863  * @param {object} c the execution context for the function.
       
  5864  * @param {boolean} proto if true, prototype properties are
       
  5865  * iterated on objects.
       
  5866  * @return {boolean} true if the function ever returns true,
       
  5867  * false otherwise.
       
  5868  */
       
  5869 Y.some = function(o, f, c, proto) {
       
  5870     return dispatch(o, f, c, proto, 'some');
       
  5871 };
       
  5872 
       
  5873 /**
       
  5874 Deep object/array copy. Function clones are actually wrappers around the
       
  5875 original function. Array-like objects are treated as arrays. Primitives are
       
  5876 returned untouched. Optionally, a function can be provided to handle other data
       
  5877 types, filter keys, validate values, etc.
       
  5878 
       
  5879 **Note:** Cloning a non-trivial object is a reasonably heavy operation, due to
       
  5880 the need to recursively iterate down non-primitive properties. Clone should be
       
  5881 used only when a deep clone down to leaf level properties is explicitly
       
  5882 required. This method will also
       
  5883 
       
  5884 In many cases (for example, when trying to isolate objects used as hashes for
       
  5885 configuration properties), a shallow copy, using `Y.merge()` is normally
       
  5886 sufficient. If more than one level of isolation is required, `Y.merge()` can be
       
  5887 used selectively at each level which needs to be isolated from the original
       
  5888 without going all the way to leaf properties.
       
  5889 
       
  5890 @method clone
       
  5891 @param {object} o what to clone.
       
  5892 @param {boolean} safe if true, objects will not have prototype items from the
       
  5893     source. If false, they will. In this case, the original is initially
       
  5894     protected, but the clone is not completely immune from changes to the source
       
  5895     object prototype. Also, cloned prototype items that are deleted from the
       
  5896     clone will result in the value of the source prototype being exposed. If
       
  5897     operating on a non-safe clone, items should be nulled out rather than
       
  5898     deleted.
       
  5899 @param {function} f optional function to apply to each item in a collection; it
       
  5900     will be executed prior to applying the value to the new object.
       
  5901     Return false to prevent the copy.
       
  5902 @param {object} c optional execution context for f.
       
  5903 @param {object} owner Owner object passed when clone is iterating an object.
       
  5904     Used to set up context for cloned functions.
       
  5905 @param {object} cloned hash of previously cloned objects to avoid multiple
       
  5906     clones.
       
  5907 @return {Array|Object} the cloned object.
       
  5908 **/
       
  5909 Y.clone = function(o, safe, f, c, owner, cloned) {
       
  5910     var o2, marked, stamp;
       
  5911 
       
  5912     // Does not attempt to clone:
       
  5913     //
       
  5914     // * Non-typeof-object values, "primitive" values don't need cloning.
       
  5915     //
       
  5916     // * YUI instances, cloning complex object like YUI instances is not
       
  5917     //   advised, this is like cloning the world.
       
  5918     //
       
  5919     // * DOM nodes (#2528250), common host objects like DOM nodes cannot be
       
  5920     //   "subclassed" in Firefox and old versions of IE. Trying to use
       
  5921     //   `Object.create()` or `Y.extend()` on a DOM node will throw an error in
       
  5922     //   these browsers.
       
  5923     //
       
  5924     // Instad, the passed-in `o` will be return as-is when it matches one of the
       
  5925     // above criteria.
       
  5926     if (!L.isObject(o) ||
       
  5927             Y.instanceOf(o, YUI) ||
       
  5928             (o.addEventListener || o.attachEvent)) {
       
  5929 
       
  5930         return o;
       
  5931     }
       
  5932 
       
  5933     marked = cloned || {};
       
  5934 
       
  5935     switch (L.type(o)) {
       
  5936         case 'date':
       
  5937             return new Date(o);
       
  5938         case 'regexp':
       
  5939             // if we do this we need to set the flags too
       
  5940             // return new RegExp(o.source);
       
  5941             return o;
       
  5942         case 'function':
       
  5943             // o2 = Y.bind(o, owner);
       
  5944             // break;
       
  5945             return o;
       
  5946         case 'array':
       
  5947             o2 = [];
       
  5948             break;
       
  5949         default:
       
  5950 
       
  5951             // #2528250 only one clone of a given object should be created.
       
  5952             if (o[CLONE_MARKER]) {
       
  5953                 return marked[o[CLONE_MARKER]];
       
  5954             }
       
  5955 
       
  5956             stamp = Y.guid();
       
  5957 
       
  5958             o2 = (safe) ? {} : Y.Object(o);
       
  5959 
       
  5960             o[CLONE_MARKER] = stamp;
       
  5961             marked[stamp] = o;
       
  5962     }
       
  5963 
       
  5964     Y.each(o, function(v, k) {
       
  5965         if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
       
  5966             if (k !== CLONE_MARKER) {
       
  5967                 if (k == 'prototype') {
       
  5968                     // skip the prototype
       
  5969                 // } else if (o[k] === o) {
       
  5970                 //     this[k] = this;
       
  5971                 } else {
       
  5972                     this[k] =
       
  5973                         Y.clone(v, safe, f, c, owner || o, marked);
       
  5974                 }
       
  5975             }
       
  5976         }
       
  5977     }, o2);
       
  5978 
       
  5979     if (!cloned) {
       
  5980         Y.Object.each(marked, function(v, k) {
       
  5981             if (v[CLONE_MARKER]) {
       
  5982                 try {
       
  5983                     delete v[CLONE_MARKER];
       
  5984                 } catch (e) {
       
  5985                     v[CLONE_MARKER] = null;
       
  5986                 }
       
  5987             }
       
  5988         }, this);
       
  5989         marked = null;
       
  5990     }
       
  5991 
       
  5992     return o2;
       
  5993 };
       
  5994 
       
  5995 /**
       
  5996  * Returns a function that will execute the supplied function in the
       
  5997  * supplied object's context, optionally adding any additional
       
  5998  * supplied parameters to the beginning of the arguments collection the
       
  5999  * supplied to the function.
       
  6000  *
       
  6001  * @method bind
       
  6002  * @param {Function|String} f the function to bind, or a function name
       
  6003  * to execute on the context object.
       
  6004  * @param {object} c the execution context.
       
  6005  * @param {any} args* 0..n arguments to include before the arguments the
       
  6006  * function is executed with.
       
  6007  * @return {function} the wrapped function.
       
  6008  */
       
  6009 Y.bind = function(f, c) {
       
  6010     var xargs = arguments.length > 2 ?
       
  6011             Y.Array(arguments, 2, true) : null;
       
  6012     return function() {
       
  6013         var fn = L.isString(f) ? c[f] : f,
       
  6014             args = (xargs) ?
       
  6015                 xargs.concat(Y.Array(arguments, 0, true)) : arguments;
       
  6016         return fn.apply(c || fn, args);
       
  6017     };
       
  6018 };
       
  6019 
       
  6020 /**
       
  6021  * Returns a function that will execute the supplied function in the
       
  6022  * supplied object's context, optionally adding any additional
       
  6023  * supplied parameters to the end of the arguments the function
       
  6024  * is executed with.
       
  6025  *
       
  6026  * @method rbind
       
  6027  * @param {Function|String} f the function to bind, or a function name
       
  6028  * to execute on the context object.
       
  6029  * @param {object} c the execution context.
       
  6030  * @param {any} args* 0..n arguments to append to the end of
       
  6031  * arguments collection supplied to the function.
       
  6032  * @return {function} the wrapped function.
       
  6033  */
       
  6034 Y.rbind = function(f, c) {
       
  6035     var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
  6036     return function() {
       
  6037         var fn = L.isString(f) ? c[f] : f,
       
  6038             args = (xargs) ?
       
  6039                 Y.Array(arguments, 0, true).concat(xargs) : arguments;
       
  6040         return fn.apply(c || fn, args);
       
  6041     };
       
  6042 };
       
  6043 
       
  6044 
       
  6045 }, '@VERSION@', {"requires": ["yui-base"]});
       
  6046 YUI.add('features', function (Y, NAME) {
       
  6047 
       
  6048 var feature_tests = {};
       
  6049 
       
  6050 /**
       
  6051 Contains the core of YUI's feature test architecture.
       
  6052 @module features
       
  6053 */
       
  6054 
       
  6055 /**
       
  6056 * Feature detection
       
  6057 * @class Features
       
  6058 * @static
       
  6059 */
       
  6060 
       
  6061 Y.mix(Y.namespace('Features'), {
       
  6062 
       
  6063     /**
       
  6064     * Object hash of all registered feature tests
       
  6065     * @property tests
       
  6066     * @type Object
       
  6067     */
       
  6068     tests: feature_tests,
       
  6069 
       
  6070     /**
       
  6071     * Add a test to the system
       
  6072     *
       
  6073     *   ```
       
  6074     *   Y.Features.add("load", "1", {});
       
  6075     *   ```
       
  6076     *
       
  6077     * @method add
       
  6078     * @param {String} cat The category, right now only 'load' is supported
       
  6079     * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
       
  6080     * @param {Object} o Object containing test properties
       
  6081     * @param {String} o.name The name of the test
       
  6082     * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
       
  6083     * @param {String} o.trigger The module that triggers this test.
       
  6084     */
       
  6085     add: function(cat, name, o) {
       
  6086         feature_tests[cat] = feature_tests[cat] || {};
       
  6087         feature_tests[cat][name] = o;
       
  6088     },
       
  6089     /**
       
  6090     * Execute all tests of a given category and return the serialized results
       
  6091     *
       
  6092     *   ```
       
  6093     *   caps=1:1;2:1;3:0
       
  6094     *   ```
       
  6095     * @method all
       
  6096     * @param {String} cat The category to execute
       
  6097     * @param {Array} args The arguments to pass to the test function
       
  6098     * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
       
  6099     */
       
  6100     all: function(cat, args) {
       
  6101         var cat_o = feature_tests[cat],
       
  6102             // results = {};
       
  6103             result = [];
       
  6104         if (cat_o) {
       
  6105             Y.Object.each(cat_o, function(v, k) {
       
  6106                 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
       
  6107             });
       
  6108         }
       
  6109 
       
  6110         return (result.length) ? result.join(';') : '';
       
  6111     },
       
  6112     /**
       
  6113     * Run a sepecific test and return a Boolean response.
       
  6114     *
       
  6115     *   ```
       
  6116     *   Y.Features.test("load", "1");
       
  6117     *   ```
       
  6118     *
       
  6119     * @method test
       
  6120     * @param {String} cat The category of the test to run
       
  6121     * @param {String} name The name of the test to run
       
  6122     * @param {Array} args The arguments to pass to the test function
       
  6123     * @return {Boolean} True or false if the test passed/failed.
       
  6124     */
       
  6125     test: function(cat, name, args) {
       
  6126         args = args || [];
       
  6127         var result, ua, test,
       
  6128             cat_o = feature_tests[cat],
       
  6129             feature = cat_o && cat_o[name];
       
  6130 
       
  6131         if (!feature) {
       
  6132         } else {
       
  6133 
       
  6134             result = feature.result;
       
  6135 
       
  6136             if (Y.Lang.isUndefined(result)) {
       
  6137 
       
  6138                 ua = feature.ua;
       
  6139                 if (ua) {
       
  6140                     result = (Y.UA[ua]);
       
  6141                 }
       
  6142 
       
  6143                 test = feature.test;
       
  6144                 if (test && ((!ua) || result)) {
       
  6145                     result = test.apply(Y, args);
       
  6146                 }
       
  6147 
       
  6148                 feature.result = result;
       
  6149             }
       
  6150         }
       
  6151 
       
  6152         return result;
       
  6153     }
       
  6154 });
       
  6155 
       
  6156 // Y.Features.add("load", "1", {});
       
  6157 // Y.Features.test("load", "1");
       
  6158 // caps=1:1;2:0;3:1;
       
  6159 
       
  6160 /* This file is auto-generated by (yogi loader --yes --mix --start ../) */
       
  6161 /*jshint maxlen:900, eqeqeq: false */
       
  6162 var add = Y.Features.add;
       
  6163 // app-transitions-native
       
  6164 add('load', '0', {
       
  6165     "name": "app-transitions-native",
       
  6166     "test": function (Y) {
       
  6167     var doc  = Y.config.doc,
       
  6168         node = doc ? doc.documentElement : null;
       
  6169 
       
  6170     if (node && node.style) {
       
  6171         return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  6172     }
       
  6173 
       
  6174     return false;
       
  6175 },
       
  6176     "trigger": "app-transitions"
       
  6177 });
       
  6178 // autocomplete-list-keys
       
  6179 add('load', '1', {
       
  6180     "name": "autocomplete-list-keys",
       
  6181     "test": function (Y) {
       
  6182     // Only add keyboard support to autocomplete-list if this doesn't appear to
       
  6183     // be an iOS or Android-based mobile device.
       
  6184     //
       
  6185     // There's currently no feasible way to actually detect whether a device has
       
  6186     // a hardware keyboard, so this sniff will have to do. It can easily be
       
  6187     // overridden by manually loading the autocomplete-list-keys module.
       
  6188     //
       
  6189     // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
       
  6190     // doesn't fire the keyboard events used by AutoCompleteList, so there's
       
  6191     // no point loading the -keys module even when a bluetooth keyboard may be
       
  6192     // available.
       
  6193     return !(Y.UA.ios || Y.UA.android);
       
  6194 },
       
  6195     "trigger": "autocomplete-list"
       
  6196 });
       
  6197 // dd-gestures
       
  6198 add('load', '2', {
       
  6199     "name": "dd-gestures",
       
  6200     "trigger": "dd-drag",
       
  6201     "ua": "touchEnabled"
       
  6202 });
       
  6203 // dom-style-ie
       
  6204 add('load', '3', {
       
  6205     "name": "dom-style-ie",
       
  6206     "test": function (Y) {
       
  6207 
       
  6208     var testFeature = Y.Features.test,
       
  6209         addFeature = Y.Features.add,
       
  6210         WINDOW = Y.config.win,
       
  6211         DOCUMENT = Y.config.doc,
       
  6212         DOCUMENT_ELEMENT = 'documentElement',
       
  6213         ret = false;
       
  6214 
       
  6215     addFeature('style', 'computedStyle', {
       
  6216         test: function() {
       
  6217             return WINDOW && 'getComputedStyle' in WINDOW;
       
  6218         }
       
  6219     });
       
  6220 
       
  6221     addFeature('style', 'opacity', {
       
  6222         test: function() {
       
  6223             return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
       
  6224         }
       
  6225     });
       
  6226 
       
  6227     ret =  (!testFeature('style', 'opacity') &&
       
  6228             !testFeature('style', 'computedStyle'));
       
  6229 
       
  6230     return ret;
       
  6231 },
       
  6232     "trigger": "dom-style"
       
  6233 });
       
  6234 // editor-para-ie
       
  6235 add('load', '4', {
       
  6236     "name": "editor-para-ie",
       
  6237     "trigger": "editor-para",
       
  6238     "ua": "ie",
       
  6239     "when": "instead"
       
  6240 });
       
  6241 // event-base-ie
       
  6242 add('load', '5', {
       
  6243     "name": "event-base-ie",
       
  6244     "test": function(Y) {
       
  6245     var imp = Y.config.doc && Y.config.doc.implementation;
       
  6246     return (imp && (!imp.hasFeature('Events', '2.0')));
       
  6247 },
       
  6248     "trigger": "node-base"
       
  6249 });
       
  6250 // graphics-canvas
       
  6251 add('load', '6', {
       
  6252     "name": "graphics-canvas",
       
  6253     "test": function(Y) {
       
  6254     var DOCUMENT = Y.config.doc,
       
  6255         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  6256 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6257         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6258     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  6259 },
       
  6260     "trigger": "graphics"
       
  6261 });
       
  6262 // graphics-canvas-default
       
  6263 add('load', '7', {
       
  6264     "name": "graphics-canvas-default",
       
  6265     "test": function(Y) {
       
  6266     var DOCUMENT = Y.config.doc,
       
  6267         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  6268 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6269         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6270     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  6271 },
       
  6272     "trigger": "graphics"
       
  6273 });
       
  6274 // graphics-svg
       
  6275 add('load', '8', {
       
  6276     "name": "graphics-svg",
       
  6277     "test": function(Y) {
       
  6278     var DOCUMENT = Y.config.doc,
       
  6279         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  6280 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6281         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6282     
       
  6283     return svg && (useSVG || !canvas);
       
  6284 },
       
  6285     "trigger": "graphics"
       
  6286 });
       
  6287 // graphics-svg-default
       
  6288 add('load', '9', {
       
  6289     "name": "graphics-svg-default",
       
  6290     "test": function(Y) {
       
  6291     var DOCUMENT = Y.config.doc,
       
  6292         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  6293 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6294         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6295     
       
  6296     return svg && (useSVG || !canvas);
       
  6297 },
       
  6298     "trigger": "graphics"
       
  6299 });
       
  6300 // graphics-vml
       
  6301 add('load', '10', {
       
  6302     "name": "graphics-vml",
       
  6303     "test": function(Y) {
       
  6304     var DOCUMENT = Y.config.doc,
       
  6305 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  6306     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  6307 },
       
  6308     "trigger": "graphics"
       
  6309 });
       
  6310 // graphics-vml-default
       
  6311 add('load', '11', {
       
  6312     "name": "graphics-vml-default",
       
  6313     "test": function(Y) {
       
  6314     var DOCUMENT = Y.config.doc,
       
  6315 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  6316     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  6317 },
       
  6318     "trigger": "graphics"
       
  6319 });
       
  6320 // history-hash-ie
       
  6321 add('load', '12', {
       
  6322     "name": "history-hash-ie",
       
  6323     "test": function (Y) {
       
  6324     var docMode = Y.config.doc && Y.config.doc.documentMode;
       
  6325 
       
  6326     return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
       
  6327             !docMode || docMode < 8);
       
  6328 },
       
  6329     "trigger": "history-hash"
       
  6330 });
       
  6331 // io-nodejs
       
  6332 add('load', '13', {
       
  6333     "name": "io-nodejs",
       
  6334     "trigger": "io-base",
       
  6335     "ua": "nodejs"
       
  6336 });
       
  6337 // json-parse-shim
       
  6338 add('load', '14', {
       
  6339     "name": "json-parse-shim",
       
  6340     "test": function (Y) {
       
  6341     var _JSON = Y.config.global.JSON,
       
  6342         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  6343         nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
       
  6344 
       
  6345     function workingNative( k, v ) {
       
  6346         return k === "ok" ? true : v;
       
  6347     }
       
  6348     
       
  6349     // Double check basic functionality.  This is mainly to catch early broken
       
  6350     // implementations of the JSON API in Firefox 3.1 beta1 and beta2
       
  6351     if ( nativeSupport ) {
       
  6352         try {
       
  6353             nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
       
  6354         }
       
  6355         catch ( e ) {
       
  6356             nativeSupport = false;
       
  6357         }
       
  6358     }
       
  6359 
       
  6360     return !nativeSupport;
       
  6361 },
       
  6362     "trigger": "json-parse"
       
  6363 });
       
  6364 // json-stringify-shim
       
  6365 add('load', '15', {
       
  6366     "name": "json-stringify-shim",
       
  6367     "test": function (Y) {
       
  6368     var _JSON = Y.config.global.JSON,
       
  6369         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  6370         nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
       
  6371 
       
  6372     // Double check basic native functionality.  This is primarily to catch broken
       
  6373     // early JSON API implementations in Firefox 3.1 beta1 and beta2.
       
  6374     if ( nativeSupport ) {
       
  6375         try {
       
  6376             nativeSupport = ( '0' === Native.stringify(0) );
       
  6377         } catch ( e ) {
       
  6378             nativeSupport = false;
       
  6379         }
       
  6380     }
       
  6381 
       
  6382 
       
  6383     return !nativeSupport;
       
  6384 },
       
  6385     "trigger": "json-stringify"
       
  6386 });
       
  6387 // scrollview-base-ie
       
  6388 add('load', '16', {
       
  6389     "name": "scrollview-base-ie",
       
  6390     "trigger": "scrollview-base",
       
  6391     "ua": "ie"
       
  6392 });
       
  6393 // selector-css2
       
  6394 add('load', '17', {
       
  6395     "name": "selector-css2",
       
  6396     "test": function (Y) {
       
  6397     var DOCUMENT = Y.config.doc,
       
  6398         ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
       
  6399 
       
  6400     return ret;
       
  6401 },
       
  6402     "trigger": "selector"
       
  6403 });
       
  6404 // transition-timer
       
  6405 add('load', '18', {
       
  6406     "name": "transition-timer",
       
  6407     "test": function (Y) {
       
  6408     var DOCUMENT = Y.config.doc,
       
  6409         node = (DOCUMENT) ? DOCUMENT.documentElement: null,
       
  6410         ret = true;
       
  6411 
       
  6412     if (node && node.style) {
       
  6413         ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  6414     }
       
  6415 
       
  6416     return ret;
       
  6417 },
       
  6418     "trigger": "transition"
       
  6419 });
       
  6420 // widget-base-ie
       
  6421 add('load', '19', {
       
  6422     "name": "widget-base-ie",
       
  6423     "trigger": "widget-base",
       
  6424     "ua": "ie"
       
  6425 });
       
  6426 // yql-jsonp
       
  6427 add('load', '20', {
       
  6428     "name": "yql-jsonp",
       
  6429     "test": function (Y) {
       
  6430     /* Only load the JSONP module when not in nodejs or winjs
       
  6431     TODO Make the winjs module a CORS module
       
  6432     */
       
  6433     return (!Y.UA.nodejs && !Y.UA.winjs);
       
  6434 },
       
  6435     "trigger": "yql",
       
  6436     "when": "after"
       
  6437 });
       
  6438 // yql-nodejs
       
  6439 add('load', '21', {
       
  6440     "name": "yql-nodejs",
       
  6441     "trigger": "yql",
       
  6442     "ua": "nodejs",
       
  6443     "when": "after"
       
  6444 });
       
  6445 // yql-winjs
       
  6446 add('load', '22', {
       
  6447     "name": "yql-winjs",
       
  6448     "trigger": "yql",
       
  6449     "ua": "winjs",
       
  6450     "when": "after"
       
  6451 });
       
  6452 
       
  6453 }, '@VERSION@', {"requires": ["yui-base"]});
       
  6454 YUI.add('dom-core', function (Y, NAME) {
       
  6455 
       
  6456 var NODE_TYPE = 'nodeType',
       
  6457     OWNER_DOCUMENT = 'ownerDocument',
       
  6458     DOCUMENT_ELEMENT = 'documentElement',
       
  6459     DEFAULT_VIEW = 'defaultView',
       
  6460     PARENT_WINDOW = 'parentWindow',
       
  6461     TAG_NAME = 'tagName',
       
  6462     PARENT_NODE = 'parentNode',
       
  6463     PREVIOUS_SIBLING = 'previousSibling',
       
  6464     NEXT_SIBLING = 'nextSibling',
       
  6465     CONTAINS = 'contains',
       
  6466     COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
       
  6467     EMPTY_ARRAY = [],
       
  6468     
       
  6469     // IE < 8 throws on node.contains(textNode)
       
  6470     supportsContainsTextNode = (function() {
       
  6471         var node = Y.config.doc.createElement('div'),
       
  6472             textNode = node.appendChild(Y.config.doc.createTextNode('')),
       
  6473             result = false;
       
  6474         
       
  6475         try {
       
  6476             result = node.contains(textNode);
       
  6477         } catch(e) {}
       
  6478 
       
  6479         return result;
       
  6480     })(),
       
  6481 
       
  6482 /** 
       
  6483  * The DOM utility provides a cross-browser abtraction layer
       
  6484  * normalizing DOM tasks, and adds extra helper functionality
       
  6485  * for other common tasks. 
       
  6486  * @module dom
       
  6487  * @main dom
       
  6488  * @submodule dom-base
       
  6489  * @for DOM
       
  6490  *
       
  6491  */
       
  6492 
       
  6493 /**
       
  6494  * Provides DOM helper methods.
       
  6495  * @class DOM
       
  6496  *
       
  6497  */
       
  6498     
       
  6499 Y_DOM = {
       
  6500     /**
       
  6501      * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
       
  6502      * @method byId         
       
  6503      * @param {String} id the id attribute 
       
  6504      * @param {Object} doc optional The document to search. Defaults to current document 
       
  6505      * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. 
       
  6506      */
       
  6507     byId: function(id, doc) {
       
  6508         // handle dupe IDs and IE name collision
       
  6509         return Y_DOM.allById(id, doc)[0] || null;
       
  6510     },
       
  6511 
       
  6512     getId: function(node) {
       
  6513         var id;
       
  6514         // HTMLElement returned from FORM when INPUT name === "id"
       
  6515         // IE < 8: HTMLCollection returned when INPUT id === "id"
       
  6516         // via both getAttribute and form.id 
       
  6517         if (node.id && !node.id.tagName && !node.id.item) {
       
  6518             id = node.id;
       
  6519         } else if (node.attributes && node.attributes.id) {
       
  6520             id = node.attributes.id.value;
       
  6521         }
       
  6522 
       
  6523         return id;
       
  6524     },
       
  6525 
       
  6526     setId: function(node, id) {
       
  6527         if (node.setAttribute) {
       
  6528             node.setAttribute('id', id);
       
  6529         } else {
       
  6530             node.id = id;
       
  6531         }
       
  6532     },
       
  6533 
       
  6534     /*
       
  6535      * Finds the ancestor of the element.
       
  6536      * @method ancestor
       
  6537      * @param {HTMLElement} element The html element.
       
  6538      * @param {Function} fn optional An optional boolean test to apply.
       
  6539      * The optional function is passed the current DOM node being tested as its only argument.
       
  6540      * If no function is given, the parentNode is returned.
       
  6541      * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
       
  6542      * @return {HTMLElement | null} The matching DOM node or null if none found. 
       
  6543      */
       
  6544     ancestor: function(element, fn, testSelf, stopFn) {
       
  6545         var ret = null;
       
  6546         if (testSelf) {
       
  6547             ret = (!fn || fn(element)) ? element : null;
       
  6548 
       
  6549         }
       
  6550         return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null, stopFn);
       
  6551     },
       
  6552 
       
  6553     /*
       
  6554      * Finds the ancestors of the element.
       
  6555      * @method ancestors
       
  6556      * @param {HTMLElement} element The html element.
       
  6557      * @param {Function} fn optional An optional boolean test to apply.
       
  6558      * The optional function is passed the current DOM node being tested as its only argument.
       
  6559      * If no function is given, all ancestors are returned.
       
  6560      * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
       
  6561      * @return {Array} An array containing all matching DOM nodes.
       
  6562      */
       
  6563     ancestors: function(element, fn, testSelf, stopFn) {
       
  6564         var ancestor = element,
       
  6565             ret = [];
       
  6566 
       
  6567         while ((ancestor = Y_DOM.ancestor(ancestor, fn, testSelf, stopFn))) {
       
  6568             testSelf = false;
       
  6569             if (ancestor) {
       
  6570                 ret.unshift(ancestor);
       
  6571 
       
  6572                 if (stopFn && stopFn(ancestor)) {
       
  6573                     return ret;
       
  6574                 }
       
  6575             }
       
  6576         }
       
  6577 
       
  6578         return ret;
       
  6579     },
       
  6580 
       
  6581     /**
       
  6582      * Searches the element by the given axis for the first matching element.
       
  6583      * @method elementByAxis
       
  6584      * @param {HTMLElement} element The html element.
       
  6585      * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
       
  6586      * @param {Function} fn optional An optional boolean test to apply.
       
  6587      * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
       
  6588      * The optional function is passed the current HTMLElement being tested as its only argument.
       
  6589      * If no function is given, the first element is returned.
       
  6590      * @return {HTMLElement | null} The matching element or null if none found.
       
  6591      */
       
  6592     elementByAxis: function(element, axis, fn, all, stopAt) {
       
  6593         while (element && (element = element[axis])) { // NOTE: assignment
       
  6594                 if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
       
  6595                     return element;
       
  6596                 }
       
  6597 
       
  6598                 if (stopAt && stopAt(element)) {
       
  6599                     return null;
       
  6600                 }
       
  6601         }
       
  6602         return null;
       
  6603     },
       
  6604 
       
  6605     /**
       
  6606      * Determines whether or not one HTMLElement is or contains another HTMLElement.
       
  6607      * @method contains
       
  6608      * @param {HTMLElement} element The containing html element.
       
  6609      * @param {HTMLElement} needle The html element that may be contained.
       
  6610      * @return {Boolean} Whether or not the element is or contains the needle.
       
  6611      */
       
  6612     contains: function(element, needle) {
       
  6613         var ret = false;
       
  6614 
       
  6615         if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
       
  6616             ret = false;
       
  6617         } else if (element[CONTAINS] &&
       
  6618                 // IE < 8 throws on node.contains(textNode) so fall back to brute.
       
  6619                 // Falling back for other nodeTypes as well.
       
  6620                 (needle[NODE_TYPE] === 1 || supportsContainsTextNode)) {
       
  6621                 ret = element[CONTAINS](needle);
       
  6622         } else if (element[COMPARE_DOCUMENT_POSITION]) {
       
  6623             // Match contains behavior (node.contains(node) === true).
       
  6624             // Needed for Firefox < 4.
       
  6625             if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) { 
       
  6626                 ret = true;
       
  6627             }
       
  6628         } else {
       
  6629             ret = Y_DOM._bruteContains(element, needle);
       
  6630         }
       
  6631 
       
  6632         return ret;
       
  6633     },
       
  6634 
       
  6635     /**
       
  6636      * Determines whether or not the HTMLElement is part of the document.
       
  6637      * @method inDoc
       
  6638      * @param {HTMLElement} element The containing html element.
       
  6639      * @param {HTMLElement} doc optional The document to check.
       
  6640      * @return {Boolean} Whether or not the element is attached to the document. 
       
  6641      */
       
  6642     inDoc: function(element, doc) {
       
  6643         var ret = false,
       
  6644             rootNode;
       
  6645 
       
  6646         if (element && element.nodeType) {
       
  6647             (doc) || (doc = element[OWNER_DOCUMENT]);
       
  6648 
       
  6649             rootNode = doc[DOCUMENT_ELEMENT];
       
  6650 
       
  6651             // contains only works with HTML_ELEMENT
       
  6652             if (rootNode && rootNode.contains && element.tagName) {
       
  6653                 ret = rootNode.contains(element);
       
  6654             } else {
       
  6655                 ret = Y_DOM.contains(rootNode, element);
       
  6656             }
       
  6657         }
       
  6658 
       
  6659         return ret;
       
  6660 
       
  6661     },
       
  6662 
       
  6663    allById: function(id, root) {
       
  6664         root = root || Y.config.doc;
       
  6665         var nodes = [],
       
  6666             ret = [],
       
  6667             i,
       
  6668             node;
       
  6669 
       
  6670         if (root.querySelectorAll) {
       
  6671             ret = root.querySelectorAll('[id="' + id + '"]');
       
  6672         } else if (root.all) {
       
  6673             nodes = root.all(id);
       
  6674 
       
  6675             if (nodes) {
       
  6676                 // root.all may return HTMLElement or HTMLCollection.
       
  6677                 // some elements are also HTMLCollection (FORM, SELECT).
       
  6678                 if (nodes.nodeName) {
       
  6679                     if (nodes.id === id) { // avoid false positive on name
       
  6680                         ret.push(nodes);
       
  6681                         nodes = EMPTY_ARRAY; // done, no need to filter
       
  6682                     } else { //  prep for filtering
       
  6683                         nodes = [nodes];
       
  6684                     }
       
  6685                 }
       
  6686 
       
  6687                 if (nodes.length) {
       
  6688                     // filter out matches on node.name
       
  6689                     // and element.id as reference to element with id === 'id'
       
  6690                     for (i = 0; node = nodes[i++];) {
       
  6691                         if (node.id === id  || 
       
  6692                                 (node.attributes && node.attributes.id &&
       
  6693                                 node.attributes.id.value === id)) { 
       
  6694                             ret.push(node);
       
  6695                         }
       
  6696                     }
       
  6697                 }
       
  6698             }
       
  6699         } else {
       
  6700             ret = [Y_DOM._getDoc(root).getElementById(id)];
       
  6701         }
       
  6702     
       
  6703         return ret;
       
  6704    },
       
  6705 
       
  6706 
       
  6707     isWindow: function(obj) {
       
  6708         return !!(obj && obj.scrollTo && obj.document);
       
  6709     },
       
  6710 
       
  6711     _removeChildNodes: function(node) {
       
  6712         while (node.firstChild) {
       
  6713             node.removeChild(node.firstChild);
       
  6714         }
       
  6715     },
       
  6716 
       
  6717     siblings: function(node, fn) {
       
  6718         var nodes = [],
       
  6719             sibling = node;
       
  6720 
       
  6721         while ((sibling = sibling[PREVIOUS_SIBLING])) {
       
  6722             if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
       
  6723                 nodes.unshift(sibling);
       
  6724             }
       
  6725         }
       
  6726 
       
  6727         sibling = node;
       
  6728         while ((sibling = sibling[NEXT_SIBLING])) {
       
  6729             if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
       
  6730                 nodes.push(sibling);
       
  6731             }
       
  6732         }
       
  6733 
       
  6734         return nodes;
       
  6735     },
       
  6736 
       
  6737     /**
       
  6738      * Brute force version of contains.
       
  6739      * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
       
  6740      * @method _bruteContains
       
  6741      * @private
       
  6742      * @param {HTMLElement} element The containing html element.
       
  6743      * @param {HTMLElement} needle The html element that may be contained.
       
  6744      * @return {Boolean} Whether or not the element is or contains the needle.
       
  6745      */
       
  6746     _bruteContains: function(element, needle) {
       
  6747         while (needle) {
       
  6748             if (element === needle) {
       
  6749                 return true;
       
  6750             }
       
  6751             needle = needle.parentNode;
       
  6752         }
       
  6753         return false;
       
  6754     },
       
  6755 
       
  6756 // TODO: move to Lang?
       
  6757     /**
       
  6758      * Memoizes dynamic regular expressions to boost runtime performance. 
       
  6759      * @method _getRegExp
       
  6760      * @private
       
  6761      * @param {String} str The string to convert to a regular expression.
       
  6762      * @param {String} flags optional An optinal string of flags.
       
  6763      * @return {RegExp} An instance of RegExp
       
  6764      */
       
  6765     _getRegExp: function(str, flags) {
       
  6766         flags = flags || '';
       
  6767         Y_DOM._regexCache = Y_DOM._regexCache || {};
       
  6768         if (!Y_DOM._regexCache[str + flags]) {
       
  6769             Y_DOM._regexCache[str + flags] = new RegExp(str, flags);
       
  6770         }
       
  6771         return Y_DOM._regexCache[str + flags];
       
  6772     },
       
  6773 
       
  6774 // TODO: make getDoc/Win true privates?
       
  6775     /**
       
  6776      * returns the appropriate document.
       
  6777      * @method _getDoc
       
  6778      * @private
       
  6779      * @param {HTMLElement} element optional Target element.
       
  6780      * @return {Object} The document for the given element or the default document. 
       
  6781      */
       
  6782     _getDoc: function(element) {
       
  6783         var doc = Y.config.doc;
       
  6784         if (element) {
       
  6785             doc = (element[NODE_TYPE] === 9) ? element : // element === document
       
  6786                 element[OWNER_DOCUMENT] || // element === DOM node
       
  6787                 element.document || // element === window
       
  6788                 Y.config.doc; // default
       
  6789         }
       
  6790 
       
  6791         return doc;
       
  6792     },
       
  6793 
       
  6794     /**
       
  6795      * returns the appropriate window.
       
  6796      * @method _getWin
       
  6797      * @private
       
  6798      * @param {HTMLElement} element optional Target element.
       
  6799      * @return {Object} The window for the given element or the default window. 
       
  6800      */
       
  6801     _getWin: function(element) {
       
  6802         var doc = Y_DOM._getDoc(element);
       
  6803         return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
       
  6804     },
       
  6805 
       
  6806     _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
       
  6807         fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
       
  6808         var result,
       
  6809             i = 0,
       
  6810             node,
       
  6811             ret;
       
  6812 
       
  6813         if (fn && nodes) {
       
  6814             while ((node = nodes[i++])) {
       
  6815                 result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
       
  6816                 if (typeof result !== 'undefined') {
       
  6817                     (ret) || (ret = []);
       
  6818                     ret.push(result);
       
  6819                 }
       
  6820             }
       
  6821         }
       
  6822 
       
  6823         return (typeof ret !== 'undefined') ? ret : nodes;
       
  6824     },
       
  6825 
       
  6826     generateID: function(el) {
       
  6827         var id = el.id;
       
  6828 
       
  6829         if (!id) {
       
  6830             id = Y.stamp(el);
       
  6831             el.id = id; 
       
  6832         }   
       
  6833 
       
  6834         return id; 
       
  6835     }
       
  6836 };
       
  6837 
       
  6838 
       
  6839 Y.DOM = Y_DOM;
       
  6840 
       
  6841 
       
  6842 }, '@VERSION@', {"requires": ["oop", "features"]});
       
  6843 YUI.add('dom-base', function (Y, NAME) {
       
  6844 
       
  6845 /**
       
  6846 * @for DOM
       
  6847 * @module dom
       
  6848 */
       
  6849 var documentElement = Y.config.doc.documentElement,
       
  6850     Y_DOM = Y.DOM,
       
  6851     TAG_NAME = 'tagName',
       
  6852     OWNER_DOCUMENT = 'ownerDocument',
       
  6853     EMPTY_STRING = '',
       
  6854     addFeature = Y.Features.add,
       
  6855     testFeature = Y.Features.test;
       
  6856 
       
  6857 Y.mix(Y_DOM, {
       
  6858     /**
       
  6859      * Returns the text content of the HTMLElement. 
       
  6860      * @method getText         
       
  6861      * @param {HTMLElement} element The html element. 
       
  6862      * @return {String} The text content of the element (includes text of any descending elements).
       
  6863      */
       
  6864     getText: (documentElement.textContent !== undefined) ?
       
  6865         function(element) {
       
  6866             var ret = '';
       
  6867             if (element) {
       
  6868                 ret = element.textContent;
       
  6869             }
       
  6870             return ret || '';
       
  6871         } : function(element) {
       
  6872             var ret = '';
       
  6873             if (element) {
       
  6874                 ret = element.innerText || element.nodeValue; // might be a textNode
       
  6875             }
       
  6876             return ret || '';
       
  6877         },
       
  6878 
       
  6879     /**
       
  6880      * Sets the text content of the HTMLElement. 
       
  6881      * @method setText         
       
  6882      * @param {HTMLElement} element The html element. 
       
  6883      * @param {String} content The content to add. 
       
  6884      */
       
  6885     setText: (documentElement.textContent !== undefined) ?
       
  6886         function(element, content) {
       
  6887             if (element) {
       
  6888                 element.textContent = content;
       
  6889             }
       
  6890         } : function(element, content) {
       
  6891             if ('innerText' in element) {
       
  6892                 element.innerText = content;
       
  6893             } else if ('nodeValue' in element) {
       
  6894                 element.nodeValue = content;
       
  6895             }
       
  6896     },
       
  6897 
       
  6898     CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
       
  6899         'for': 'htmlFor',
       
  6900         'class': 'className'
       
  6901     } : { // w3c
       
  6902         'htmlFor': 'for',
       
  6903         'className': 'class'
       
  6904     },
       
  6905 
       
  6906     /**
       
  6907      * Provides a normalized attribute interface. 
       
  6908      * @method setAttribute
       
  6909      * @param {HTMLElement} el The target element for the attribute.
       
  6910      * @param {String} attr The attribute to set.
       
  6911      * @param {String} val The value of the attribute.
       
  6912      */
       
  6913     setAttribute: function(el, attr, val, ieAttr) {
       
  6914         if (el && attr && el.setAttribute) {
       
  6915             attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
       
  6916             el.setAttribute(attr, val, ieAttr);
       
  6917         }
       
  6918     },
       
  6919 
       
  6920 
       
  6921     /**
       
  6922      * Provides a normalized attribute interface. 
       
  6923      * @method getAttribute
       
  6924      * @param {HTMLElement} el The target element for the attribute.
       
  6925      * @param {String} attr The attribute to get.
       
  6926      * @return {String} The current value of the attribute. 
       
  6927      */
       
  6928     getAttribute: function(el, attr, ieAttr) {
       
  6929         ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
       
  6930         var ret = '';
       
  6931         if (el && attr && el.getAttribute) {
       
  6932             attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
       
  6933             ret = el.getAttribute(attr, ieAttr);
       
  6934 
       
  6935             if (ret === null) {
       
  6936                 ret = ''; // per DOM spec
       
  6937             }
       
  6938         }
       
  6939         return ret;
       
  6940     },
       
  6941 
       
  6942     VALUE_SETTERS: {},
       
  6943 
       
  6944     VALUE_GETTERS: {},
       
  6945 
       
  6946     getValue: function(node) {
       
  6947         var ret = '', // TODO: return null?
       
  6948             getter;
       
  6949 
       
  6950         if (node && node[TAG_NAME]) {
       
  6951             getter = Y_DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
       
  6952 
       
  6953             if (getter) {
       
  6954                 ret = getter(node);
       
  6955             } else {
       
  6956                 ret = node.value;
       
  6957             }
       
  6958         }
       
  6959 
       
  6960         // workaround for IE8 JSON stringify bug
       
  6961         // which converts empty string values to null
       
  6962         if (ret === EMPTY_STRING) {
       
  6963             ret = EMPTY_STRING; // for real
       
  6964         }
       
  6965 
       
  6966         return (typeof ret === 'string') ? ret : '';
       
  6967     },
       
  6968 
       
  6969     setValue: function(node, val) {
       
  6970         var setter;
       
  6971 
       
  6972         if (node && node[TAG_NAME]) {
       
  6973             setter = Y_DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
       
  6974 
       
  6975             if (setter) {
       
  6976                 setter(node, val);
       
  6977             } else {
       
  6978                 node.value = val;
       
  6979             }
       
  6980         }
       
  6981     },
       
  6982 
       
  6983     creators: {}
       
  6984 });
       
  6985 
       
  6986 addFeature('value-set', 'select', {
       
  6987     test: function() {
       
  6988         var node = Y.config.doc.createElement('select');
       
  6989         node.innerHTML = '<option>1</option><option>2</option>';
       
  6990         node.value = '2';
       
  6991         return (node.value && node.value === '2');
       
  6992     }
       
  6993 });
       
  6994 
       
  6995 if (!testFeature('value-set', 'select')) {
       
  6996     Y_DOM.VALUE_SETTERS.select = function(node, val) {
       
  6997         for (var i = 0, options = node.getElementsByTagName('option'), option;
       
  6998                 option = options[i++];) {
       
  6999             if (Y_DOM.getValue(option) === val) {
       
  7000                 option.selected = true;
       
  7001                 //Y_DOM.setAttribute(option, 'selected', 'selected');
       
  7002                 break;
       
  7003             }
       
  7004         }
       
  7005     };
       
  7006 }
       
  7007 
       
  7008 Y.mix(Y_DOM.VALUE_GETTERS, {
       
  7009     button: function(node) {
       
  7010         return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
       
  7011     }
       
  7012 });
       
  7013 
       
  7014 Y.mix(Y_DOM.VALUE_SETTERS, {
       
  7015     // IE: node.value changes the button text, which should be handled via innerHTML
       
  7016     button: function(node, val) {
       
  7017         var attr = node.attributes.value;
       
  7018         if (!attr) {
       
  7019             attr = node[OWNER_DOCUMENT].createAttribute('value');
       
  7020             node.setAttributeNode(attr);
       
  7021         }
       
  7022 
       
  7023         attr.value = val;
       
  7024     }
       
  7025 });
       
  7026 
       
  7027 
       
  7028 Y.mix(Y_DOM.VALUE_GETTERS, {
       
  7029     option: function(node) {
       
  7030         var attrs = node.attributes;
       
  7031         return (attrs.value && attrs.value.specified) ? node.value : node.text;
       
  7032     },
       
  7033 
       
  7034     select: function(node) {
       
  7035         var val = node.value,
       
  7036             options = node.options;
       
  7037 
       
  7038         if (options && options.length) {
       
  7039             // TODO: implement multipe select
       
  7040             if (node.multiple) {
       
  7041             } else if (node.selectedIndex > -1) {
       
  7042                 val = Y_DOM.getValue(options[node.selectedIndex]);
       
  7043             }
       
  7044         }
       
  7045 
       
  7046         return val;
       
  7047     }
       
  7048 });
       
  7049 var addClass, hasClass, removeClass;
       
  7050 
       
  7051 Y.mix(Y.DOM, {
       
  7052     /**
       
  7053      * Determines whether a DOM element has the given className.
       
  7054      * @method hasClass
       
  7055      * @for DOM
       
  7056      * @param {HTMLElement} element The DOM element. 
       
  7057      * @param {String} className the class name to search for
       
  7058      * @return {Boolean} Whether or not the element has the given class. 
       
  7059      */
       
  7060     hasClass: function(node, className) {
       
  7061         var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
       
  7062         return re.test(node.className);
       
  7063     },
       
  7064 
       
  7065     /**
       
  7066      * Adds a class name to a given DOM element.
       
  7067      * @method addClass         
       
  7068      * @for DOM
       
  7069      * @param {HTMLElement} element The DOM element. 
       
  7070      * @param {String} className the class name to add to the class attribute
       
  7071      */
       
  7072     addClass: function(node, className) {
       
  7073         if (!Y.DOM.hasClass(node, className)) { // skip if already present 
       
  7074             node.className = Y.Lang.trim([node.className, className].join(' '));
       
  7075         }
       
  7076     },
       
  7077 
       
  7078     /**
       
  7079      * Removes a class name from a given element.
       
  7080      * @method removeClass         
       
  7081      * @for DOM
       
  7082      * @param {HTMLElement} element The DOM element. 
       
  7083      * @param {String} className the class name to remove from the class attribute
       
  7084      */
       
  7085     removeClass: function(node, className) {
       
  7086         if (className && hasClass(node, className)) {
       
  7087             node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
       
  7088                             className + '(?:\\s+|$)'), ' '));
       
  7089 
       
  7090             if ( hasClass(node, className) ) { // in case of multiple adjacent
       
  7091                 removeClass(node, className);
       
  7092             }
       
  7093         }                 
       
  7094     },
       
  7095 
       
  7096     /**
       
  7097      * Replace a class with another class for a given element.
       
  7098      * If no oldClassName is present, the newClassName is simply added.
       
  7099      * @method replaceClass  
       
  7100      * @for DOM
       
  7101      * @param {HTMLElement} element The DOM element 
       
  7102      * @param {String} oldClassName the class name to be replaced
       
  7103      * @param {String} newClassName the class name that will be replacing the old class name
       
  7104      */
       
  7105     replaceClass: function(node, oldC, newC) {
       
  7106         removeClass(node, oldC); // remove first in case oldC === newC
       
  7107         addClass(node, newC);
       
  7108     },
       
  7109 
       
  7110     /**
       
  7111      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
  7112      * @method toggleClass  
       
  7113      * @for DOM
       
  7114      * @param {HTMLElement} element The DOM element
       
  7115      * @param {String} className the class name to be toggled
       
  7116      * @param {Boolean} addClass optional boolean to indicate whether class
       
  7117      * should be added or removed regardless of current state
       
  7118      */
       
  7119     toggleClass: function(node, className, force) {
       
  7120         var add = (force !== undefined) ? force :
       
  7121                 !(hasClass(node, className));
       
  7122 
       
  7123         if (add) {
       
  7124             addClass(node, className);
       
  7125         } else {
       
  7126             removeClass(node, className);
       
  7127         }
       
  7128     }
       
  7129 });
       
  7130 
       
  7131 hasClass = Y.DOM.hasClass;
       
  7132 removeClass = Y.DOM.removeClass;
       
  7133 addClass = Y.DOM.addClass;
       
  7134 
       
  7135 var re_tag = /<([a-z]+)/i,
       
  7136 
       
  7137     Y_DOM = Y.DOM,
       
  7138 
       
  7139     addFeature = Y.Features.add,
       
  7140     testFeature = Y.Features.test,
       
  7141 
       
  7142     creators = {},
       
  7143 
       
  7144     createFromDIV = function(html, tag) {
       
  7145         var div = Y.config.doc.createElement('div'),
       
  7146             ret = true;
       
  7147 
       
  7148         div.innerHTML = html;
       
  7149         if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
       
  7150             ret = false;
       
  7151         }
       
  7152 
       
  7153         return ret;
       
  7154     },
       
  7155 
       
  7156     re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,
       
  7157 
       
  7158     TABLE_OPEN = '<table>',
       
  7159     TABLE_CLOSE = '</table>';
       
  7160 
       
  7161 Y.mix(Y.DOM, {
       
  7162     _fragClones: {},
       
  7163 
       
  7164     _create: function(html, doc, tag) {
       
  7165         tag = tag || 'div';
       
  7166 
       
  7167         var frag = Y_DOM._fragClones[tag];
       
  7168         if (frag) {
       
  7169             frag = frag.cloneNode(false);
       
  7170         } else {
       
  7171             frag = Y_DOM._fragClones[tag] = doc.createElement(tag);
       
  7172         }
       
  7173         frag.innerHTML = html;
       
  7174         return frag;
       
  7175     },
       
  7176 
       
  7177     _children: function(node, tag) {
       
  7178             var i = 0,
       
  7179             children = node.children,
       
  7180             childNodes,
       
  7181             hasComments,
       
  7182             child;
       
  7183 
       
  7184         if (children && children.tags) { // use tags filter when possible
       
  7185             if (tag) {
       
  7186                 children = node.children.tags(tag);
       
  7187             } else { // IE leaks comments into children
       
  7188                 hasComments = children.tags('!').length;
       
  7189             }
       
  7190         }
       
  7191         
       
  7192         if (!children || (!children.tags && tag) || hasComments) {
       
  7193             childNodes = children || node.childNodes;
       
  7194             children = [];
       
  7195             while ((child = childNodes[i++])) {
       
  7196                 if (child.nodeType === 1) {
       
  7197                     if (!tag || tag === child.tagName) {
       
  7198                         children.push(child);
       
  7199                     }
       
  7200                 }
       
  7201             }
       
  7202         }
       
  7203 
       
  7204         return children || [];
       
  7205     },
       
  7206 
       
  7207     /**
       
  7208      * Creates a new dom node using the provided markup string. 
       
  7209      * @method create
       
  7210      * @param {String} html The markup used to create the element
       
  7211      * @param {HTMLDocument} doc An optional document context 
       
  7212      * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 
       
  7213      * when creating one node, and a documentFragment when creating
       
  7214      * multiple nodes.
       
  7215      */
       
  7216     create: function(html, doc) {
       
  7217         if (typeof html === 'string') {
       
  7218             html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML
       
  7219 
       
  7220         }
       
  7221 
       
  7222         doc = doc || Y.config.doc;
       
  7223         var m = re_tag.exec(html),
       
  7224             create = Y_DOM._create,
       
  7225             custom = creators,
       
  7226             ret = null,
       
  7227             creator,
       
  7228             tag, nodes;
       
  7229 
       
  7230         if (html != undefined) { // not undefined or null
       
  7231             if (m && m[1]) {
       
  7232                 creator = custom[m[1].toLowerCase()];
       
  7233                 if (typeof creator === 'function') {
       
  7234                     create = creator; 
       
  7235                 } else {
       
  7236                     tag = creator;
       
  7237                 }
       
  7238             }
       
  7239 
       
  7240             nodes = create(html, doc, tag).childNodes;
       
  7241 
       
  7242             if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment"
       
  7243                 ret = nodes[0].parentNode.removeChild(nodes[0]);
       
  7244             } else if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { // using dummy node to preserve some attributes (e.g. OPTION not selected)
       
  7245                 if (nodes.length === 2) {
       
  7246                     ret = nodes[0].nextSibling;
       
  7247                 } else {
       
  7248                     nodes[0].parentNode.removeChild(nodes[0]); 
       
  7249                     ret = Y_DOM._nl2frag(nodes, doc);
       
  7250                 }
       
  7251             } else { // return multiple nodes as a fragment
       
  7252                  ret = Y_DOM._nl2frag(nodes, doc);
       
  7253             }
       
  7254 
       
  7255         }
       
  7256 
       
  7257         return ret;
       
  7258     },
       
  7259 
       
  7260     _nl2frag: function(nodes, doc) {
       
  7261         var ret = null,
       
  7262             i, len;
       
  7263 
       
  7264         if (nodes && (nodes.push || nodes.item) && nodes[0]) {
       
  7265             doc = doc || nodes[0].ownerDocument; 
       
  7266             ret = doc.createDocumentFragment();
       
  7267 
       
  7268             if (nodes.item) { // convert live list to static array
       
  7269                 nodes = Y.Array(nodes, 0, true);
       
  7270             }
       
  7271 
       
  7272             for (i = 0, len = nodes.length; i < len; i++) {
       
  7273                 ret.appendChild(nodes[i]); 
       
  7274             }
       
  7275         } // else inline with log for minification
       
  7276         return ret;
       
  7277     },
       
  7278 
       
  7279     /**
       
  7280      * Inserts content in a node at the given location 
       
  7281      * @method addHTML
       
  7282      * @param {HTMLElement} node The node to insert into
       
  7283      * @param {HTMLElement | Array | HTMLCollection} content The content to be inserted 
       
  7284      * @param {HTMLElement} where Where to insert the content
       
  7285      * If no "where" is given, content is appended to the node
       
  7286      * Possible values for "where"
       
  7287      * <dl>
       
  7288      * <dt>HTMLElement</dt>
       
  7289      * <dd>The element to insert before</dd>
       
  7290      * <dt>"replace"</dt>
       
  7291      * <dd>Replaces the existing HTML</dd>
       
  7292      * <dt>"before"</dt>
       
  7293      * <dd>Inserts before the existing HTML</dd>
       
  7294      * <dt>"before"</dt>
       
  7295      * <dd>Inserts content before the node</dd>
       
  7296      * <dt>"after"</dt>
       
  7297      * <dd>Inserts content after the node</dd>
       
  7298      * </dl>
       
  7299      */
       
  7300     addHTML: function(node, content, where) {
       
  7301         var nodeParent = node.parentNode,
       
  7302             i = 0,
       
  7303             item,
       
  7304             ret = content,
       
  7305             newNode;
       
  7306             
       
  7307 
       
  7308         if (content != undefined) { // not null or undefined (maybe 0)
       
  7309             if (content.nodeType) { // DOM node, just add it
       
  7310                 newNode = content;
       
  7311             } else if (typeof content == 'string' || typeof content == 'number') {
       
  7312                 ret = newNode = Y_DOM.create(content);
       
  7313             } else if (content[0] && content[0].nodeType) { // array or collection 
       
  7314                 newNode = Y.config.doc.createDocumentFragment();
       
  7315                 while ((item = content[i++])) {
       
  7316                     newNode.appendChild(item); // append to fragment for insertion
       
  7317                 }
       
  7318             }
       
  7319         }
       
  7320 
       
  7321         if (where) {
       
  7322             if (newNode && where.parentNode) { // insert regardless of relationship to node
       
  7323                 where.parentNode.insertBefore(newNode, where);
       
  7324             } else {
       
  7325                 switch (where) {
       
  7326                     case 'replace':
       
  7327                         while (node.firstChild) {
       
  7328                             node.removeChild(node.firstChild);
       
  7329                         }
       
  7330                         if (newNode) { // allow empty content to clear node
       
  7331                             node.appendChild(newNode);
       
  7332                         }
       
  7333                         break;
       
  7334                     case 'before':
       
  7335                         if (newNode) {
       
  7336                             nodeParent.insertBefore(newNode, node);
       
  7337                         }
       
  7338                         break;
       
  7339                     case 'after':
       
  7340                         if (newNode) {
       
  7341                             if (node.nextSibling) { // IE errors if refNode is null
       
  7342                                 nodeParent.insertBefore(newNode, node.nextSibling);
       
  7343                             } else {
       
  7344                                 nodeParent.appendChild(newNode);
       
  7345                             }
       
  7346                         }
       
  7347                         break;
       
  7348                     default:
       
  7349                         if (newNode) {
       
  7350                             node.appendChild(newNode);
       
  7351                         }
       
  7352                 }
       
  7353             }
       
  7354         } else if (newNode) {
       
  7355             node.appendChild(newNode);
       
  7356         }
       
  7357 
       
  7358         return ret;
       
  7359     },
       
  7360 
       
  7361     wrap: function(node, html) {
       
  7362         var parent = (html && html.nodeType) ? html : Y.DOM.create(html),
       
  7363             nodes = parent.getElementsByTagName('*');
       
  7364 
       
  7365         if (nodes.length) {
       
  7366             parent = nodes[nodes.length - 1];
       
  7367         }
       
  7368 
       
  7369         if (node.parentNode) { 
       
  7370             node.parentNode.replaceChild(parent, node);
       
  7371         }
       
  7372         parent.appendChild(node);
       
  7373     },
       
  7374 
       
  7375     unwrap: function(node) {
       
  7376         var parent = node.parentNode,
       
  7377             lastChild = parent.lastChild,
       
  7378             next = node,
       
  7379             grandparent;
       
  7380 
       
  7381         if (parent) {
       
  7382             grandparent = parent.parentNode;
       
  7383             if (grandparent) {
       
  7384                 node = parent.firstChild;
       
  7385                 while (node !== lastChild) {
       
  7386                     next = node.nextSibling;
       
  7387                     grandparent.insertBefore(node, parent);
       
  7388                     node = next;
       
  7389                 }
       
  7390                 grandparent.replaceChild(lastChild, parent);
       
  7391             } else {
       
  7392                 parent.removeChild(node);
       
  7393             }
       
  7394         }
       
  7395     }
       
  7396 });
       
  7397 
       
  7398 addFeature('innerhtml', 'table', {
       
  7399     test: function() {
       
  7400         var node = Y.config.doc.createElement('table');
       
  7401         try {
       
  7402             node.innerHTML = '<tbody></tbody>';
       
  7403         } catch(e) {
       
  7404             return false;
       
  7405         }
       
  7406         return (node.firstChild && node.firstChild.nodeName === 'TBODY');
       
  7407     }
       
  7408 });
       
  7409 
       
  7410 addFeature('innerhtml-div', 'tr', {
       
  7411     test: function() {
       
  7412         return createFromDIV('<tr></tr>', 'tr');
       
  7413     }
       
  7414 });
       
  7415 
       
  7416 addFeature('innerhtml-div', 'script', {
       
  7417     test: function() {
       
  7418         return createFromDIV('<script></script>', 'script');
       
  7419     }
       
  7420 });
       
  7421 
       
  7422 if (!testFeature('innerhtml', 'table')) {
       
  7423     // TODO: thead/tfoot with nested tbody
       
  7424         // IE adds TBODY when creating TABLE elements (which may share this impl)
       
  7425     creators.tbody = function(html, doc) {
       
  7426         var frag = Y_DOM.create(TABLE_OPEN + html + TABLE_CLOSE, doc),
       
  7427             tb = Y.DOM._children(frag, 'tbody')[0];
       
  7428 
       
  7429         if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
       
  7430             tb.parentNode.removeChild(tb); // strip extraneous tbody
       
  7431         }
       
  7432         return frag;
       
  7433     };
       
  7434 }
       
  7435 
       
  7436 if (!testFeature('innerhtml-div', 'script')) {
       
  7437     creators.script = function(html, doc) {
       
  7438         var frag = doc.createElement('div');
       
  7439 
       
  7440         frag.innerHTML = '-' + html;
       
  7441         frag.removeChild(frag.firstChild);
       
  7442         return frag;
       
  7443     };
       
  7444 
       
  7445     creators.link = creators.style = creators.script;
       
  7446 }
       
  7447 
       
  7448 if (!testFeature('innerhtml-div', 'tr')) {
       
  7449     Y.mix(creators, {
       
  7450         option: function(html, doc) {
       
  7451             return Y_DOM.create('<select><option class="yui3-big-dummy" selected></option>' + html + '</select>', doc);
       
  7452         },
       
  7453 
       
  7454         tr: function(html, doc) {
       
  7455             return Y_DOM.create('<tbody>' + html + '</tbody>', doc);
       
  7456         },
       
  7457 
       
  7458         td: function(html, doc) {
       
  7459             return Y_DOM.create('<tr>' + html + '</tr>', doc);
       
  7460         }, 
       
  7461 
       
  7462         col: function(html, doc) {
       
  7463             return Y_DOM.create('<colgroup>' + html + '</colgroup>', doc);
       
  7464         }, 
       
  7465 
       
  7466         tbody: 'table'
       
  7467     });
       
  7468 
       
  7469     Y.mix(creators, {
       
  7470         legend: 'fieldset',
       
  7471         th: creators.td,
       
  7472         thead: creators.tbody,
       
  7473         tfoot: creators.tbody,
       
  7474         caption: creators.tbody,
       
  7475         colgroup: creators.tbody,
       
  7476         optgroup: creators.option
       
  7477     });
       
  7478 }
       
  7479 
       
  7480 Y_DOM.creators = creators;
       
  7481 Y.mix(Y.DOM, {
       
  7482     /**
       
  7483      * Sets the width of the element to the given size, regardless
       
  7484      * of box model, border, padding, etc.
       
  7485      * @method setWidth
       
  7486      * @param {HTMLElement} element The DOM element. 
       
  7487      * @param {String|Number} size The pixel height to size to
       
  7488      */
       
  7489 
       
  7490     setWidth: function(node, size) {
       
  7491         Y.DOM._setSize(node, 'width', size);
       
  7492     },
       
  7493 
       
  7494     /**
       
  7495      * Sets the height of the element to the given size, regardless
       
  7496      * of box model, border, padding, etc.
       
  7497      * @method setHeight
       
  7498      * @param {HTMLElement} element The DOM element. 
       
  7499      * @param {String|Number} size The pixel height to size to
       
  7500      */
       
  7501 
       
  7502     setHeight: function(node, size) {
       
  7503         Y.DOM._setSize(node, 'height', size);
       
  7504     },
       
  7505 
       
  7506     _setSize: function(node, prop, val) {
       
  7507         val = (val > 0) ? val : 0;
       
  7508         var size = 0;
       
  7509 
       
  7510         node.style[prop] = val + 'px';
       
  7511         size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
       
  7512 
       
  7513         if (size > val) {
       
  7514             val = val - (size - val);
       
  7515 
       
  7516             if (val < 0) {
       
  7517                 val = 0;
       
  7518             }
       
  7519 
       
  7520             node.style[prop] = val + 'px';
       
  7521         }
       
  7522     }
       
  7523 });
       
  7524 
       
  7525 
       
  7526 }, '@VERSION@', {"requires": ["dom-core"]});
       
  7527 YUI.add('color-base', function (Y, NAME) {
       
  7528 
       
  7529 /**
       
  7530 Color provides static methods for color conversion.
       
  7531 
       
  7532     Y.Color.toRGB('f00'); // rgb(255, 0, 0)
       
  7533 
       
  7534     Y.Color.toHex('rgb(255, 255, 0)'); // #ffff00
       
  7535 
       
  7536 @module color
       
  7537 @submodule color-base
       
  7538 @class Color
       
  7539 @since 3.8.0
       
  7540 **/
       
  7541 
       
  7542 var REGEX_HEX = /^#?([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})(\ufffe)?/,
       
  7543     REGEX_HEX3 = /^#?([\da-fA-F]{1})([\da-fA-F]{1})([\da-fA-F]{1})(\ufffe)?/,
       
  7544     REGEX_RGB = /rgba?\(([\d]{1,3}), ?([\d]{1,3}), ?([\d]{1,3}),? ?([.\d]*)?\)/,
       
  7545     TYPES = { 'HEX': 'hex', 'RGB': 'rgb', 'RGBA': 'rgba' },
       
  7546     CONVERTS = { 'hex': 'toHex', 'rgb': 'toRGB', 'rgba': 'toRGBA' };
       
  7547 
       
  7548 
       
  7549 Y.Color = {
       
  7550     /**
       
  7551     @static
       
  7552     @property KEYWORDS
       
  7553     @type Object
       
  7554     @since 3.8.0
       
  7555     **/
       
  7556     KEYWORDS: {
       
  7557         'black': '000', 'silver': 'c0c0c0', 'gray': '808080', 'white': 'fff',
       
  7558         'maroon': '800000', 'red': 'f00', 'purple': '800080', 'fuchsia': 'f0f',
       
  7559         'green': '008000', 'lime': '0f0', 'olive': '808000', 'yellow': 'ff0',
       
  7560         'navy': '000080', 'blue': '00f', 'teal': '008080', 'aqua': '0ff'
       
  7561     },
       
  7562 
       
  7563     /**
       
  7564         NOTE: `(\ufffe)?` is added to the Regular Expression to carve out a
       
  7565         place for the alpha channel that is returned from toArray
       
  7566         without compromising any usage of the Regular Expression
       
  7567 
       
  7568     @static
       
  7569     @property REGEX_HEX
       
  7570     @type RegExp
       
  7571     @default /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})(\ufffe)?/
       
  7572     @since 3.8.0
       
  7573     **/
       
  7574     REGEX_HEX: REGEX_HEX,
       
  7575 
       
  7576     /**
       
  7577         NOTE: `(\ufffe)?` is added to the Regular Expression to carve out a
       
  7578         place for the alpha channel that is returned from toArray
       
  7579         without compromising any usage of the Regular Expression
       
  7580 
       
  7581     @static
       
  7582     @property REGEX_HEX3
       
  7583     @type RegExp
       
  7584     @default /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})(\ufffe)?/
       
  7585     @since 3.8.0
       
  7586     **/
       
  7587     REGEX_HEX3: REGEX_HEX3,
       
  7588 
       
  7589     /**
       
  7590     @static
       
  7591     @property REGEX_RGB
       
  7592     @type RegExp
       
  7593     @default /rgba?\(([0-9]{1,3}), ?([0-9]{1,3}), ?([0-9]{1,3}),? ?([.0-9]{1,3})?\)/
       
  7594     @since 3.8.0
       
  7595     **/
       
  7596     REGEX_RGB: REGEX_RGB,
       
  7597 
       
  7598     re_RGB: REGEX_RGB,
       
  7599 
       
  7600     re_hex: REGEX_HEX,
       
  7601 
       
  7602     re_hex3: REGEX_HEX3,
       
  7603 
       
  7604     /**
       
  7605     @static
       
  7606     @property STR_HEX
       
  7607     @type String
       
  7608     @default #{*}{*}{*}
       
  7609     @since 3.8.0
       
  7610     **/
       
  7611     STR_HEX: '#{*}{*}{*}',
       
  7612 
       
  7613     /**
       
  7614     @static
       
  7615     @property STR_RGB
       
  7616     @type String
       
  7617     @default rgb({*}, {*}, {*})
       
  7618     @since 3.8.0
       
  7619     **/
       
  7620     STR_RGB: 'rgb({*}, {*}, {*})',
       
  7621 
       
  7622     /**
       
  7623     @static
       
  7624     @property STR_RGBA
       
  7625     @type String
       
  7626     @default rgba({*}, {*}, {*}, {*})
       
  7627     @since 3.8.0
       
  7628     **/
       
  7629     STR_RGBA: 'rgba({*}, {*}, {*}, {*})',
       
  7630 
       
  7631     /**
       
  7632     @static
       
  7633     @property TYPES
       
  7634     @type Object
       
  7635     @default {'rgb':'rgb', 'rgba':'rgba'}
       
  7636     @since 3.8.0
       
  7637     **/
       
  7638     TYPES: TYPES,
       
  7639 
       
  7640     /**
       
  7641     @static
       
  7642     @property CONVERTS
       
  7643     @type Object
       
  7644     @default {}
       
  7645     @since 3.8.0
       
  7646     **/
       
  7647     CONVERTS: CONVERTS,
       
  7648 
       
  7649     /**
       
  7650      Converts the provided string to the provided type.
       
  7651      You can use the `Y.Color.TYPES` to get a valid `to` type.
       
  7652      If the color cannot be converted, the original color will be returned.
       
  7653 
       
  7654      @public
       
  7655      @method convert
       
  7656      @param {String} str
       
  7657      @param {String} to
       
  7658      @return {String}
       
  7659      @since 3.8.0
       
  7660      **/
       
  7661     convert: function (str, to) {
       
  7662         var convert = Y.Color.CONVERTS[to.toLowerCase()],
       
  7663             clr = str;
       
  7664 
       
  7665         if (convert && Y.Color[convert]) {
       
  7666             clr = Y.Color[convert](str);
       
  7667         }
       
  7668 
       
  7669         return clr;
       
  7670     },
       
  7671 
       
  7672     /**
       
  7673     Converts provided color value to a hex value string
       
  7674 
       
  7675     @public
       
  7676     @method toHex
       
  7677     @param {String} str Hex or RGB value string
       
  7678     @return {String} returns array of values or CSS string if options.css is true
       
  7679     @since 3.8.0
       
  7680     **/
       
  7681     toHex: function (str) {
       
  7682         var clr = Y.Color._convertTo(str, 'hex'),
       
  7683             isTransparent = clr.toLowerCase() === 'transparent';
       
  7684 
       
  7685         if (clr.charAt(0) !== '#' && !isTransparent) {
       
  7686             clr = '#' + clr;
       
  7687         }
       
  7688 
       
  7689         return isTransparent ? clr.toLowerCase() : clr.toUpperCase();
       
  7690     },
       
  7691 
       
  7692     /**
       
  7693     Converts provided color value to an RGB value string
       
  7694     @public
       
  7695     @method toRGB
       
  7696     @param {String} str Hex or RGB value string
       
  7697     @return {String}
       
  7698     @since 3.8.0
       
  7699     **/
       
  7700     toRGB: function (str) {
       
  7701         var clr = Y.Color._convertTo(str, 'rgb');
       
  7702         return clr.toLowerCase();
       
  7703     },
       
  7704 
       
  7705     /**
       
  7706     Converts provided color value to an RGB value string
       
  7707     @public
       
  7708     @method toRGBA
       
  7709     @param {String} str Hex or RGB value string
       
  7710     @return {String}
       
  7711     @since 3.8.0
       
  7712     **/
       
  7713     toRGBA: function (str) {
       
  7714         var clr = Y.Color._convertTo(str, 'rgba' );
       
  7715         return clr.toLowerCase();
       
  7716     },
       
  7717 
       
  7718     /**
       
  7719     Converts the provided color string to an array of values where the
       
  7720         last value is the alpha value. Will return an empty array if
       
  7721         the provided string is not able to be parsed.
       
  7722 
       
  7723         NOTE: `(\ufffe)?` is added to `HEX` and `HEX3` Regular Expressions to
       
  7724         carve out a place for the alpha channel that is returned from
       
  7725         toArray without compromising any usage of the Regular Expression
       
  7726 
       
  7727         Y.Color.toArray('fff');              // ['ff', 'ff', 'ff', 1]
       
  7728         Y.Color.toArray('rgb(0, 0, 0)');     // ['0', '0', '0', 1]
       
  7729         Y.Color.toArray('rgba(0, 0, 0, 0)'); // ['0', '0', '0', 1]
       
  7730 
       
  7731 
       
  7732 
       
  7733     @public
       
  7734     @method toArray
       
  7735     @param {String} str
       
  7736     @return {Array}
       
  7737     @since 3.8.0
       
  7738     **/
       
  7739     toArray: function(str) {
       
  7740         // parse with regex and return "matches" array
       
  7741         var type = Y.Color.findType(str).toUpperCase(),
       
  7742             regex,
       
  7743             arr,
       
  7744             length,
       
  7745             lastItem;
       
  7746 
       
  7747         if (type === 'HEX' && str.length < 5) {
       
  7748             type = 'HEX3';
       
  7749         }
       
  7750 
       
  7751         if (type.charAt(type.length - 1) === 'A') {
       
  7752             type = type.slice(0, -1);
       
  7753         }
       
  7754 
       
  7755         regex = Y.Color['REGEX_' + type];
       
  7756 
       
  7757         if (regex) {
       
  7758             arr = regex.exec(str) || [];
       
  7759             length = arr.length;
       
  7760 
       
  7761             if (length) {
       
  7762 
       
  7763                 arr.shift();
       
  7764                 length--;
       
  7765 
       
  7766                 if (type === 'HEX3') {
       
  7767                     arr[0] += arr[0];
       
  7768                     arr[1] += arr[1];
       
  7769                     arr[2] += arr[2];
       
  7770                 }
       
  7771 
       
  7772                 lastItem = arr[length - 1];
       
  7773                 if (!lastItem) {
       
  7774                     arr[length - 1] = 1;
       
  7775                 }
       
  7776             }
       
  7777         }
       
  7778 
       
  7779         return arr;
       
  7780 
       
  7781     },
       
  7782 
       
  7783     /**
       
  7784     Converts the array of values to a string based on the provided template.
       
  7785     @public
       
  7786     @method fromArray
       
  7787     @param {Array} arr
       
  7788     @param {String} template
       
  7789     @return {String}
       
  7790     @since 3.8.0
       
  7791     **/
       
  7792     fromArray: function(arr, template) {
       
  7793         arr = arr.concat();
       
  7794 
       
  7795         if (typeof template === 'undefined') {
       
  7796             return arr.join(', ');
       
  7797         }
       
  7798 
       
  7799         var replace = '{*}';
       
  7800 
       
  7801         template = Y.Color['STR_' + template.toUpperCase()];
       
  7802 
       
  7803         if (arr.length === 3 && template.match(/\{\*\}/g).length === 4) {
       
  7804             arr.push(1);
       
  7805         }
       
  7806 
       
  7807         while ( template.indexOf(replace) >= 0 && arr.length > 0) {
       
  7808             template = template.replace(replace, arr.shift());
       
  7809         }
       
  7810 
       
  7811         return template;
       
  7812     },
       
  7813 
       
  7814     /**
       
  7815     Finds the value type based on the str value provided.
       
  7816     @public
       
  7817     @method findType
       
  7818     @param {String} str
       
  7819     @return {String}
       
  7820     @since 3.8.0
       
  7821     **/
       
  7822     findType: function (str) {
       
  7823         if (Y.Color.KEYWORDS[str]) {
       
  7824             return 'keyword';
       
  7825         }
       
  7826 
       
  7827         var index = str.indexOf('('),
       
  7828             key;
       
  7829 
       
  7830         if (index > 0) {
       
  7831             key = str.substr(0, index);
       
  7832         }
       
  7833 
       
  7834         if (key && Y.Color.TYPES[key.toUpperCase()]) {
       
  7835             return Y.Color.TYPES[key.toUpperCase()];
       
  7836         }
       
  7837 
       
  7838         return 'hex';
       
  7839 
       
  7840     }, // return 'keyword', 'hex', 'rgb'
       
  7841 
       
  7842     /**
       
  7843     Retrives the alpha channel from the provided string. If no alpha
       
  7844         channel is present, `1` will be returned.
       
  7845     @protected
       
  7846     @method _getAlpha
       
  7847     @param {String} clr
       
  7848     @return {Number}
       
  7849     @since 3.8.0
       
  7850     **/
       
  7851     _getAlpha: function (clr) {
       
  7852         var alpha,
       
  7853             arr = Y.Color.toArray(clr);
       
  7854 
       
  7855         if (arr.length > 3) {
       
  7856             alpha = arr.pop();
       
  7857         }
       
  7858 
       
  7859         return +alpha || 1;
       
  7860     },
       
  7861 
       
  7862     /**
       
  7863     Returns the hex value string if found in the KEYWORDS object
       
  7864     @protected
       
  7865     @method _keywordToHex
       
  7866     @param {String} clr
       
  7867     @return {String}
       
  7868     @since 3.8.0
       
  7869     **/
       
  7870     _keywordToHex: function (clr) {
       
  7871         var keyword = Y.Color.KEYWORDS[clr];
       
  7872 
       
  7873         if (keyword) {
       
  7874             return keyword;
       
  7875         }
       
  7876     },
       
  7877 
       
  7878     /**
       
  7879     Converts the provided color string to the value type provided as `to`
       
  7880     @protected
       
  7881     @method _convertTo
       
  7882     @param {String} clr
       
  7883     @param {String} to
       
  7884     @return {String}
       
  7885     @since 3.8.0
       
  7886     **/
       
  7887     _convertTo: function(clr, to) {
       
  7888 
       
  7889         if (clr === 'transparent') {
       
  7890             return clr;
       
  7891         }
       
  7892 
       
  7893         var from = Y.Color.findType(clr),
       
  7894             originalTo = to,
       
  7895             needsAlpha,
       
  7896             alpha,
       
  7897             method,
       
  7898             ucTo;
       
  7899 
       
  7900         if (from === 'keyword') {
       
  7901             clr = Y.Color._keywordToHex(clr);
       
  7902             from = 'hex';
       
  7903         }
       
  7904 
       
  7905         if (from === 'hex' && clr.length < 5) {
       
  7906             if (clr.charAt(0) === '#') {
       
  7907                 clr = clr.substr(1);
       
  7908             }
       
  7909 
       
  7910             clr = '#' + clr.charAt(0) + clr.charAt(0) +
       
  7911                         clr.charAt(1) + clr.charAt(1) +
       
  7912                         clr.charAt(2) + clr.charAt(2);
       
  7913         }
       
  7914 
       
  7915         if (from === to) {
       
  7916             return clr;
       
  7917         }
       
  7918 
       
  7919         if (from.charAt(from.length - 1) === 'a') {
       
  7920             from = from.slice(0, -1);
       
  7921         }
       
  7922 
       
  7923         needsAlpha = (to.charAt(to.length - 1) === 'a');
       
  7924         if (needsAlpha) {
       
  7925             to = to.slice(0, -1);
       
  7926             alpha = Y.Color._getAlpha(clr);
       
  7927         }
       
  7928 
       
  7929         ucTo = to.charAt(0).toUpperCase() + to.substr(1).toLowerCase();
       
  7930         method = Y.Color['_' + from + 'To' + ucTo ];
       
  7931 
       
  7932         // check to see if need conversion to rgb first
       
  7933         // check to see if there is a direct conversion method
       
  7934         // convertions are: hex <-> rgb <-> hsl
       
  7935         if (!method) {
       
  7936             if (from !== 'rgb' && to !== 'rgb') {
       
  7937                 clr = Y.Color['_' + from + 'ToRgb'](clr);
       
  7938                 from = 'rgb';
       
  7939                 method = Y.Color['_' + from + 'To' + ucTo ];
       
  7940             }
       
  7941         }
       
  7942 
       
  7943         if (method) {
       
  7944             clr = ((method)(clr, needsAlpha));
       
  7945         }
       
  7946 
       
  7947         // process clr from arrays to strings after conversions if alpha is needed
       
  7948         if (needsAlpha) {
       
  7949             if (!Y.Lang.isArray(clr)) {
       
  7950                 clr = Y.Color.toArray(clr);
       
  7951             }
       
  7952             clr.push(alpha);
       
  7953             clr = Y.Color.fromArray(clr, originalTo.toUpperCase());
       
  7954         }
       
  7955 
       
  7956         return clr;
       
  7957     },
       
  7958 
       
  7959     /**
       
  7960     Processes the hex string into r, g, b values. Will return values as
       
  7961         an array, or as an rgb string.
       
  7962     @protected
       
  7963     @method _hexToRgb
       
  7964     @param {String} str
       
  7965     @param {Boolean} [toArray]
       
  7966     @return {String|Array}
       
  7967     @since 3.8.0
       
  7968     **/
       
  7969     _hexToRgb: function (str, toArray) {
       
  7970         var r, g, b;
       
  7971 
       
  7972         /*jshint bitwise:false*/
       
  7973         if (str.charAt(0) === '#') {
       
  7974             str = str.substr(1);
       
  7975         }
       
  7976 
       
  7977         str = parseInt(str, 16);
       
  7978 
       
  7979         r = str >> 16;
       
  7980         g = str >> 8 & 0xFF;
       
  7981         b = str & 0xFF;
       
  7982 
       
  7983         if (toArray) {
       
  7984             return [r, g, b];
       
  7985         }
       
  7986 
       
  7987         return 'rgb(' + r + ', ' + g + ', ' + b + ')';
       
  7988     },
       
  7989 
       
  7990     /**
       
  7991     Processes the rgb string into r, g, b values. Will return values as
       
  7992         an array, or as a hex string.
       
  7993     @protected
       
  7994     @method _rgbToHex
       
  7995     @param {String} str
       
  7996     @param {Boolean} [toArray]
       
  7997     @return {String|Array}
       
  7998     @since 3.8.0
       
  7999     **/
       
  8000     _rgbToHex: function (str) {
       
  8001         /*jshint bitwise:false*/
       
  8002         var rgb = Y.Color.toArray(str),
       
  8003             hex = rgb[2] | (rgb[1] << 8) | (rgb[0] << 16);
       
  8004 
       
  8005         hex = (+hex).toString(16);
       
  8006 
       
  8007         while (hex.length < 6) {
       
  8008             hex = '0' + hex;
       
  8009         }
       
  8010 
       
  8011         return '#' + hex;
       
  8012     }
       
  8013 
       
  8014 };
       
  8015 
       
  8016 
       
  8017 
       
  8018 }, '@VERSION@', {"requires": ["yui-base"]});
       
  8019 YUI.add('dom-style', function (Y, NAME) {
       
  8020 
       
  8021 (function(Y) {
       
  8022 /** 
       
  8023  * Add style management functionality to DOM.
       
  8024  * @module dom
       
  8025  * @submodule dom-style
       
  8026  * @for DOM
       
  8027  */
       
  8028 
       
  8029 var DOCUMENT_ELEMENT = 'documentElement',
       
  8030     DEFAULT_VIEW = 'defaultView',
       
  8031     OWNER_DOCUMENT = 'ownerDocument',
       
  8032     STYLE = 'style',
       
  8033     FLOAT = 'float',
       
  8034     CSS_FLOAT = 'cssFloat',
       
  8035     STYLE_FLOAT = 'styleFloat',
       
  8036     TRANSPARENT = 'transparent',
       
  8037     GET_COMPUTED_STYLE = 'getComputedStyle',
       
  8038     GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
       
  8039 
       
  8040     WINDOW = Y.config.win,
       
  8041     DOCUMENT = Y.config.doc,
       
  8042     UNDEFINED = undefined,
       
  8043 
       
  8044     Y_DOM = Y.DOM,
       
  8045 
       
  8046     TRANSFORM = 'transform',
       
  8047     TRANSFORMORIGIN = 'transformOrigin',
       
  8048     VENDOR_TRANSFORM = [
       
  8049         'WebkitTransform',
       
  8050         'MozTransform',
       
  8051         'OTransform',
       
  8052         'msTransform'
       
  8053     ],
       
  8054 
       
  8055     re_color = /color$/i,
       
  8056     re_unit = /width|height|top|left|right|bottom|margin|padding/i;
       
  8057 
       
  8058 Y.Array.each(VENDOR_TRANSFORM, function(val) {
       
  8059     if (val in DOCUMENT[DOCUMENT_ELEMENT].style) {
       
  8060         TRANSFORM = val;
       
  8061         TRANSFORMORIGIN = val + "Origin";
       
  8062     }
       
  8063 });
       
  8064 
       
  8065 Y.mix(Y_DOM, {
       
  8066     DEFAULT_UNIT: 'px',
       
  8067 
       
  8068     CUSTOM_STYLES: {
       
  8069     },
       
  8070 
       
  8071 
       
  8072     /**
       
  8073      * Sets a style property for a given element.
       
  8074      * @method setStyle
       
  8075      * @param {HTMLElement} An HTMLElement to apply the style to.
       
  8076      * @param {String} att The style property to set. 
       
  8077      * @param {String|Number} val The value. 
       
  8078      */
       
  8079     setStyle: function(node, att, val, style) {
       
  8080         style = style || node.style;
       
  8081         var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES;
       
  8082 
       
  8083         if (style) {
       
  8084             if (val === null || val === '') { // normalize unsetting
       
  8085                 val = '';
       
  8086             } else if (!isNaN(new Number(val)) && re_unit.test(att)) { // number values may need a unit
       
  8087                 val += Y_DOM.DEFAULT_UNIT;
       
  8088             }
       
  8089 
       
  8090             if (att in CUSTOM_STYLES) {
       
  8091                 if (CUSTOM_STYLES[att].set) {
       
  8092                     CUSTOM_STYLES[att].set(node, val, style);
       
  8093                     return; // NOTE: return
       
  8094                 } else if (typeof CUSTOM_STYLES[att] === 'string') {
       
  8095                     att = CUSTOM_STYLES[att];
       
  8096                 }
       
  8097             } else if (att === '') { // unset inline styles
       
  8098                 att = 'cssText';
       
  8099                 val = '';
       
  8100             }
       
  8101             style[att] = val; 
       
  8102         }
       
  8103     },
       
  8104 
       
  8105     /**
       
  8106      * Returns the current style value for the given property.
       
  8107      * @method getStyle
       
  8108      * @param {HTMLElement} An HTMLElement to get the style from.
       
  8109      * @param {String} att The style property to get. 
       
  8110      */
       
  8111     getStyle: function(node, att, style) {
       
  8112         style = style || node.style;
       
  8113         var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES,
       
  8114             val = '';
       
  8115 
       
  8116         if (style) {
       
  8117             if (att in CUSTOM_STYLES) {
       
  8118                 if (CUSTOM_STYLES[att].get) {
       
  8119                     return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
       
  8120                 } else if (typeof CUSTOM_STYLES[att] === 'string') {
       
  8121                     att = CUSTOM_STYLES[att];
       
  8122                 }
       
  8123             }
       
  8124             val = style[att];
       
  8125             if (val === '') { // TODO: is empty string sufficient?
       
  8126                 val = Y_DOM[GET_COMPUTED_STYLE](node, att);
       
  8127             }
       
  8128         }
       
  8129 
       
  8130         return val;
       
  8131     },
       
  8132 
       
  8133     /**
       
  8134      * Sets multiple style properties.
       
  8135      * @method setStyles
       
  8136      * @param {HTMLElement} node An HTMLElement to apply the styles to. 
       
  8137      * @param {Object} hash An object literal of property:value pairs. 
       
  8138      */
       
  8139     setStyles: function(node, hash) {
       
  8140         var style = node.style;
       
  8141         Y.each(hash, function(v, n) {
       
  8142             Y_DOM.setStyle(node, n, v, style);
       
  8143         }, Y_DOM);
       
  8144     },
       
  8145 
       
  8146     /**
       
  8147      * Returns the computed style for the given node.
       
  8148      * @method getComputedStyle
       
  8149      * @param {HTMLElement} An HTMLElement to get the style from.
       
  8150      * @param {String} att The style property to get. 
       
  8151      * @return {String} The computed value of the style property. 
       
  8152      */
       
  8153     getComputedStyle: function(node, att) {
       
  8154         var val = '',
       
  8155             doc = node[OWNER_DOCUMENT],
       
  8156             computed;
       
  8157 
       
  8158         if (node[STYLE] && doc[DEFAULT_VIEW] && doc[DEFAULT_VIEW][GET_COMPUTED_STYLE]) {
       
  8159             computed = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, null);
       
  8160             if (computed) { // FF may be null in some cases (ticket #2530548)
       
  8161                 val = computed[att];
       
  8162             }
       
  8163         }
       
  8164         return val;
       
  8165     }
       
  8166 });
       
  8167 
       
  8168 // normalize reserved word float alternatives ("cssFloat" or "styleFloat")
       
  8169 if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
       
  8170     Y_DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
       
  8171 } else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
       
  8172     Y_DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
       
  8173 }
       
  8174 
       
  8175 // fix opera computedStyle default color unit (convert to rgb)
       
  8176 if (Y.UA.opera) {
       
  8177     Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
       
  8178         var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
       
  8179             val = view[GET_COMPUTED_STYLE](node, '')[att];
       
  8180 
       
  8181         if (re_color.test(att)) {
       
  8182             val = Y.Color.toRGB(val);
       
  8183         }
       
  8184 
       
  8185         return val;
       
  8186     };
       
  8187 
       
  8188 }
       
  8189 
       
  8190 // safari converts transparent to rgba(), others use "transparent"
       
  8191 if (Y.UA.webkit) {
       
  8192     Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
       
  8193         var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
       
  8194             val = view[GET_COMPUTED_STYLE](node, '')[att];
       
  8195 
       
  8196         if (val === 'rgba(0, 0, 0, 0)') {
       
  8197             val = TRANSPARENT; 
       
  8198         }
       
  8199 
       
  8200         return val;
       
  8201     };
       
  8202 
       
  8203 }
       
  8204 
       
  8205 Y.DOM._getAttrOffset = function(node, attr) {
       
  8206     var val = Y.DOM[GET_COMPUTED_STYLE](node, attr),
       
  8207         offsetParent = node.offsetParent,
       
  8208         position,
       
  8209         parentOffset,
       
  8210         offset;
       
  8211 
       
  8212     if (val === 'auto') {
       
  8213         position = Y.DOM.getStyle(node, 'position');
       
  8214         if (position === 'static' || position === 'relative') {
       
  8215             val = 0;    
       
  8216         } else if (offsetParent && offsetParent[GET_BOUNDING_CLIENT_RECT]) {
       
  8217             parentOffset = offsetParent[GET_BOUNDING_CLIENT_RECT]()[attr];
       
  8218             offset = node[GET_BOUNDING_CLIENT_RECT]()[attr];
       
  8219             if (attr === 'left' || attr === 'top') {
       
  8220                 val = offset - parentOffset;
       
  8221             } else {
       
  8222                 val = parentOffset - node[GET_BOUNDING_CLIENT_RECT]()[attr];
       
  8223             }
       
  8224         }
       
  8225     }
       
  8226 
       
  8227     return val;
       
  8228 };
       
  8229 
       
  8230 Y.DOM._getOffset = function(node) {
       
  8231     var pos,
       
  8232         xy = null;
       
  8233 
       
  8234     if (node) {
       
  8235         pos = Y_DOM.getStyle(node, 'position');
       
  8236         xy = [
       
  8237             parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'left'), 10),
       
  8238             parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'top'), 10)
       
  8239         ];
       
  8240 
       
  8241         if ( isNaN(xy[0]) ) { // in case of 'auto'
       
  8242             xy[0] = parseInt(Y_DOM.getStyle(node, 'left'), 10); // try inline
       
  8243             if ( isNaN(xy[0]) ) { // default to offset value
       
  8244                 xy[0] = (pos === 'relative') ? 0 : node.offsetLeft || 0;
       
  8245             }
       
  8246         } 
       
  8247 
       
  8248         if ( isNaN(xy[1]) ) { // in case of 'auto'
       
  8249             xy[1] = parseInt(Y_DOM.getStyle(node, 'top'), 10); // try inline
       
  8250             if ( isNaN(xy[1]) ) { // default to offset value
       
  8251                 xy[1] = (pos === 'relative') ? 0 : node.offsetTop || 0;
       
  8252             }
       
  8253         } 
       
  8254     }
       
  8255 
       
  8256     return xy;
       
  8257 
       
  8258 };
       
  8259 
       
  8260 Y_DOM.CUSTOM_STYLES.transform = {
       
  8261     set: function(node, val, style) {
       
  8262         style[TRANSFORM] = val;
       
  8263     },
       
  8264 
       
  8265     get: function(node, style) {
       
  8266         return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORM);
       
  8267     }
       
  8268 };
       
  8269 
       
  8270 Y_DOM.CUSTOM_STYLES.transformOrigin = {
       
  8271     set: function(node, val, style) {
       
  8272         style[TRANSFORMORIGIN] = val;
       
  8273     },
       
  8274 
       
  8275     get: function(node, style) {
       
  8276         return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORMORIGIN);
       
  8277     }
       
  8278 };
       
  8279 
       
  8280 
       
  8281 })(Y);
       
  8282 
       
  8283 
       
  8284 }, '@VERSION@', {"requires": ["dom-base", "color-base"]});
       
  8285 YUI.add('dom-style-ie', function (Y, NAME) {
       
  8286 
       
  8287 (function(Y) {
       
  8288 var HAS_LAYOUT = 'hasLayout',
       
  8289     PX = 'px',
       
  8290     FILTER = 'filter',
       
  8291     FILTERS = 'filters',
       
  8292     OPACITY = 'opacity',
       
  8293     AUTO = 'auto',
       
  8294 
       
  8295     BORDER_WIDTH = 'borderWidth',
       
  8296     BORDER_TOP_WIDTH = 'borderTopWidth',
       
  8297     BORDER_RIGHT_WIDTH = 'borderRightWidth',
       
  8298     BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
       
  8299     BORDER_LEFT_WIDTH = 'borderLeftWidth',
       
  8300     WIDTH = 'width',
       
  8301     HEIGHT = 'height',
       
  8302     TRANSPARENT = 'transparent',
       
  8303     VISIBLE = 'visible',
       
  8304     GET_COMPUTED_STYLE = 'getComputedStyle',
       
  8305     UNDEFINED = undefined,
       
  8306     documentElement = Y.config.doc.documentElement,
       
  8307 
       
  8308     testFeature = Y.Features.test,
       
  8309     addFeature = Y.Features.add,
       
  8310 
       
  8311     // TODO: unit-less lineHeight (e.g. 1.22)
       
  8312     re_unit = /^(\d[.\d]*)+(em|ex|px|gd|rem|vw|vh|vm|ch|mm|cm|in|pt|pc|deg|rad|ms|s|hz|khz|%){1}?/i,
       
  8313 
       
  8314     isIE8 = (Y.UA.ie >= 8),
       
  8315 
       
  8316     _getStyleObj = function(node) {
       
  8317         return node.currentStyle || node.style;
       
  8318     },
       
  8319 
       
  8320     ComputedStyle = {
       
  8321         CUSTOM_STYLES: {},
       
  8322 
       
  8323         get: function(el, property) {
       
  8324             var value = '',
       
  8325                 current;
       
  8326 
       
  8327             if (el) {
       
  8328                     current = _getStyleObj(el)[property];
       
  8329 
       
  8330                 if (property === OPACITY && Y.DOM.CUSTOM_STYLES[OPACITY]) {
       
  8331                     value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);        
       
  8332                 } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
       
  8333                     value = current;
       
  8334                 } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
       
  8335                     value = Y.DOM.IE.COMPUTED[property](el, property);
       
  8336                 } else if (re_unit.test(current)) { // convert to pixel
       
  8337                     value = ComputedStyle.getPixel(el, property) + PX;
       
  8338                 } else {
       
  8339                     value = current;
       
  8340                 }
       
  8341             }
       
  8342 
       
  8343             return value;
       
  8344         },
       
  8345 
       
  8346         sizeOffsets: {
       
  8347             width: ['Left', 'Right'],
       
  8348             height: ['Top', 'Bottom'],
       
  8349             top: ['Top'],
       
  8350             bottom: ['Bottom']
       
  8351         },
       
  8352 
       
  8353         getOffset: function(el, prop) {
       
  8354             var current = _getStyleObj(el)[prop],                     // value of "width", "top", etc.
       
  8355                 capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
       
  8356                 offset = 'offset' + capped,                             // "offsetWidth", "offsetTop", etc.
       
  8357                 pixel = 'pixel' + capped,                               // "pixelWidth", "pixelTop", etc.
       
  8358                 sizeOffsets = ComputedStyle.sizeOffsets[prop], 
       
  8359                 mode = el.ownerDocument.compatMode,
       
  8360                 value = '';
       
  8361 
       
  8362             // IE pixelWidth incorrect for percent
       
  8363             // manually compute by subtracting padding and border from offset size
       
  8364             // NOTE: clientWidth/Height (size minus border) is 0 when current === AUTO so offsetHeight is used
       
  8365             // reverting to auto from auto causes position stacking issues (old impl)
       
  8366             if (current === AUTO || current.indexOf('%') > -1) {
       
  8367                 value = el['offset' + capped];
       
  8368 
       
  8369                 if (mode !== 'BackCompat') {
       
  8370                     if (sizeOffsets[0]) {
       
  8371                         value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[0]);
       
  8372                         value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[0] + 'Width', 1);
       
  8373                     }
       
  8374 
       
  8375                     if (sizeOffsets[1]) {
       
  8376                         value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[1]);
       
  8377                         value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[1] + 'Width', 1);
       
  8378                     }
       
  8379                 }
       
  8380 
       
  8381             } else { // use style.pixelWidth, etc. to convert to pixels
       
  8382                 // need to map style.width to currentStyle (no currentStyle.pixelWidth)
       
  8383                 if (!el.style[pixel] && !el.style[prop]) {
       
  8384                     el.style[prop] = current;
       
  8385                 }
       
  8386                 value = el.style[pixel];
       
  8387                 
       
  8388             }
       
  8389             return value + PX;
       
  8390         },
       
  8391 
       
  8392         borderMap: {
       
  8393             thin: (isIE8) ? '1px' : '2px',
       
  8394             medium: (isIE8) ? '3px': '4px', 
       
  8395             thick: (isIE8) ? '5px' : '6px'
       
  8396         },
       
  8397 
       
  8398         getBorderWidth: function(el, property, omitUnit) {
       
  8399             var unit = omitUnit ? '' : PX,
       
  8400                 current = el.currentStyle[property];
       
  8401 
       
  8402             if (current.indexOf(PX) < 0) { // look up keywords if a border exists
       
  8403                 if (ComputedStyle.borderMap[current] &&
       
  8404                         el.currentStyle.borderStyle !== 'none') {
       
  8405                     current = ComputedStyle.borderMap[current];
       
  8406                 } else { // otherwise no border (default is "medium")
       
  8407                     current = 0;
       
  8408                 }
       
  8409             }
       
  8410             return (omitUnit) ? parseFloat(current) : current;
       
  8411         },
       
  8412 
       
  8413         getPixel: function(node, att) {
       
  8414             // use pixelRight to convert to px
       
  8415             var val = null,
       
  8416                 style = _getStyleObj(node),
       
  8417                 styleRight = style.right,
       
  8418                 current = style[att];
       
  8419 
       
  8420             node.style.right = current;
       
  8421             val = node.style.pixelRight;
       
  8422             node.style.right = styleRight; // revert
       
  8423 
       
  8424             return val;
       
  8425         },
       
  8426 
       
  8427         getMargin: function(node, att) {
       
  8428             var val,
       
  8429                 style = _getStyleObj(node);
       
  8430 
       
  8431             if (style[att] == AUTO) {
       
  8432                 val = 0;
       
  8433             } else {
       
  8434                 val = ComputedStyle.getPixel(node, att);
       
  8435             }
       
  8436             return val + PX;
       
  8437         },
       
  8438 
       
  8439         getVisibility: function(node, att) {
       
  8440             var current;
       
  8441             while ( (current = node.currentStyle) && current[att] == 'inherit') { // NOTE: assignment in test
       
  8442                 node = node.parentNode;
       
  8443             }
       
  8444             return (current) ? current[att] : VISIBLE;
       
  8445         },
       
  8446 
       
  8447         getColor: function(node, att) {
       
  8448             var current = _getStyleObj(node)[att];
       
  8449 
       
  8450             if (!current || current === TRANSPARENT) {
       
  8451                 Y.DOM.elementByAxis(node, 'parentNode', null, function(parent) {
       
  8452                     current = _getStyleObj(parent)[att];
       
  8453                     if (current && current !== TRANSPARENT) {
       
  8454                         node = parent;
       
  8455                         return true;
       
  8456                     }
       
  8457                 });
       
  8458             }
       
  8459 
       
  8460             return Y.Color.toRGB(current);
       
  8461         },
       
  8462 
       
  8463         getBorderColor: function(node, att) {
       
  8464             var current = _getStyleObj(node),
       
  8465                 val = current[att] || current.color;
       
  8466             return Y.Color.toRGB(Y.Color.toHex(val));
       
  8467         }
       
  8468     },
       
  8469 
       
  8470     //fontSize: getPixelFont,
       
  8471     IEComputed = {};
       
  8472 
       
  8473 addFeature('style', 'computedStyle', {
       
  8474     test: function() {
       
  8475         return 'getComputedStyle' in Y.config.win;
       
  8476     }
       
  8477 });
       
  8478 
       
  8479 addFeature('style', 'opacity', {
       
  8480     test: function() {
       
  8481         return 'opacity' in documentElement.style;
       
  8482     }
       
  8483 });
       
  8484 
       
  8485 addFeature('style', 'filter', {
       
  8486     test: function() {
       
  8487         return 'filters' in documentElement;
       
  8488     }
       
  8489 });
       
  8490 
       
  8491 // use alpha filter for IE opacity
       
  8492 if (!testFeature('style', 'opacity') && testFeature('style', 'filter')) {
       
  8493     Y.DOM.CUSTOM_STYLES[OPACITY] = {
       
  8494         get: function(node) {
       
  8495             var val = 100;
       
  8496             try { // will error if no DXImageTransform
       
  8497                 val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
       
  8498 
       
  8499             } catch(e) {
       
  8500                 try { // make sure its in the document
       
  8501                     val = node[FILTERS]('alpha')[OPACITY];
       
  8502                 } catch(err) {
       
  8503                 }
       
  8504             }
       
  8505             return val / 100;
       
  8506         },
       
  8507 
       
  8508         set: function(node, val, style) {
       
  8509             var current,
       
  8510                 styleObj = _getStyleObj(node),
       
  8511                 currentFilter = styleObj[FILTER];
       
  8512 
       
  8513             style = style || node.style;
       
  8514             if (val === '') { // normalize inline style behavior
       
  8515                 current = (OPACITY in styleObj) ? styleObj[OPACITY] : 1; // revert to original opacity
       
  8516                 val = current;
       
  8517             }
       
  8518 
       
  8519             if (typeof currentFilter == 'string') { // in case not appended
       
  8520                 style[FILTER] = currentFilter.replace(/alpha([^)]*\))/gi, '') +
       
  8521                         ((val < 1) ? 'alpha(' + OPACITY + '=' + val * 100 + ')' : '');
       
  8522 
       
  8523                 if (!style[FILTER]) {
       
  8524                     style.removeAttribute(FILTER);
       
  8525                 }
       
  8526 
       
  8527                 if (!styleObj[HAS_LAYOUT]) {
       
  8528                     style.zoom = 1; // needs layout 
       
  8529                 }
       
  8530             }
       
  8531         }
       
  8532     };
       
  8533 }
       
  8534 
       
  8535 try {
       
  8536     Y.config.doc.createElement('div').style.height = '-1px';
       
  8537 } catch(e) { // IE throws error on invalid style set; trap common cases
       
  8538     Y.DOM.CUSTOM_STYLES.height = {
       
  8539         set: function(node, val, style) {
       
  8540             var floatVal = parseFloat(val);
       
  8541             if (floatVal >= 0 || val === 'auto' || val === '') {
       
  8542                 style.height = val;
       
  8543             } else {
       
  8544             }
       
  8545         }
       
  8546     };
       
  8547 
       
  8548     Y.DOM.CUSTOM_STYLES.width = {
       
  8549         set: function(node, val, style) {
       
  8550             var floatVal = parseFloat(val);
       
  8551             if (floatVal >= 0 || val === 'auto' || val === '') {
       
  8552                 style.width = val;
       
  8553             } else {
       
  8554             }
       
  8555         }
       
  8556     };
       
  8557 }
       
  8558 
       
  8559 if (!testFeature('style', 'computedStyle')) {
       
  8560     // TODO: top, right, bottom, left
       
  8561     IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
       
  8562 
       
  8563     IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
       
  8564 
       
  8565     IEComputed[BORDER_WIDTH] = IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
       
  8566             IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
       
  8567             ComputedStyle.getBorderWidth;
       
  8568 
       
  8569     IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
       
  8570             IEComputed.marginLeft = ComputedStyle.getMargin;
       
  8571 
       
  8572     IEComputed.visibility = ComputedStyle.getVisibility;
       
  8573     IEComputed.borderColor = IEComputed.borderTopColor =
       
  8574             IEComputed.borderRightColor = IEComputed.borderBottomColor =
       
  8575             IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
       
  8576 
       
  8577     Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get; 
       
  8578 
       
  8579     Y.namespace('DOM.IE');
       
  8580     Y.DOM.IE.COMPUTED = IEComputed;
       
  8581     Y.DOM.IE.ComputedStyle = ComputedStyle;
       
  8582 }
       
  8583 
       
  8584 })(Y);
       
  8585 
       
  8586 
       
  8587 }, '@VERSION@', {"requires": ["dom-style"]});
       
  8588 YUI.add('dom-screen', function (Y, NAME) {
       
  8589 
       
  8590 (function(Y) {
       
  8591 
       
  8592 /**
       
  8593  * Adds position and region management functionality to DOM.
       
  8594  * @module dom
       
  8595  * @submodule dom-screen
       
  8596  * @for DOM
       
  8597  */
       
  8598 
       
  8599 var DOCUMENT_ELEMENT = 'documentElement',
       
  8600     COMPAT_MODE = 'compatMode',
       
  8601     POSITION = 'position',
       
  8602     FIXED = 'fixed',
       
  8603     RELATIVE = 'relative',
       
  8604     LEFT = 'left',
       
  8605     TOP = 'top',
       
  8606     _BACK_COMPAT = 'BackCompat',
       
  8607     MEDIUM = 'medium',
       
  8608     BORDER_LEFT_WIDTH = 'borderLeftWidth',
       
  8609     BORDER_TOP_WIDTH = 'borderTopWidth',
       
  8610     GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
       
  8611     GET_COMPUTED_STYLE = 'getComputedStyle',
       
  8612 
       
  8613     Y_DOM = Y.DOM,
       
  8614 
       
  8615     // TODO: how about thead/tbody/tfoot/tr?
       
  8616     // TODO: does caption matter?
       
  8617     RE_TABLE = /^t(?:able|d|h)$/i,
       
  8618 
       
  8619     SCROLL_NODE;
       
  8620 
       
  8621 if (Y.UA.ie) {
       
  8622     if (Y.config.doc[COMPAT_MODE] !== 'BackCompat') {
       
  8623         SCROLL_NODE = DOCUMENT_ELEMENT; 
       
  8624     } else {
       
  8625         SCROLL_NODE = 'body';
       
  8626     }
       
  8627 }
       
  8628 
       
  8629 Y.mix(Y_DOM, {
       
  8630     /**
       
  8631      * Returns the inner height of the viewport (exludes scrollbar). 
       
  8632      * @method winHeight
       
  8633      * @return {Number} The current height of the viewport.
       
  8634      */
       
  8635     winHeight: function(node) {
       
  8636         var h = Y_DOM._getWinSize(node).height;
       
  8637         return h;
       
  8638     },
       
  8639 
       
  8640     /**
       
  8641      * Returns the inner width of the viewport (exludes scrollbar). 
       
  8642      * @method winWidth
       
  8643      * @return {Number} The current width of the viewport.
       
  8644      */
       
  8645     winWidth: function(node) {
       
  8646         var w = Y_DOM._getWinSize(node).width;
       
  8647         return w;
       
  8648     },
       
  8649 
       
  8650     /**
       
  8651      * Document height 
       
  8652      * @method docHeight
       
  8653      * @return {Number} The current height of the document.
       
  8654      */
       
  8655     docHeight:  function(node) {
       
  8656         var h = Y_DOM._getDocSize(node).height;
       
  8657         return Math.max(h, Y_DOM._getWinSize(node).height);
       
  8658     },
       
  8659 
       
  8660     /**
       
  8661      * Document width 
       
  8662      * @method docWidth
       
  8663      * @return {Number} The current width of the document.
       
  8664      */
       
  8665     docWidth:  function(node) {
       
  8666         var w = Y_DOM._getDocSize(node).width;
       
  8667         return Math.max(w, Y_DOM._getWinSize(node).width);
       
  8668     },
       
  8669 
       
  8670     /**
       
  8671      * Amount page has been scroll horizontally 
       
  8672      * @method docScrollX
       
  8673      * @return {Number} The current amount the screen is scrolled horizontally.
       
  8674      */
       
  8675     docScrollX: function(node, doc) {
       
  8676         doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
       
  8677         var dv = doc.defaultView,
       
  8678             pageOffset = (dv) ? dv.pageXOffset : 0;
       
  8679         return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, pageOffset);
       
  8680     },
       
  8681 
       
  8682     /**
       
  8683      * Amount page has been scroll vertically 
       
  8684      * @method docScrollY
       
  8685      * @return {Number} The current amount the screen is scrolled vertically.
       
  8686      */
       
  8687     docScrollY:  function(node, doc) {
       
  8688         doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
       
  8689         var dv = doc.defaultView,
       
  8690             pageOffset = (dv) ? dv.pageYOffset : 0;
       
  8691         return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, pageOffset);
       
  8692     },
       
  8693 
       
  8694     /**
       
  8695      * Gets the current position of an element based on page coordinates. 
       
  8696      * Element must be part of the DOM tree to have page coordinates
       
  8697      * (display:none or elements not appended return false).
       
  8698      * @method getXY
       
  8699      * @param element The target element
       
  8700      * @return {Array} The XY position of the element
       
  8701 
       
  8702      TODO: test inDocument/display?
       
  8703      */
       
  8704     getXY: function() {
       
  8705         if (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
       
  8706             return function(node) {
       
  8707                 var xy = null,
       
  8708                     scrollLeft,
       
  8709                     scrollTop,
       
  8710                     mode,
       
  8711                     box,
       
  8712                     offX,
       
  8713                     offY,
       
  8714                     doc,
       
  8715                     win,
       
  8716                     inDoc,
       
  8717                     rootNode;
       
  8718 
       
  8719                 if (node && node.tagName) {
       
  8720                     doc = node.ownerDocument;
       
  8721                     mode = doc[COMPAT_MODE];
       
  8722 
       
  8723                     if (mode !== _BACK_COMPAT) {
       
  8724                         rootNode = doc[DOCUMENT_ELEMENT];
       
  8725                     } else {
       
  8726                         rootNode = doc.body;
       
  8727                     }
       
  8728 
       
  8729                     // inline inDoc check for perf
       
  8730                     if (rootNode.contains) {
       
  8731                         inDoc = rootNode.contains(node); 
       
  8732                     } else {
       
  8733                         inDoc = Y.DOM.contains(rootNode, node);
       
  8734                     }
       
  8735 
       
  8736                     if (inDoc) {
       
  8737                         win = doc.defaultView;
       
  8738 
       
  8739                         // inline scroll calc for perf
       
  8740                         if (win && 'pageXOffset' in win) {
       
  8741                             scrollLeft = win.pageXOffset;
       
  8742                             scrollTop = win.pageYOffset;
       
  8743                         } else {
       
  8744                             scrollLeft = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc);
       
  8745                             scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop : Y_DOM.docScrollY(node, doc);
       
  8746                         }
       
  8747 
       
  8748                         if (Y.UA.ie) { // IE < 8, quirks, or compatMode
       
  8749                             if (!doc.documentMode || doc.documentMode < 8 || mode === _BACK_COMPAT) {
       
  8750                                 offX = rootNode.clientLeft;
       
  8751                                 offY = rootNode.clientTop;
       
  8752                             }
       
  8753                         }
       
  8754                         box = node[GET_BOUNDING_CLIENT_RECT]();
       
  8755                         xy = [box.left, box.top];
       
  8756 
       
  8757                         if (offX || offY) {
       
  8758                                 xy[0] -= offX;
       
  8759                                 xy[1] -= offY;
       
  8760                             
       
  8761                         }
       
  8762                         if ((scrollTop || scrollLeft)) {
       
  8763                             if (!Y.UA.ios || (Y.UA.ios >= 4.2)) {
       
  8764                                 xy[0] += scrollLeft;
       
  8765                                 xy[1] += scrollTop;
       
  8766                             }
       
  8767                             
       
  8768                         }
       
  8769                     } else {
       
  8770                         xy = Y_DOM._getOffset(node);       
       
  8771                     }
       
  8772                 }
       
  8773                 return xy;                   
       
  8774             };
       
  8775         } else {
       
  8776             return function(node) { // manually calculate by crawling up offsetParents
       
  8777                 //Calculate the Top and Left border sizes (assumes pixels)
       
  8778                 var xy = null,
       
  8779                     doc,
       
  8780                     parentNode,
       
  8781                     bCheck,
       
  8782                     scrollTop,
       
  8783                     scrollLeft;
       
  8784 
       
  8785                 if (node) {
       
  8786                     if (Y_DOM.inDoc(node)) {
       
  8787                         xy = [node.offsetLeft, node.offsetTop];
       
  8788                         doc = node.ownerDocument;
       
  8789                         parentNode = node;
       
  8790                         // TODO: refactor with !! or just falsey
       
  8791                         bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
       
  8792 
       
  8793                         // TODO: worth refactoring for TOP/LEFT only?
       
  8794                         while ((parentNode = parentNode.offsetParent)) {
       
  8795                             xy[0] += parentNode.offsetLeft;
       
  8796                             xy[1] += parentNode.offsetTop;
       
  8797                             if (bCheck) {
       
  8798                                 xy = Y_DOM._calcBorders(parentNode, xy);
       
  8799                             }
       
  8800                         }
       
  8801 
       
  8802                         // account for any scrolled ancestors
       
  8803                         if (Y_DOM.getStyle(node, POSITION) != FIXED) {
       
  8804                             parentNode = node;
       
  8805 
       
  8806                             while ((parentNode = parentNode.parentNode)) {
       
  8807                                 scrollTop = parentNode.scrollTop;
       
  8808                                 scrollLeft = parentNode.scrollLeft;
       
  8809 
       
  8810                                 //Firefox does something funky with borders when overflow is not visible.
       
  8811                                 if (Y.UA.gecko && (Y_DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
       
  8812                                         xy = Y_DOM._calcBorders(parentNode, xy);
       
  8813                                 }
       
  8814                                 
       
  8815 
       
  8816                                 if (scrollTop || scrollLeft) {
       
  8817                                     xy[0] -= scrollLeft;
       
  8818                                     xy[1] -= scrollTop;
       
  8819                                 }
       
  8820                             }
       
  8821                             xy[0] += Y_DOM.docScrollX(node, doc);
       
  8822                             xy[1] += Y_DOM.docScrollY(node, doc);
       
  8823 
       
  8824                         } else {
       
  8825                             //Fix FIXED position -- add scrollbars
       
  8826                             xy[0] += Y_DOM.docScrollX(node, doc);
       
  8827                             xy[1] += Y_DOM.docScrollY(node, doc);
       
  8828                         }
       
  8829                     } else {
       
  8830                         xy = Y_DOM._getOffset(node);
       
  8831                     }
       
  8832                 }
       
  8833 
       
  8834                 return xy;                
       
  8835             };
       
  8836         }
       
  8837     }(),// NOTE: Executing for loadtime branching
       
  8838 
       
  8839     /**
       
  8840     Gets the width of vertical scrollbars on overflowed containers in the body
       
  8841     content.
       
  8842 
       
  8843     @method getScrollbarWidth
       
  8844     @return {Number} Pixel width of a scrollbar in the current browser
       
  8845     **/
       
  8846     getScrollbarWidth: Y.cached(function () {
       
  8847         var doc      = Y.config.doc,
       
  8848             testNode = doc.createElement('div'),
       
  8849             body     = doc.getElementsByTagName('body')[0],
       
  8850             // 0.1 because cached doesn't support falsy refetch values
       
  8851             width    = 0.1;
       
  8852             
       
  8853         if (body) {
       
  8854             testNode.style.cssText = "position:absolute;visibility:hidden;overflow:scroll;width:20px;";
       
  8855             testNode.appendChild(doc.createElement('p')).style.height = '1px';
       
  8856             body.insertBefore(testNode, body.firstChild);
       
  8857             width = testNode.offsetWidth - testNode.clientWidth;
       
  8858 
       
  8859             body.removeChild(testNode);
       
  8860         }
       
  8861 
       
  8862         return width;
       
  8863     }, null, 0.1),
       
  8864 
       
  8865     /**
       
  8866      * Gets the current X position of an element based on page coordinates. 
       
  8867      * Element must be part of the DOM tree to have page coordinates
       
  8868      * (display:none or elements not appended return false).
       
  8869      * @method getX
       
  8870      * @param element The target element
       
  8871      * @return {Number} The X position of the element
       
  8872      */
       
  8873 
       
  8874     getX: function(node) {
       
  8875         return Y_DOM.getXY(node)[0];
       
  8876     },
       
  8877 
       
  8878     /**
       
  8879      * Gets the current Y position of an element based on page coordinates. 
       
  8880      * Element must be part of the DOM tree to have page coordinates
       
  8881      * (display:none or elements not appended return false).
       
  8882      * @method getY
       
  8883      * @param element The target element
       
  8884      * @return {Number} The Y position of the element
       
  8885      */
       
  8886 
       
  8887     getY: function(node) {
       
  8888         return Y_DOM.getXY(node)[1];
       
  8889     },
       
  8890 
       
  8891     /**
       
  8892      * Set the position of an html element in page coordinates.
       
  8893      * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
       
  8894      * @method setXY
       
  8895      * @param element The target element
       
  8896      * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
       
  8897      * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
       
  8898      */
       
  8899     setXY: function(node, xy, noRetry) {
       
  8900         var setStyle = Y_DOM.setStyle,
       
  8901             pos,
       
  8902             delta,
       
  8903             newXY,
       
  8904             currentXY;
       
  8905 
       
  8906         if (node && xy) {
       
  8907             pos = Y_DOM.getStyle(node, POSITION);
       
  8908 
       
  8909             delta = Y_DOM._getOffset(node);       
       
  8910             if (pos == 'static') { // default to relative
       
  8911                 pos = RELATIVE;
       
  8912                 setStyle(node, POSITION, pos);
       
  8913             }
       
  8914             currentXY = Y_DOM.getXY(node);
       
  8915 
       
  8916             if (xy[0] !== null) {
       
  8917                 setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
       
  8918             }
       
  8919 
       
  8920             if (xy[1] !== null) {
       
  8921                 setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
       
  8922             }
       
  8923 
       
  8924             if (!noRetry) {
       
  8925                 newXY = Y_DOM.getXY(node);
       
  8926                 if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) {
       
  8927                     Y_DOM.setXY(node, xy, true); 
       
  8928                 }
       
  8929             }
       
  8930           
       
  8931         } else {
       
  8932         }
       
  8933     },
       
  8934 
       
  8935     /**
       
  8936      * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
       
  8937      * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
       
  8938      * @method setX
       
  8939      * @param element The target element
       
  8940      * @param {Number} x The X values for new position (coordinates are page-based)
       
  8941      */
       
  8942     setX: function(node, x) {
       
  8943         return Y_DOM.setXY(node, [x, null]);
       
  8944     },
       
  8945 
       
  8946     /**
       
  8947      * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
       
  8948      * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
       
  8949      * @method setY
       
  8950      * @param element The target element
       
  8951      * @param {Number} y The Y values for new position (coordinates are page-based)
       
  8952      */
       
  8953     setY: function(node, y) {
       
  8954         return Y_DOM.setXY(node, [null, y]);
       
  8955     },
       
  8956 
       
  8957     /**
       
  8958      * @method swapXY
       
  8959      * @description Swap the xy position with another node
       
  8960      * @param {Node} node The node to swap with
       
  8961      * @param {Node} otherNode The other node to swap with
       
  8962      * @return {Node}
       
  8963      */
       
  8964     swapXY: function(node, otherNode) {
       
  8965         var xy = Y_DOM.getXY(node);
       
  8966         Y_DOM.setXY(node, Y_DOM.getXY(otherNode));
       
  8967         Y_DOM.setXY(otherNode, xy);
       
  8968     },
       
  8969 
       
  8970     _calcBorders: function(node, xy2) {
       
  8971         var t = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
       
  8972             l = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
       
  8973         if (Y.UA.gecko) {
       
  8974             if (RE_TABLE.test(node.tagName)) {
       
  8975                 t = 0;
       
  8976                 l = 0;
       
  8977             }
       
  8978         }
       
  8979         xy2[0] += l;
       
  8980         xy2[1] += t;
       
  8981         return xy2;
       
  8982     },
       
  8983 
       
  8984     _getWinSize: function(node, doc) {
       
  8985         doc  = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc;
       
  8986         var win = doc.defaultView || doc.parentWindow,
       
  8987             mode = doc[COMPAT_MODE],
       
  8988             h = win.innerHeight,
       
  8989             w = win.innerWidth,
       
  8990             root = doc[DOCUMENT_ELEMENT];
       
  8991 
       
  8992         if ( mode && !Y.UA.opera ) { // IE, Gecko
       
  8993             if (mode != 'CSS1Compat') { // Quirks
       
  8994                 root = doc.body; 
       
  8995             }
       
  8996             h = root.clientHeight;
       
  8997             w = root.clientWidth;
       
  8998         }
       
  8999         return { height: h, width: w };
       
  9000     },
       
  9001 
       
  9002     _getDocSize: function(node) {
       
  9003         var doc = (node) ? Y_DOM._getDoc(node) : Y.config.doc,
       
  9004             root = doc[DOCUMENT_ELEMENT];
       
  9005 
       
  9006         if (doc[COMPAT_MODE] != 'CSS1Compat') {
       
  9007             root = doc.body;
       
  9008         }
       
  9009 
       
  9010         return { height: root.scrollHeight, width: root.scrollWidth };
       
  9011     }
       
  9012 });
       
  9013 
       
  9014 })(Y);
       
  9015 (function(Y) {
       
  9016 var TOP = 'top',
       
  9017     RIGHT = 'right',
       
  9018     BOTTOM = 'bottom',
       
  9019     LEFT = 'left',
       
  9020 
       
  9021     getOffsets = function(r1, r2) {
       
  9022         var t = Math.max(r1[TOP], r2[TOP]),
       
  9023             r = Math.min(r1[RIGHT], r2[RIGHT]),
       
  9024             b = Math.min(r1[BOTTOM], r2[BOTTOM]),
       
  9025             l = Math.max(r1[LEFT], r2[LEFT]),
       
  9026             ret = {};
       
  9027         
       
  9028         ret[TOP] = t;
       
  9029         ret[RIGHT] = r;
       
  9030         ret[BOTTOM] = b;
       
  9031         ret[LEFT] = l;
       
  9032         return ret;
       
  9033     },
       
  9034 
       
  9035     DOM = Y.DOM;
       
  9036 
       
  9037 Y.mix(DOM, {
       
  9038     /**
       
  9039      * Returns an Object literal containing the following about this element: (top, right, bottom, left)
       
  9040      * @for DOM
       
  9041      * @method region
       
  9042      * @param {HTMLElement} element The DOM element. 
       
  9043      * @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
       
  9044      */
       
  9045     region: function(node) {
       
  9046         var xy = DOM.getXY(node),
       
  9047             ret = false;
       
  9048         
       
  9049         if (node && xy) {
       
  9050             ret = DOM._getRegion(
       
  9051                 xy[1], // top
       
  9052                 xy[0] + node.offsetWidth, // right
       
  9053                 xy[1] + node.offsetHeight, // bottom
       
  9054                 xy[0] // left
       
  9055             );
       
  9056         }
       
  9057 
       
  9058         return ret;
       
  9059     },
       
  9060 
       
  9061     /**
       
  9062      * Find the intersect information for the passed nodes.
       
  9063      * @method intersect
       
  9064      * @for DOM
       
  9065      * @param {HTMLElement} element The first element 
       
  9066      * @param {HTMLElement | Object} element2 The element or region to check the interect with
       
  9067      * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance e.g. DragDrop)
       
  9068      * @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
       
  9069      */
       
  9070     intersect: function(node, node2, altRegion) {
       
  9071         var r = altRegion || DOM.region(node), region = {},
       
  9072             n = node2,
       
  9073             off;
       
  9074 
       
  9075         if (n.tagName) {
       
  9076             region = DOM.region(n);
       
  9077         } else if (Y.Lang.isObject(node2)) {
       
  9078             region = node2;
       
  9079         } else {
       
  9080             return false;
       
  9081         }
       
  9082         
       
  9083         off = getOffsets(region, r);
       
  9084         return {
       
  9085             top: off[TOP],
       
  9086             right: off[RIGHT],
       
  9087             bottom: off[BOTTOM],
       
  9088             left: off[LEFT],
       
  9089             area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
       
  9090             yoff: ((off[BOTTOM] - off[TOP])),
       
  9091             xoff: (off[RIGHT] - off[LEFT]),
       
  9092             inRegion: DOM.inRegion(node, node2, false, altRegion)
       
  9093         };
       
  9094         
       
  9095     },
       
  9096     /**
       
  9097      * Check if any part of this node is in the passed region
       
  9098      * @method inRegion
       
  9099      * @for DOM
       
  9100      * @param {Object} node The node to get the region from
       
  9101      * @param {Object} node2 The second node to get the region from or an Object literal of the region
       
  9102      * @param {Boolean} all Should all of the node be inside the region
       
  9103      * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop)
       
  9104      * @return {Boolean} True if in region, false if not.
       
  9105      */
       
  9106     inRegion: function(node, node2, all, altRegion) {
       
  9107         var region = {},
       
  9108             r = altRegion || DOM.region(node),
       
  9109             n = node2,
       
  9110             off;
       
  9111 
       
  9112         if (n.tagName) {
       
  9113             region = DOM.region(n);
       
  9114         } else if (Y.Lang.isObject(node2)) {
       
  9115             region = node2;
       
  9116         } else {
       
  9117             return false;
       
  9118         }
       
  9119             
       
  9120         if (all) {
       
  9121             return (
       
  9122                 r[LEFT]   >= region[LEFT]   &&
       
  9123                 r[RIGHT]  <= region[RIGHT]  && 
       
  9124                 r[TOP]    >= region[TOP]    && 
       
  9125                 r[BOTTOM] <= region[BOTTOM]  );
       
  9126         } else {
       
  9127             off = getOffsets(region, r);
       
  9128             if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
       
  9129                 return true;
       
  9130             } else {
       
  9131                 return false;
       
  9132             }
       
  9133             
       
  9134         }
       
  9135     },
       
  9136 
       
  9137     /**
       
  9138      * Check if any part of this element is in the viewport
       
  9139      * @method inViewportRegion
       
  9140      * @for DOM
       
  9141      * @param {HTMLElement} element The DOM element. 
       
  9142      * @param {Boolean} all Should all of the node be inside the region
       
  9143      * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop)
       
  9144      * @return {Boolean} True if in region, false if not.
       
  9145      */
       
  9146     inViewportRegion: function(node, all, altRegion) {
       
  9147         return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
       
  9148             
       
  9149     },
       
  9150 
       
  9151     _getRegion: function(t, r, b, l) {
       
  9152         var region = {};
       
  9153 
       
  9154         region[TOP] = region[1] = t;
       
  9155         region[LEFT] = region[0] = l;
       
  9156         region[BOTTOM] = b;
       
  9157         region[RIGHT] = r;
       
  9158         region.width = region[RIGHT] - region[LEFT];
       
  9159         region.height = region[BOTTOM] - region[TOP];
       
  9160 
       
  9161         return region;
       
  9162     },
       
  9163 
       
  9164     /**
       
  9165      * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
       
  9166      * @method viewportRegion
       
  9167      * @for DOM
       
  9168      * @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
       
  9169      */
       
  9170     viewportRegion: function(node) {
       
  9171         node = node || Y.config.doc.documentElement;
       
  9172         var ret = false,
       
  9173             scrollX,
       
  9174             scrollY;
       
  9175 
       
  9176         if (node) {
       
  9177             scrollX = DOM.docScrollX(node);
       
  9178             scrollY = DOM.docScrollY(node);
       
  9179 
       
  9180             ret = DOM._getRegion(scrollY, // top
       
  9181                 DOM.winWidth(node) + scrollX, // right
       
  9182                 scrollY + DOM.winHeight(node), // bottom
       
  9183                 scrollX); // left
       
  9184         }
       
  9185 
       
  9186         return ret;
       
  9187     }
       
  9188 });
       
  9189 })(Y);
       
  9190 
       
  9191 
       
  9192 }, '@VERSION@', {"requires": ["dom-base", "dom-style"]});
       
  9193 YUI.add('selector-native', function (Y, NAME) {
       
  9194 
       
  9195 (function(Y) {
       
  9196 /**
       
  9197  * The selector-native module provides support for native querySelector
       
  9198  * @module dom
       
  9199  * @submodule selector-native
       
  9200  * @for Selector
       
  9201  */
       
  9202 
       
  9203 /**
       
  9204  * Provides support for using CSS selectors to query the DOM 
       
  9205  * @class Selector 
       
  9206  * @static
       
  9207  * @for Selector
       
  9208  */
       
  9209 
       
  9210 Y.namespace('Selector'); // allow native module to standalone
       
  9211 
       
  9212 var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
       
  9213     OWNER_DOCUMENT = 'ownerDocument';
       
  9214 
       
  9215 var Selector = {
       
  9216     _types: {
       
  9217         esc: {
       
  9218             token: '\uE000',
       
  9219             re: /\\[:\[\]\(\)#\.\'\>+~"]/gi
       
  9220         },
       
  9221 
       
  9222         attr: {
       
  9223             token: '\uE001',
       
  9224             re: /(\[[^\]]*\])/g
       
  9225         },
       
  9226 
       
  9227         pseudo: {
       
  9228             token: '\uE002',
       
  9229             re: /(\([^\)]*\))/g
       
  9230         }
       
  9231     },
       
  9232 
       
  9233     useNative: true,
       
  9234 
       
  9235     _escapeId: function(id) {
       
  9236         if (id) {
       
  9237             id = id.replace(/([:\[\]\(\)#\.'<>+~"])/g,'\\$1');
       
  9238         }
       
  9239         return id;
       
  9240     },
       
  9241 
       
  9242     _compare: ('sourceIndex' in Y.config.doc.documentElement) ?
       
  9243         function(nodeA, nodeB) {
       
  9244             var a = nodeA.sourceIndex,
       
  9245                 b = nodeB.sourceIndex;
       
  9246 
       
  9247             if (a === b) {
       
  9248                 return 0;
       
  9249             } else if (a > b) {
       
  9250                 return 1;
       
  9251             }
       
  9252 
       
  9253             return -1;
       
  9254 
       
  9255         } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ?
       
  9256         function(nodeA, nodeB) {
       
  9257             if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
       
  9258                 return -1;
       
  9259             } else {
       
  9260                 return 1;
       
  9261             }
       
  9262         } :
       
  9263         function(nodeA, nodeB) {
       
  9264             var rangeA, rangeB, compare;
       
  9265             if (nodeA && nodeB) {
       
  9266                 rangeA = nodeA[OWNER_DOCUMENT].createRange();
       
  9267                 rangeA.setStart(nodeA, 0);
       
  9268                 rangeB = nodeB[OWNER_DOCUMENT].createRange();
       
  9269                 rangeB.setStart(nodeB, 0);
       
  9270                 compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END
       
  9271             }
       
  9272 
       
  9273             return compare;
       
  9274         
       
  9275     }),
       
  9276 
       
  9277     _sort: function(nodes) {
       
  9278         if (nodes) {
       
  9279             nodes = Y.Array(nodes, 0, true);
       
  9280             if (nodes.sort) {
       
  9281                 nodes.sort(Selector._compare);
       
  9282             }
       
  9283         }
       
  9284 
       
  9285         return nodes;
       
  9286     },
       
  9287 
       
  9288     _deDupe: function(nodes) {
       
  9289         var ret = [],
       
  9290             i, node;
       
  9291 
       
  9292         for (i = 0; (node = nodes[i++]);) {
       
  9293             if (!node._found) {
       
  9294                 ret[ret.length] = node;
       
  9295                 node._found = true;
       
  9296             }
       
  9297         }
       
  9298 
       
  9299         for (i = 0; (node = ret[i++]);) {
       
  9300             node._found = null;
       
  9301             node.removeAttribute('_found');
       
  9302         }
       
  9303 
       
  9304         return ret;
       
  9305     },
       
  9306 
       
  9307     /**
       
  9308      * Retrieves a set of nodes based on a given CSS selector. 
       
  9309      * @method query
       
  9310      *
       
  9311      * @param {string} selector The CSS Selector to test the node against.
       
  9312      * @param {HTMLElement} root optional An HTMLElement to start the query from. Defaults to Y.config.doc
       
  9313      * @param {Boolean} firstOnly optional Whether or not to return only the first match.
       
  9314      * @return {Array} An array of nodes that match the given selector.
       
  9315      * @static
       
  9316      */
       
  9317     query: function(selector, root, firstOnly, skipNative) {
       
  9318         root = root || Y.config.doc;
       
  9319         var ret = [],
       
  9320             useNative = (Y.Selector.useNative && Y.config.doc.querySelector && !skipNative),
       
  9321             queries = [[selector, root]],
       
  9322             query,
       
  9323             result,
       
  9324             i,
       
  9325             fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery;
       
  9326 
       
  9327         if (selector && fn) {
       
  9328             // split group into seperate queries
       
  9329             if (!skipNative && // already done if skipping
       
  9330                     (!useNative || root.tagName)) { // split native when element scoping is needed
       
  9331                 queries = Selector._splitQueries(selector, root);
       
  9332             }
       
  9333 
       
  9334             for (i = 0; (query = queries[i++]);) {
       
  9335                 result = fn(query[0], query[1], firstOnly);
       
  9336                 if (!firstOnly) { // coerce DOM Collection to Array
       
  9337                     result = Y.Array(result, 0, true);
       
  9338                 }
       
  9339                 if (result) {
       
  9340                     ret = ret.concat(result);
       
  9341                 }
       
  9342             }
       
  9343 
       
  9344             if (queries.length > 1) { // remove dupes and sort by doc order 
       
  9345                 ret = Selector._sort(Selector._deDupe(ret));
       
  9346             }
       
  9347         }
       
  9348 
       
  9349         return (firstOnly) ? (ret[0] || null) : ret;
       
  9350 
       
  9351     },
       
  9352 
       
  9353     _replaceSelector: function(selector) {
       
  9354         var esc = Y.Selector._parse('esc', selector), // pull escaped colon, brackets, etc. 
       
  9355             attrs,
       
  9356             pseudos;
       
  9357 
       
  9358         // first replace escaped chars, which could be present in attrs or pseudos
       
  9359         selector = Y.Selector._replace('esc', selector);
       
  9360 
       
  9361         // then replace pseudos before attrs to avoid replacing :not([foo])
       
  9362         pseudos = Y.Selector._parse('pseudo', selector);
       
  9363         selector = Selector._replace('pseudo', selector);
       
  9364 
       
  9365         attrs = Y.Selector._parse('attr', selector);
       
  9366         selector = Y.Selector._replace('attr', selector);
       
  9367 
       
  9368         return {
       
  9369             esc: esc,
       
  9370             attrs: attrs,
       
  9371             pseudos: pseudos,
       
  9372             selector: selector
       
  9373         };
       
  9374     },
       
  9375 
       
  9376     _restoreSelector: function(replaced) {
       
  9377         var selector = replaced.selector;
       
  9378         selector = Y.Selector._restore('attr', selector, replaced.attrs);
       
  9379         selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
       
  9380         selector = Y.Selector._restore('esc', selector, replaced.esc);
       
  9381         return selector;
       
  9382     },
       
  9383 
       
  9384     _replaceCommas: function(selector) {
       
  9385         var replaced = Y.Selector._replaceSelector(selector),
       
  9386             selector = replaced.selector;
       
  9387 
       
  9388         if (selector) {
       
  9389             selector = selector.replace(/,/g, '\uE007');
       
  9390             replaced.selector = selector;
       
  9391             selector = Y.Selector._restoreSelector(replaced);
       
  9392         }
       
  9393         return selector;
       
  9394     },
       
  9395 
       
  9396     // allows element scoped queries to begin with combinator
       
  9397     // e.g. query('> p', document.body) === query('body > p')
       
  9398     _splitQueries: function(selector, node) {
       
  9399         if (selector.indexOf(',') > -1) {
       
  9400             selector = Y.Selector._replaceCommas(selector);
       
  9401         }
       
  9402 
       
  9403         var groups = selector.split('\uE007'), // split on replaced comma token
       
  9404             queries = [],
       
  9405             prefix = '',
       
  9406             id,
       
  9407             i,
       
  9408             len;
       
  9409 
       
  9410         if (node) {
       
  9411             // enforce for element scoping
       
  9412             if (node.nodeType === 1) { // Elements only
       
  9413                 id = Y.Selector._escapeId(Y.DOM.getId(node));
       
  9414 
       
  9415                 if (!id) {
       
  9416                     id = Y.guid();
       
  9417                     Y.DOM.setId(node, id);
       
  9418                 }
       
  9419             
       
  9420                 prefix = '[id="' + id + '"] ';
       
  9421             }
       
  9422 
       
  9423             for (i = 0, len = groups.length; i < len; ++i) {
       
  9424                 selector =  prefix + groups[i];
       
  9425                 queries.push([selector, node]);
       
  9426             }
       
  9427         }
       
  9428 
       
  9429         return queries;
       
  9430     },
       
  9431 
       
  9432     _nativeQuery: function(selector, root, one) {
       
  9433         if (Y.UA.webkit && selector.indexOf(':checked') > -1 &&
       
  9434                 (Y.Selector.pseudos && Y.Selector.pseudos.checked)) { // webkit (chrome, safari) fails to pick up "selected"  with "checked"
       
  9435             return Y.Selector.query(selector, root, one, true); // redo with skipNative true to try brute query
       
  9436         }
       
  9437         try {
       
  9438             return root['querySelector' + (one ? '' : 'All')](selector);
       
  9439         } catch(e) { // fallback to brute if available
       
  9440             return Y.Selector.query(selector, root, one, true); // redo with skipNative true
       
  9441         }
       
  9442     },
       
  9443 
       
  9444     filter: function(nodes, selector) {
       
  9445         var ret = [],
       
  9446             i, node;
       
  9447 
       
  9448         if (nodes && selector) {
       
  9449             for (i = 0; (node = nodes[i++]);) {
       
  9450                 if (Y.Selector.test(node, selector)) {
       
  9451                     ret[ret.length] = node;
       
  9452                 }
       
  9453             }
       
  9454         } else {
       
  9455         }
       
  9456 
       
  9457         return ret;
       
  9458     },
       
  9459 
       
  9460     test: function(node, selector, root) {
       
  9461         var ret = false,
       
  9462             useFrag = false,
       
  9463             groups,
       
  9464             parent,
       
  9465             item,
       
  9466             items,
       
  9467             frag,
       
  9468             id,
       
  9469             i, j, group;
       
  9470 
       
  9471         if (node && node.tagName) { // only test HTMLElements
       
  9472 
       
  9473             if (typeof selector == 'function') { // test with function
       
  9474                 ret = selector.call(node, node);
       
  9475             } else { // test with query
       
  9476                 // we need a root if off-doc
       
  9477                 groups = selector.split(',');
       
  9478                 if (!root && !Y.DOM.inDoc(node)) {
       
  9479                     parent = node.parentNode;
       
  9480                     if (parent) { 
       
  9481                         root = parent;
       
  9482                     } else { // only use frag when no parent to query
       
  9483                         frag = node[OWNER_DOCUMENT].createDocumentFragment();
       
  9484                         frag.appendChild(node);
       
  9485                         root = frag;
       
  9486                         useFrag = true;
       
  9487                     }
       
  9488                 }
       
  9489                 root = root || node[OWNER_DOCUMENT];
       
  9490 
       
  9491                 id = Y.Selector._escapeId(Y.DOM.getId(node));
       
  9492                 if (!id) {
       
  9493                     id = Y.guid();
       
  9494                     Y.DOM.setId(node, id);
       
  9495                 }
       
  9496 
       
  9497                 for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
       
  9498                     group += '[id="' + id + '"]';
       
  9499                     items = Y.Selector.query(group, root);
       
  9500 
       
  9501                     for (j = 0; item = items[j++];) {
       
  9502                         if (item === node) {
       
  9503                             ret = true;
       
  9504                             break;
       
  9505                         }
       
  9506                     }
       
  9507                     if (ret) {
       
  9508                         break;
       
  9509                     }
       
  9510                 }
       
  9511 
       
  9512                 if (useFrag) { // cleanup
       
  9513                     frag.removeChild(node);
       
  9514                 }
       
  9515             };
       
  9516         }
       
  9517 
       
  9518         return ret;
       
  9519     },
       
  9520 
       
  9521     /**
       
  9522      * A convenience function to emulate Y.Node's aNode.ancestor(selector).
       
  9523      * @param {HTMLElement} element An HTMLElement to start the query from.
       
  9524      * @param {String} selector The CSS selector to test the node against.
       
  9525      * @return {HTMLElement} The ancestor node matching the selector, or null.
       
  9526      * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
       
  9527      * @static
       
  9528      * @method ancestor
       
  9529      */
       
  9530     ancestor: function (element, selector, testSelf) {
       
  9531         return Y.DOM.ancestor(element, function(n) {
       
  9532             return Y.Selector.test(n, selector);
       
  9533         }, testSelf);
       
  9534     },
       
  9535 
       
  9536     _parse: function(name, selector) {
       
  9537         return selector.match(Y.Selector._types[name].re);
       
  9538     },
       
  9539 
       
  9540     _replace: function(name, selector) {
       
  9541         var o = Y.Selector._types[name];
       
  9542         return selector.replace(o.re, o.token);
       
  9543     },
       
  9544 
       
  9545     _restore: function(name, selector, items) {
       
  9546         if (items) {
       
  9547             var token = Y.Selector._types[name].token,
       
  9548                 i, len;
       
  9549             for (i = 0, len = items.length; i < len; ++i) {
       
  9550                 selector = selector.replace(token, items[i]);
       
  9551             }
       
  9552         }
       
  9553         return selector;
       
  9554     }
       
  9555 };
       
  9556 
       
  9557 Y.mix(Y.Selector, Selector, true);
       
  9558 
       
  9559 })(Y);
       
  9560 
       
  9561 
       
  9562 }, '@VERSION@', {"requires": ["dom-base"]});
       
  9563 YUI.add('selector', function (Y, NAME) {
       
  9564 
       
  9565 
       
  9566 
       
  9567 }, '@VERSION@', {"requires": ["selector-native"]});
       
  9568 YUI.add('event-custom-base', function (Y, NAME) {
       
  9569 
       
  9570 /**
       
  9571  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
  9572  * events.
       
  9573  * @module event-custom
       
  9574  */
       
  9575 
       
  9576 Y.Env.evt = {
       
  9577     handles: {},
       
  9578     plugins: {}
       
  9579 };
       
  9580 
       
  9581 
       
  9582 /**
       
  9583  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
  9584  * events.
       
  9585  * @module event-custom
       
  9586  * @submodule event-custom-base
       
  9587  */
       
  9588 
       
  9589 /**
       
  9590  * Allows for the insertion of methods that are executed before or after
       
  9591  * a specified method
       
  9592  * @class Do
       
  9593  * @static
       
  9594  */
       
  9595 
       
  9596 var DO_BEFORE = 0,
       
  9597     DO_AFTER = 1,
       
  9598 
       
  9599 DO = {
       
  9600 
       
  9601     /**
       
  9602      * Cache of objects touched by the utility
       
  9603      * @property objs
       
  9604      * @static
       
  9605      * @deprecated Since 3.6.0. The `_yuiaop` property on the AOP'd object
       
  9606      * replaces the role of this property, but is considered to be private, and
       
  9607      * is only mentioned to provide a migration path.
       
  9608      *
       
  9609      * If you have a use case which warrants migration to the _yuiaop property,
       
  9610      * please file a ticket to let us know what it's used for and we can see if
       
  9611      * we need to expose hooks for that functionality more formally.
       
  9612      */
       
  9613     objs: null,
       
  9614 
       
  9615     /**
       
  9616      * <p>Execute the supplied method before the specified function.  Wrapping
       
  9617      * function may optionally return an instance of the following classes to
       
  9618      * further alter runtime behavior:</p>
       
  9619      * <dl>
       
  9620      *     <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
       
  9621      *         <dd>Immediatly stop execution and return
       
  9622      *         <code>returnValue</code>.  No other wrapping functions will be
       
  9623      *         executed.</dd>
       
  9624      *     <dt></code>Y.Do.AlterArgs(message, newArgArray)</code></dt>
       
  9625      *         <dd>Replace the arguments that the original function will be
       
  9626      *         called with.</dd>
       
  9627      *     <dt></code>Y.Do.Prevent(message)</code></dt>
       
  9628      *         <dd>Don't execute the wrapped function.  Other before phase
       
  9629      *         wrappers will be executed.</dd>
       
  9630      * </dl>
       
  9631      *
       
  9632      * @method before
       
  9633      * @param fn {Function} the function to execute
       
  9634      * @param obj the object hosting the method to displace
       
  9635      * @param sFn {string} the name of the method to displace
       
  9636      * @param c The execution context for fn
       
  9637      * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
       
  9638      * when the event fires.
       
  9639      * @return {string} handle for the subscription
       
  9640      * @static
       
  9641      */
       
  9642     before: function(fn, obj, sFn, c) {
       
  9643         var f = fn, a;
       
  9644         if (c) {
       
  9645             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
  9646             f = Y.rbind.apply(Y, a);
       
  9647         }
       
  9648 
       
  9649         return this._inject(DO_BEFORE, f, obj, sFn);
       
  9650     },
       
  9651 
       
  9652     /**
       
  9653      * <p>Execute the supplied method after the specified function.  Wrapping
       
  9654      * function may optionally return an instance of the following classes to
       
  9655      * further alter runtime behavior:</p>
       
  9656      * <dl>
       
  9657      *     <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
       
  9658      *         <dd>Immediatly stop execution and return
       
  9659      *         <code>returnValue</code>.  No other wrapping functions will be
       
  9660      *         executed.</dd>
       
  9661      *     <dt></code>Y.Do.AlterReturn(message, returnValue)</code></dt>
       
  9662      *         <dd>Return <code>returnValue</code> instead of the wrapped
       
  9663      *         method's original return value.  This can be further altered by
       
  9664      *         other after phase wrappers.</dd>
       
  9665      * </dl>
       
  9666      *
       
  9667      * <p>The static properties <code>Y.Do.originalRetVal</code> and
       
  9668      * <code>Y.Do.currentRetVal</code> will be populated for reference.</p>
       
  9669      *
       
  9670      * @method after
       
  9671      * @param fn {Function} the function to execute
       
  9672      * @param obj the object hosting the method to displace
       
  9673      * @param sFn {string} the name of the method to displace
       
  9674      * @param c The execution context for fn
       
  9675      * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
       
  9676      * @return {string} handle for the subscription
       
  9677      * @static
       
  9678      */
       
  9679     after: function(fn, obj, sFn, c) {
       
  9680         var f = fn, a;
       
  9681         if (c) {
       
  9682             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
  9683             f = Y.rbind.apply(Y, a);
       
  9684         }
       
  9685 
       
  9686         return this._inject(DO_AFTER, f, obj, sFn);
       
  9687     },
       
  9688 
       
  9689     /**
       
  9690      * Execute the supplied method before or after the specified function.
       
  9691      * Used by <code>before</code> and <code>after</code>.
       
  9692      *
       
  9693      * @method _inject
       
  9694      * @param when {string} before or after
       
  9695      * @param fn {Function} the function to execute
       
  9696      * @param obj the object hosting the method to displace
       
  9697      * @param sFn {string} the name of the method to displace
       
  9698      * @param c The execution context for fn
       
  9699      * @return {string} handle for the subscription
       
  9700      * @private
       
  9701      * @static
       
  9702      */
       
  9703     _inject: function(when, fn, obj, sFn) {
       
  9704         // object id
       
  9705         var id = Y.stamp(obj), o, sid;
       
  9706 
       
  9707         if (!obj._yuiaop) {
       
  9708             // create a map entry for the obj if it doesn't exist, to hold overridden methods
       
  9709             obj._yuiaop = {};
       
  9710         }
       
  9711 
       
  9712         o = obj._yuiaop;
       
  9713 
       
  9714         if (!o[sFn]) {
       
  9715             // create a map entry for the method if it doesn't exist
       
  9716             o[sFn] = new Y.Do.Method(obj, sFn);
       
  9717 
       
  9718             // re-route the method to our wrapper
       
  9719             obj[sFn] = function() {
       
  9720                 return o[sFn].exec.apply(o[sFn], arguments);
       
  9721             };
       
  9722         }
       
  9723 
       
  9724         // subscriber id
       
  9725         sid = id + Y.stamp(fn) + sFn;
       
  9726 
       
  9727         // register the callback
       
  9728         o[sFn].register(sid, fn, when);
       
  9729 
       
  9730         return new Y.EventHandle(o[sFn], sid);
       
  9731     },
       
  9732 
       
  9733     /**
       
  9734      * Detach a before or after subscription.
       
  9735      *
       
  9736      * @method detach
       
  9737      * @param handle {string} the subscription handle
       
  9738      * @static
       
  9739      */
       
  9740     detach: function(handle) {
       
  9741         if (handle.detach) {
       
  9742             handle.detach();
       
  9743         }
       
  9744     }
       
  9745 };
       
  9746 
       
  9747 Y.Do = DO;
       
  9748 
       
  9749 //////////////////////////////////////////////////////////////////////////
       
  9750 
       
  9751 /**
       
  9752  * Contains the return value from the wrapped method, accessible
       
  9753  * by 'after' event listeners.
       
  9754  *
       
  9755  * @property originalRetVal
       
  9756  * @static
       
  9757  * @since 3.2.0
       
  9758  */
       
  9759 
       
  9760 /**
       
  9761  * Contains the current state of the return value, consumable by
       
  9762  * 'after' event listeners, and updated if an after subscriber
       
  9763  * changes the return value generated by the wrapped function.
       
  9764  *
       
  9765  * @property currentRetVal
       
  9766  * @static
       
  9767  * @since 3.2.0
       
  9768  */
       
  9769 
       
  9770 //////////////////////////////////////////////////////////////////////////
       
  9771 
       
  9772 /**
       
  9773  * Wrapper for a displaced method with aop enabled
       
  9774  * @class Do.Method
       
  9775  * @constructor
       
  9776  * @param obj The object to operate on
       
  9777  * @param sFn The name of the method to displace
       
  9778  */
       
  9779 DO.Method = function(obj, sFn) {
       
  9780     this.obj = obj;
       
  9781     this.methodName = sFn;
       
  9782     this.method = obj[sFn];
       
  9783     this.before = {};
       
  9784     this.after = {};
       
  9785 };
       
  9786 
       
  9787 /**
       
  9788  * Register a aop subscriber
       
  9789  * @method register
       
  9790  * @param sid {string} the subscriber id
       
  9791  * @param fn {Function} the function to execute
       
  9792  * @param when {string} when to execute the function
       
  9793  */
       
  9794 DO.Method.prototype.register = function (sid, fn, when) {
       
  9795     if (when) {
       
  9796         this.after[sid] = fn;
       
  9797     } else {
       
  9798         this.before[sid] = fn;
       
  9799     }
       
  9800 };
       
  9801 
       
  9802 /**
       
  9803  * Unregister a aop subscriber
       
  9804  * @method delete
       
  9805  * @param sid {string} the subscriber id
       
  9806  * @param fn {Function} the function to execute
       
  9807  * @param when {string} when to execute the function
       
  9808  */
       
  9809 DO.Method.prototype._delete = function (sid) {
       
  9810     delete this.before[sid];
       
  9811     delete this.after[sid];
       
  9812 };
       
  9813 
       
  9814 /**
       
  9815  * <p>Execute the wrapped method.  All arguments are passed into the wrapping
       
  9816  * functions.  If any of the before wrappers return an instance of
       
  9817  * <code>Y.Do.Halt</code> or <code>Y.Do.Prevent</code>, neither the wrapped
       
  9818  * function nor any after phase subscribers will be executed.</p>
       
  9819  *
       
  9820  * <p>The return value will be the return value of the wrapped function or one
       
  9821  * provided by a wrapper function via an instance of <code>Y.Do.Halt</code> or
       
  9822  * <code>Y.Do.AlterReturn</code>.
       
  9823  *
       
  9824  * @method exec
       
  9825  * @param arg* {any} Arguments are passed to the wrapping and wrapped functions
       
  9826  * @return {any} Return value of wrapped function unless overwritten (see above)
       
  9827  */
       
  9828 DO.Method.prototype.exec = function () {
       
  9829 
       
  9830     var args = Y.Array(arguments, 0, true),
       
  9831         i, ret, newRet,
       
  9832         bf = this.before,
       
  9833         af = this.after,
       
  9834         prevented = false;
       
  9835 
       
  9836     // execute before
       
  9837     for (i in bf) {
       
  9838         if (bf.hasOwnProperty(i)) {
       
  9839             ret = bf[i].apply(this.obj, args);
       
  9840             if (ret) {
       
  9841                 switch (ret.constructor) {
       
  9842                     case DO.Halt:
       
  9843                         return ret.retVal;
       
  9844                     case DO.AlterArgs:
       
  9845                         args = ret.newArgs;
       
  9846                         break;
       
  9847                     case DO.Prevent:
       
  9848                         prevented = true;
       
  9849                         break;
       
  9850                     default:
       
  9851                 }
       
  9852             }
       
  9853         }
       
  9854     }
       
  9855 
       
  9856     // execute method
       
  9857     if (!prevented) {
       
  9858         ret = this.method.apply(this.obj, args);
       
  9859     }
       
  9860 
       
  9861     DO.originalRetVal = ret;
       
  9862     DO.currentRetVal = ret;
       
  9863 
       
  9864     // execute after methods.
       
  9865     for (i in af) {
       
  9866         if (af.hasOwnProperty(i)) {
       
  9867             newRet = af[i].apply(this.obj, args);
       
  9868             // Stop processing if a Halt object is returned
       
  9869             if (newRet && newRet.constructor === DO.Halt) {
       
  9870                 return newRet.retVal;
       
  9871             // Check for a new return value
       
  9872             } else if (newRet && newRet.constructor === DO.AlterReturn) {
       
  9873                 ret = newRet.newRetVal;
       
  9874                 // Update the static retval state
       
  9875                 DO.currentRetVal = ret;
       
  9876             }
       
  9877         }
       
  9878     }
       
  9879 
       
  9880     return ret;
       
  9881 };
       
  9882 
       
  9883 //////////////////////////////////////////////////////////////////////////
       
  9884 
       
  9885 /**
       
  9886  * Return an AlterArgs object when you want to change the arguments that
       
  9887  * were passed into the function.  Useful for Do.before subscribers.  An
       
  9888  * example would be a service that scrubs out illegal characters prior to
       
  9889  * executing the core business logic.
       
  9890  * @class Do.AlterArgs
       
  9891  * @constructor
       
  9892  * @param msg {String} (optional) Explanation of the altered return value
       
  9893  * @param newArgs {Array} Call parameters to be used for the original method
       
  9894  *                        instead of the arguments originally passed in.
       
  9895  */
       
  9896 DO.AlterArgs = function(msg, newArgs) {
       
  9897     this.msg = msg;
       
  9898     this.newArgs = newArgs;
       
  9899 };
       
  9900 
       
  9901 /**
       
  9902  * Return an AlterReturn object when you want to change the result returned
       
  9903  * from the core method to the caller.  Useful for Do.after subscribers.
       
  9904  * @class Do.AlterReturn
       
  9905  * @constructor
       
  9906  * @param msg {String} (optional) Explanation of the altered return value
       
  9907  * @param newRetVal {any} Return value passed to code that invoked the wrapped
       
  9908  *                      function.
       
  9909  */
       
  9910 DO.AlterReturn = function(msg, newRetVal) {
       
  9911     this.msg = msg;
       
  9912     this.newRetVal = newRetVal;
       
  9913 };
       
  9914 
       
  9915 /**
       
  9916  * Return a Halt object when you want to terminate the execution
       
  9917  * of all subsequent subscribers as well as the wrapped method
       
  9918  * if it has not exectued yet.  Useful for Do.before subscribers.
       
  9919  * @class Do.Halt
       
  9920  * @constructor
       
  9921  * @param msg {String} (optional) Explanation of why the termination was done
       
  9922  * @param retVal {any} Return value passed to code that invoked the wrapped
       
  9923  *                      function.
       
  9924  */
       
  9925 DO.Halt = function(msg, retVal) {
       
  9926     this.msg = msg;
       
  9927     this.retVal = retVal;
       
  9928 };
       
  9929 
       
  9930 /**
       
  9931  * Return a Prevent object when you want to prevent the wrapped function
       
  9932  * from executing, but want the remaining listeners to execute.  Useful
       
  9933  * for Do.before subscribers.
       
  9934  * @class Do.Prevent
       
  9935  * @constructor
       
  9936  * @param msg {String} (optional) Explanation of why the termination was done
       
  9937  */
       
  9938 DO.Prevent = function(msg) {
       
  9939     this.msg = msg;
       
  9940 };
       
  9941 
       
  9942 /**
       
  9943  * Return an Error object when you want to terminate the execution
       
  9944  * of all subsequent method calls.
       
  9945  * @class Do.Error
       
  9946  * @constructor
       
  9947  * @param msg {String} (optional) Explanation of the altered return value
       
  9948  * @param retVal {any} Return value passed to code that invoked the wrapped
       
  9949  *                      function.
       
  9950  * @deprecated use Y.Do.Halt or Y.Do.Prevent
       
  9951  */
       
  9952 DO.Error = DO.Halt;
       
  9953 
       
  9954 
       
  9955 //////////////////////////////////////////////////////////////////////////
       
  9956 
       
  9957 /**
       
  9958  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
  9959  * events.
       
  9960  * @module event-custom
       
  9961  * @submodule event-custom-base
       
  9962  */
       
  9963 
       
  9964 
       
  9965 // var onsubscribeType = "_event:onsub",
       
  9966 var YArray = Y.Array,
       
  9967 
       
  9968     AFTER = 'after',
       
  9969     CONFIGS = [
       
  9970         'broadcast',
       
  9971         'monitored',
       
  9972         'bubbles',
       
  9973         'context',
       
  9974         'contextFn',
       
  9975         'currentTarget',
       
  9976         'defaultFn',
       
  9977         'defaultTargetOnly',
       
  9978         'details',
       
  9979         'emitFacade',
       
  9980         'fireOnce',
       
  9981         'async',
       
  9982         'host',
       
  9983         'preventable',
       
  9984         'preventedFn',
       
  9985         'queuable',
       
  9986         'silent',
       
  9987         'stoppedFn',
       
  9988         'target',
       
  9989         'type'
       
  9990     ],
       
  9991 
       
  9992     CONFIGS_HASH = YArray.hash(CONFIGS),
       
  9993 
       
  9994     nativeSlice = Array.prototype.slice,
       
  9995 
       
  9996     YUI3_SIGNATURE = 9,
       
  9997     YUI_LOG = 'yui:log',
       
  9998 
       
  9999     mixConfigs = function(r, s, ov) {
       
 10000         var p;
       
 10001 
       
 10002         for (p in s) {
       
 10003             if (CONFIGS_HASH[p] && (ov || !(p in r))) {
       
 10004                 r[p] = s[p];
       
 10005             }
       
 10006         }
       
 10007 
       
 10008         return r;
       
 10009     };
       
 10010 
       
 10011 /**
       
 10012  * The CustomEvent class lets you define events for your application
       
 10013  * that can be subscribed to by one or more independent component.
       
 10014  *
       
 10015  * @param {String} type The type of event, which is passed to the callback
       
 10016  * when the event fires.
       
 10017  * @param {object} defaults configuration object.
       
 10018  * @class CustomEvent
       
 10019  * @constructor
       
 10020  */
       
 10021 
       
 10022  /**
       
 10023  * The type of event, returned to subscribers when the event fires
       
 10024  * @property type
       
 10025  * @type string
       
 10026  */
       
 10027 
       
 10028 /**
       
 10029  * By default all custom events are logged in the debug build, set silent
       
 10030  * to true to disable debug outpu for this event.
       
 10031  * @property silent
       
 10032  * @type boolean
       
 10033  */
       
 10034 
       
 10035 Y.CustomEvent = function(type, defaults) {
       
 10036 
       
 10037     this._kds = Y.CustomEvent.keepDeprecatedSubs;
       
 10038 
       
 10039     this.id = Y.guid();
       
 10040 
       
 10041     this.type = type;
       
 10042     this.silent = this.logSystem = (type === YUI_LOG);
       
 10043 
       
 10044     if (this._kds) {
       
 10045         /**
       
 10046          * The subscribers to this event
       
 10047          * @property subscribers
       
 10048          * @type Subscriber {}
       
 10049          * @deprecated
       
 10050          */
       
 10051 
       
 10052         /**
       
 10053          * 'After' subscribers
       
 10054          * @property afters
       
 10055          * @type Subscriber {}
       
 10056          * @deprecated
       
 10057          */
       
 10058         this.subscribers = {};
       
 10059         this.afters = {};
       
 10060     }
       
 10061 
       
 10062     if (defaults) {
       
 10063         mixConfigs(this, defaults, true);
       
 10064     }
       
 10065 };
       
 10066 
       
 10067 /**
       
 10068  * Static flag to enable population of the <a href="#property_subscribers">`subscribers`</a>
       
 10069  * and  <a href="#property_subscribers">`afters`</a> properties held on a `CustomEvent` instance.
       
 10070  *
       
 10071  * These properties were changed to private properties (`_subscribers` and `_afters`), and
       
 10072  * converted from objects to arrays for performance reasons.
       
 10073  *
       
 10074  * Setting this property to true will populate the deprecated `subscribers` and `afters`
       
 10075  * properties for people who may be using them (which is expected to be rare). There will
       
 10076  * be a performance hit, compared to the new array based implementation.
       
 10077  *
       
 10078  * If you are using these deprecated properties for a use case which the public API
       
 10079  * does not support, please file an enhancement request, and we can provide an alternate
       
 10080  * public implementation which doesn't have the performance cost required to maintiain the
       
 10081  * properties as objects.
       
 10082  *
       
 10083  * @property keepDeprecatedSubs
       
 10084  * @static
       
 10085  * @for CustomEvent
       
 10086  * @type boolean
       
 10087  * @default false
       
 10088  * @deprecated
       
 10089  */
       
 10090 Y.CustomEvent.keepDeprecatedSubs = false;
       
 10091 
       
 10092 Y.CustomEvent.mixConfigs = mixConfigs;
       
 10093 
       
 10094 Y.CustomEvent.prototype = {
       
 10095 
       
 10096     constructor: Y.CustomEvent,
       
 10097 
       
 10098     /**
       
 10099      * Monitor when an event is attached or detached.
       
 10100      *
       
 10101      * @property monitored
       
 10102      * @type boolean
       
 10103      */
       
 10104 
       
 10105     /**
       
 10106      * If 0, this event does not broadcast.  If 1, the YUI instance is notified
       
 10107      * every time this event fires.  If 2, the YUI instance and the YUI global
       
 10108      * (if event is enabled on the global) are notified every time this event
       
 10109      * fires.
       
 10110      * @property broadcast
       
 10111      * @type int
       
 10112      */
       
 10113 
       
 10114     /**
       
 10115      * Specifies whether this event should be queued when the host is actively
       
 10116      * processing an event.  This will effect exectution order of the callbacks
       
 10117      * for the various events.
       
 10118      * @property queuable
       
 10119      * @type boolean
       
 10120      * @default false
       
 10121      */
       
 10122 
       
 10123     /**
       
 10124      * This event has fired if true
       
 10125      *
       
 10126      * @property fired
       
 10127      * @type boolean
       
 10128      * @default false;
       
 10129      */
       
 10130 
       
 10131     /**
       
 10132      * An array containing the arguments the custom event
       
 10133      * was last fired with.
       
 10134      * @property firedWith
       
 10135      * @type Array
       
 10136      */
       
 10137 
       
 10138     /**
       
 10139      * This event should only fire one time if true, and if
       
 10140      * it has fired, any new subscribers should be notified
       
 10141      * immediately.
       
 10142      *
       
 10143      * @property fireOnce
       
 10144      * @type boolean
       
 10145      * @default false;
       
 10146      */
       
 10147 
       
 10148     /**
       
 10149      * fireOnce listeners will fire syncronously unless async
       
 10150      * is set to true
       
 10151      * @property async
       
 10152      * @type boolean
       
 10153      * @default false
       
 10154      */
       
 10155 
       
 10156     /**
       
 10157      * Flag for stopPropagation that is modified during fire()
       
 10158      * 1 means to stop propagation to bubble targets.  2 means
       
 10159      * to also stop additional subscribers on this target.
       
 10160      * @property stopped
       
 10161      * @type int
       
 10162      */
       
 10163 
       
 10164     /**
       
 10165      * Flag for preventDefault that is modified during fire().
       
 10166      * if it is not 0, the default behavior for this event
       
 10167      * @property prevented
       
 10168      * @type int
       
 10169      */
       
 10170 
       
 10171     /**
       
 10172      * Specifies the host for this custom event.  This is used
       
 10173      * to enable event bubbling
       
 10174      * @property host
       
 10175      * @type EventTarget
       
 10176      */
       
 10177 
       
 10178     /**
       
 10179      * The default function to execute after event listeners
       
 10180      * have fire, but only if the default action was not
       
 10181      * prevented.
       
 10182      * @property defaultFn
       
 10183      * @type Function
       
 10184      */
       
 10185 
       
 10186     /**
       
 10187      * The function to execute if a subscriber calls
       
 10188      * stopPropagation or stopImmediatePropagation
       
 10189      * @property stoppedFn
       
 10190      * @type Function
       
 10191      */
       
 10192 
       
 10193     /**
       
 10194      * The function to execute if a subscriber calls
       
 10195      * preventDefault
       
 10196      * @property preventedFn
       
 10197      * @type Function
       
 10198      */
       
 10199 
       
 10200     /**
       
 10201      * The subscribers to this event
       
 10202      * @property _subscribers
       
 10203      * @type Subscriber []
       
 10204      * @private
       
 10205      */
       
 10206 
       
 10207     /**
       
 10208      * 'After' subscribers
       
 10209      * @property _afters
       
 10210      * @type Subscriber []
       
 10211      * @private
       
 10212      */
       
 10213 
       
 10214     /**
       
 10215      * If set to true, the custom event will deliver an EventFacade object
       
 10216      * that is similar to a DOM event object.
       
 10217      * @property emitFacade
       
 10218      * @type boolean
       
 10219      * @default false
       
 10220      */
       
 10221 
       
 10222     /**
       
 10223      * Supports multiple options for listener signatures in order to
       
 10224      * port YUI 2 apps.
       
 10225      * @property signature
       
 10226      * @type int
       
 10227      * @default 9
       
 10228      */
       
 10229     signature : YUI3_SIGNATURE,
       
 10230 
       
 10231     /**
       
 10232      * The context the the event will fire from by default.  Defaults to the YUI
       
 10233      * instance.
       
 10234      * @property context
       
 10235      * @type object
       
 10236      */
       
 10237     context : Y,
       
 10238 
       
 10239     /**
       
 10240      * Specifies whether or not this event's default function
       
 10241      * can be cancelled by a subscriber by executing preventDefault()
       
 10242      * on the event facade
       
 10243      * @property preventable
       
 10244      * @type boolean
       
 10245      * @default true
       
 10246      */
       
 10247     preventable : true,
       
 10248 
       
 10249     /**
       
 10250      * Specifies whether or not a subscriber can stop the event propagation
       
 10251      * via stopPropagation(), stopImmediatePropagation(), or halt()
       
 10252      *
       
 10253      * Events can only bubble if emitFacade is true.
       
 10254      *
       
 10255      * @property bubbles
       
 10256      * @type boolean
       
 10257      * @default true
       
 10258      */
       
 10259     bubbles : true,
       
 10260 
       
 10261     /**
       
 10262      * Returns the number of subscribers for this event as the sum of the on()
       
 10263      * subscribers and after() subscribers.
       
 10264      *
       
 10265      * @method hasSubs
       
 10266      * @return Number
       
 10267      */
       
 10268     hasSubs: function(when) {
       
 10269         var s = 0,
       
 10270             a = 0,
       
 10271             subs = this._subscribers,
       
 10272             afters = this._afters,
       
 10273             sib = this.sibling;
       
 10274 
       
 10275         if (subs) {
       
 10276             s = subs.length;
       
 10277         }
       
 10278 
       
 10279         if (afters) {
       
 10280             a = afters.length;
       
 10281         }
       
 10282 
       
 10283         if (sib) {
       
 10284             subs = sib._subscribers;
       
 10285             afters = sib._afters;
       
 10286 
       
 10287             if (subs) {
       
 10288                 s += subs.length;
       
 10289             }
       
 10290 
       
 10291             if (afters) {
       
 10292                 a += afters.length;
       
 10293             }
       
 10294         }
       
 10295 
       
 10296         if (when) {
       
 10297             return (when === 'after') ? a : s;
       
 10298         }
       
 10299 
       
 10300         return (s + a);
       
 10301     },
       
 10302 
       
 10303     /**
       
 10304      * Monitor the event state for the subscribed event.  The first parameter
       
 10305      * is what should be monitored, the rest are the normal parameters when
       
 10306      * subscribing to an event.
       
 10307      * @method monitor
       
 10308      * @param what {string} what to monitor ('detach', 'attach', 'publish').
       
 10309      * @return {EventHandle} return value from the monitor event subscription.
       
 10310      */
       
 10311     monitor: function(what) {
       
 10312         this.monitored = true;
       
 10313         var type = this.id + '|' + this.type + '_' + what,
       
 10314             args = nativeSlice.call(arguments, 0);
       
 10315         args[0] = type;
       
 10316         return this.host.on.apply(this.host, args);
       
 10317     },
       
 10318 
       
 10319     /**
       
 10320      * Get all of the subscribers to this event and any sibling event
       
 10321      * @method getSubs
       
 10322      * @return {Array} first item is the on subscribers, second the after.
       
 10323      */
       
 10324     getSubs: function() {
       
 10325 
       
 10326         var sibling = this.sibling,
       
 10327             subs = this._subscribers,
       
 10328             afters = this._afters,
       
 10329             siblingSubs,
       
 10330             siblingAfters;
       
 10331 
       
 10332         if (sibling) {
       
 10333             siblingSubs = sibling._subscribers;
       
 10334             siblingAfters = sibling._afters;
       
 10335         }
       
 10336 
       
 10337         if (siblingSubs) {
       
 10338             if (subs) {
       
 10339                 subs = subs.concat(siblingSubs);
       
 10340             } else {
       
 10341                 subs = siblingSubs.concat();
       
 10342             }
       
 10343         } else {
       
 10344             if (subs) {
       
 10345                 subs = subs.concat();
       
 10346             } else {
       
 10347                 subs = [];
       
 10348             }
       
 10349         }
       
 10350 
       
 10351         if (siblingAfters) {
       
 10352             if (afters) {
       
 10353                 afters = afters.concat(siblingAfters);
       
 10354             } else {
       
 10355                 afters = siblingAfters.concat();
       
 10356             }
       
 10357         } else {
       
 10358             if (afters) {
       
 10359                 afters = afters.concat();
       
 10360             } else {
       
 10361                 afters = [];
       
 10362             }
       
 10363         }
       
 10364 
       
 10365         return [subs, afters];
       
 10366     },
       
 10367 
       
 10368     /**
       
 10369      * Apply configuration properties.  Only applies the CONFIG whitelist
       
 10370      * @method applyConfig
       
 10371      * @param o hash of properties to apply.
       
 10372      * @param force {boolean} if true, properties that exist on the event
       
 10373      * will be overwritten.
       
 10374      */
       
 10375     applyConfig: function(o, force) {
       
 10376         mixConfigs(this, o, force);
       
 10377     },
       
 10378 
       
 10379     /**
       
 10380      * Create the Subscription for subscribing function, context, and bound
       
 10381      * arguments.  If this is a fireOnce event, the subscriber is immediately
       
 10382      * notified.
       
 10383      *
       
 10384      * @method _on
       
 10385      * @param fn {Function} Subscription callback
       
 10386      * @param [context] {Object} Override `this` in the callback
       
 10387      * @param [args] {Array} bound arguments that will be passed to the callback after the arguments generated by fire()
       
 10388      * @param [when] {String} "after" to slot into after subscribers
       
 10389      * @return {EventHandle}
       
 10390      * @protected
       
 10391      */
       
 10392     _on: function(fn, context, args, when) {
       
 10393 
       
 10394         if (!fn) { this.log('Invalid callback for CE: ' + this.type); }
       
 10395 
       
 10396         var s = new Y.Subscriber(fn, context, args, when);
       
 10397 
       
 10398         if (this.fireOnce && this.fired) {
       
 10399             if (this.async) {
       
 10400                 setTimeout(Y.bind(this._notify, this, s, this.firedWith), 0);
       
 10401             } else {
       
 10402                 this._notify(s, this.firedWith);
       
 10403             }
       
 10404         }
       
 10405 
       
 10406         if (when === AFTER) {
       
 10407             if (!this._afters) {
       
 10408                 this._afters = [];
       
 10409                 this._hasAfters = true;
       
 10410             }
       
 10411             this._afters.push(s);
       
 10412         } else {
       
 10413             if (!this._subscribers) {
       
 10414                 this._subscribers = [];
       
 10415                 this._hasSubs = true;
       
 10416             }
       
 10417             this._subscribers.push(s);
       
 10418         }
       
 10419 
       
 10420         if (this._kds) {
       
 10421             if (when === AFTER) {
       
 10422                 this.afters[s.id] = s;
       
 10423             } else {
       
 10424                 this.subscribers[s.id] = s;
       
 10425             }
       
 10426         }
       
 10427 
       
 10428         return new Y.EventHandle(this, s);
       
 10429     },
       
 10430 
       
 10431     /**
       
 10432      * Listen for this event
       
 10433      * @method subscribe
       
 10434      * @param {Function} fn The function to execute.
       
 10435      * @return {EventHandle} Unsubscribe handle.
       
 10436      * @deprecated use on.
       
 10437      */
       
 10438     subscribe: function(fn, context) {
       
 10439         var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null;
       
 10440         return this._on(fn, context, a, true);
       
 10441     },
       
 10442 
       
 10443     /**
       
 10444      * Listen for this event
       
 10445      * @method on
       
 10446      * @param {Function} fn The function to execute.
       
 10447      * @param {object} context optional execution context.
       
 10448      * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
       
 10449      * when the event fires.
       
 10450      * @return {EventHandle} An object with a detach method to detch the handler(s).
       
 10451      */
       
 10452     on: function(fn, context) {
       
 10453         var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null;
       
 10454 
       
 10455         if (this.monitored && this.host) {
       
 10456             this.host._monitor('attach', this, {
       
 10457                 args: arguments
       
 10458             });
       
 10459         }
       
 10460         return this._on(fn, context, a, true);
       
 10461     },
       
 10462 
       
 10463     /**
       
 10464      * Listen for this event after the normal subscribers have been notified and
       
 10465      * the default behavior has been applied.  If a normal subscriber prevents the
       
 10466      * default behavior, it also prevents after listeners from firing.
       
 10467      * @method after
       
 10468      * @param {Function} fn The function to execute.
       
 10469      * @param {object} context optional execution context.
       
 10470      * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
       
 10471      * when the event fires.
       
 10472      * @return {EventHandle} handle Unsubscribe handle.
       
 10473      */
       
 10474     after: function(fn, context) {
       
 10475         var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null;
       
 10476         return this._on(fn, context, a, AFTER);
       
 10477     },
       
 10478 
       
 10479     /**
       
 10480      * Detach listeners.
       
 10481      * @method detach
       
 10482      * @param {Function} fn  The subscribed function to remove, if not supplied
       
 10483      *                       all will be removed.
       
 10484      * @param {Object}   context The context object passed to subscribe.
       
 10485      * @return {int} returns the number of subscribers unsubscribed.
       
 10486      */
       
 10487     detach: function(fn, context) {
       
 10488         // unsubscribe handle
       
 10489         if (fn && fn.detach) {
       
 10490             return fn.detach();
       
 10491         }
       
 10492 
       
 10493         var i, s,
       
 10494             found = 0,
       
 10495             subs = this._subscribers,
       
 10496             afters = this._afters;
       
 10497 
       
 10498         if (subs) {
       
 10499             for (i = subs.length; i >= 0; i--) {
       
 10500                 s = subs[i];
       
 10501                 if (s && (!fn || fn === s.fn)) {
       
 10502                     this._delete(s, subs, i);
       
 10503                     found++;
       
 10504                 }
       
 10505             }
       
 10506         }
       
 10507 
       
 10508         if (afters) {
       
 10509             for (i = afters.length; i >= 0; i--) {
       
 10510                 s = afters[i];
       
 10511                 if (s && (!fn || fn === s.fn)) {
       
 10512                     this._delete(s, afters, i);
       
 10513                     found++;
       
 10514                 }
       
 10515             }
       
 10516         }
       
 10517 
       
 10518         return found;
       
 10519     },
       
 10520 
       
 10521     /**
       
 10522      * Detach listeners.
       
 10523      * @method unsubscribe
       
 10524      * @param {Function} fn  The subscribed function to remove, if not supplied
       
 10525      *                       all will be removed.
       
 10526      * @param {Object}   context The context object passed to subscribe.
       
 10527      * @return {int|undefined} returns the number of subscribers unsubscribed.
       
 10528      * @deprecated use detach.
       
 10529      */
       
 10530     unsubscribe: function() {
       
 10531         return this.detach.apply(this, arguments);
       
 10532     },
       
 10533 
       
 10534     /**
       
 10535      * Notify a single subscriber
       
 10536      * @method _notify
       
 10537      * @param {Subscriber} s the subscriber.
       
 10538      * @param {Array} args the arguments array to apply to the listener.
       
 10539      * @protected
       
 10540      */
       
 10541     _notify: function(s, args, ef) {
       
 10542 
       
 10543         this.log(this.type + '->' + 'sub: ' + s.id);
       
 10544 
       
 10545         var ret;
       
 10546 
       
 10547         ret = s.notify(args, this);
       
 10548 
       
 10549         if (false === ret || this.stopped > 1) {
       
 10550             this.log(this.type + ' cancelled by subscriber');
       
 10551             return false;
       
 10552         }
       
 10553 
       
 10554         return true;
       
 10555     },
       
 10556 
       
 10557     /**
       
 10558      * Logger abstraction to centralize the application of the silent flag
       
 10559      * @method log
       
 10560      * @param {string} msg message to log.
       
 10561      * @param {string} cat log category.
       
 10562      */
       
 10563     log: function(msg, cat) {
       
 10564     },
       
 10565 
       
 10566     /**
       
 10567      * Notifies the subscribers.  The callback functions will be executed
       
 10568      * from the context specified when the event was created, and with the
       
 10569      * following parameters:
       
 10570      *   <ul>
       
 10571      *   <li>The type of event</li>
       
 10572      *   <li>All of the arguments fire() was executed with as an array</li>
       
 10573      *   <li>The custom object (if any) that was passed into the subscribe()
       
 10574      *       method</li>
       
 10575      *   </ul>
       
 10576      * @method fire
       
 10577      * @param {Object*} arguments an arbitrary set of parameters to pass to
       
 10578      *                            the handler.
       
 10579      * @return {boolean} false if one of the subscribers returned false,
       
 10580      *                   true otherwise.
       
 10581      *
       
 10582      */
       
 10583     fire: function() {
       
 10584 
       
 10585         // push is the fastest way to go from arguments to arrays
       
 10586         // for most browsers currently
       
 10587         // http://jsperf.com/push-vs-concat-vs-slice/2
       
 10588 
       
 10589         var args = [];
       
 10590         args.push.apply(args, arguments);
       
 10591 
       
 10592         return this._fire(args);
       
 10593     },
       
 10594 
       
 10595     /**
       
 10596      * Private internal implementation for `fire`, which is can be used directly by
       
 10597      * `EventTarget` and other event module classes which have already converted from
       
 10598      * an `arguments` list to an array, to avoid the repeated overhead.
       
 10599      *
       
 10600      * @method _fire
       
 10601      * @private
       
 10602      * @param {Array} args The array of arguments passed to be passed to handlers.
       
 10603      * @return {boolean} false if one of the subscribers returned false, true otherwise.
       
 10604      */
       
 10605     _fire: function(args) {
       
 10606 
       
 10607         if (this.fireOnce && this.fired) {
       
 10608             this.log('fireOnce event: ' + this.type + ' already fired');
       
 10609             return true;
       
 10610         } else {
       
 10611 
       
 10612             // this doesn't happen if the event isn't published
       
 10613             // this.host._monitor('fire', this.type, args);
       
 10614 
       
 10615             this.fired = true;
       
 10616 
       
 10617             if (this.fireOnce) {
       
 10618                 this.firedWith = args;
       
 10619             }
       
 10620 
       
 10621             if (this.emitFacade) {
       
 10622                 return this.fireComplex(args);
       
 10623             } else {
       
 10624                 return this.fireSimple(args);
       
 10625             }
       
 10626         }
       
 10627     },
       
 10628 
       
 10629     /**
       
 10630      * Set up for notifying subscribers of non-emitFacade events.
       
 10631      *
       
 10632      * @method fireSimple
       
 10633      * @param args {Array} Arguments passed to fire()
       
 10634      * @return Boolean false if a subscriber returned false
       
 10635      * @protected
       
 10636      */
       
 10637     fireSimple: function(args) {
       
 10638         this.stopped = 0;
       
 10639         this.prevented = 0;
       
 10640         if (this.hasSubs()) {
       
 10641             var subs = this.getSubs();
       
 10642             this._procSubs(subs[0], args);
       
 10643             this._procSubs(subs[1], args);
       
 10644         }
       
 10645         if (this.broadcast) {
       
 10646             this._broadcast(args);
       
 10647         }
       
 10648         return this.stopped ? false : true;
       
 10649     },
       
 10650 
       
 10651     // Requires the event-custom-complex module for full funcitonality.
       
 10652     fireComplex: function(args) {
       
 10653         this.log('Missing event-custom-complex needed to emit a facade for: ' + this.type);
       
 10654         args[0] = args[0] || {};
       
 10655         return this.fireSimple(args);
       
 10656     },
       
 10657 
       
 10658     /**
       
 10659      * Notifies a list of subscribers.
       
 10660      *
       
 10661      * @method _procSubs
       
 10662      * @param subs {Array} List of subscribers
       
 10663      * @param args {Array} Arguments passed to fire()
       
 10664      * @param ef {}
       
 10665      * @return Boolean false if a subscriber returns false or stops the event
       
 10666      *              propagation via e.stopPropagation(),
       
 10667      *              e.stopImmediatePropagation(), or e.halt()
       
 10668      * @private
       
 10669      */
       
 10670     _procSubs: function(subs, args, ef) {
       
 10671         var s, i, l;
       
 10672 
       
 10673         for (i = 0, l = subs.length; i < l; i++) {
       
 10674             s = subs[i];
       
 10675             if (s && s.fn) {
       
 10676                 if (false === this._notify(s, args, ef)) {
       
 10677                     this.stopped = 2;
       
 10678                 }
       
 10679                 if (this.stopped === 2) {
       
 10680                     return false;
       
 10681                 }
       
 10682             }
       
 10683         }
       
 10684 
       
 10685         return true;
       
 10686     },
       
 10687 
       
 10688     /**
       
 10689      * Notifies the YUI instance if the event is configured with broadcast = 1,
       
 10690      * and both the YUI instance and Y.Global if configured with broadcast = 2.
       
 10691      *
       
 10692      * @method _broadcast
       
 10693      * @param args {Array} Arguments sent to fire()
       
 10694      * @private
       
 10695      */
       
 10696     _broadcast: function(args) {
       
 10697         if (!this.stopped && this.broadcast) {
       
 10698 
       
 10699             var a = args.concat();
       
 10700             a.unshift(this.type);
       
 10701 
       
 10702             if (this.host !== Y) {
       
 10703                 Y.fire.apply(Y, a);
       
 10704             }
       
 10705 
       
 10706             if (this.broadcast === 2) {
       
 10707                 Y.Global.fire.apply(Y.Global, a);
       
 10708             }
       
 10709         }
       
 10710     },
       
 10711 
       
 10712     /**
       
 10713      * Removes all listeners
       
 10714      * @method unsubscribeAll
       
 10715      * @return {int} The number of listeners unsubscribed.
       
 10716      * @deprecated use detachAll.
       
 10717      */
       
 10718     unsubscribeAll: function() {
       
 10719         return this.detachAll.apply(this, arguments);
       
 10720     },
       
 10721 
       
 10722     /**
       
 10723      * Removes all listeners
       
 10724      * @method detachAll
       
 10725      * @return {int} The number of listeners unsubscribed.
       
 10726      */
       
 10727     detachAll: function() {
       
 10728         return this.detach();
       
 10729     },
       
 10730 
       
 10731     /**
       
 10732      * Deletes the subscriber from the internal store of on() and after()
       
 10733      * subscribers.
       
 10734      *
       
 10735      * @method _delete
       
 10736      * @param s subscriber object.
       
 10737      * @param subs (optional) on or after subscriber array
       
 10738      * @param index (optional) The index found.
       
 10739      * @private
       
 10740      */
       
 10741     _delete: function(s, subs, i) {
       
 10742         var when = s._when;
       
 10743 
       
 10744         if (!subs) {
       
 10745             subs = (when === AFTER) ? this._afters : this._subscribers;
       
 10746         }
       
 10747 
       
 10748         if (subs) {
       
 10749             i = YArray.indexOf(subs, s, 0);
       
 10750 
       
 10751             if (s && subs[i] === s) {
       
 10752                 subs.splice(i, 1);
       
 10753 
       
 10754                 if (subs.length === 0) {
       
 10755                     if (when === AFTER) {
       
 10756                         this._hasAfters = false;
       
 10757                     } else {
       
 10758                         this._hasSubs = false;
       
 10759                     }
       
 10760                 }
       
 10761             }
       
 10762         }
       
 10763 
       
 10764         if (this._kds) {
       
 10765             if (when === AFTER) {
       
 10766                 delete this.afters[s.id];
       
 10767             } else {
       
 10768                 delete this.subscribers[s.id];
       
 10769             }
       
 10770         }
       
 10771 
       
 10772         if (this.monitored && this.host) {
       
 10773             this.host._monitor('detach', this, {
       
 10774                 ce: this,
       
 10775                 sub: s
       
 10776             });
       
 10777         }
       
 10778 
       
 10779         if (s) {
       
 10780             s.deleted = true;
       
 10781         }
       
 10782     }
       
 10783 };
       
 10784 /**
       
 10785  * Stores the subscriber information to be used when the event fires.
       
 10786  * @param {Function} fn       The wrapped function to execute.
       
 10787  * @param {Object}   context  The value of the keyword 'this' in the listener.
       
 10788  * @param {Array} args*       0..n additional arguments to supply the listener.
       
 10789  *
       
 10790  * @class Subscriber
       
 10791  * @constructor
       
 10792  */
       
 10793 Y.Subscriber = function(fn, context, args, when) {
       
 10794 
       
 10795     /**
       
 10796      * The callback that will be execute when the event fires
       
 10797      * This is wrapped by Y.rbind if obj was supplied.
       
 10798      * @property fn
       
 10799      * @type Function
       
 10800      */
       
 10801     this.fn = fn;
       
 10802 
       
 10803     /**
       
 10804      * Optional 'this' keyword for the listener
       
 10805      * @property context
       
 10806      * @type Object
       
 10807      */
       
 10808     this.context = context;
       
 10809 
       
 10810     /**
       
 10811      * Unique subscriber id
       
 10812      * @property id
       
 10813      * @type String
       
 10814      */
       
 10815     this.id = Y.guid();
       
 10816 
       
 10817     /**
       
 10818      * Additional arguments to propagate to the subscriber
       
 10819      * @property args
       
 10820      * @type Array
       
 10821      */
       
 10822     this.args = args;
       
 10823 
       
 10824     this._when = when;
       
 10825 
       
 10826     /**
       
 10827      * Custom events for a given fire transaction.
       
 10828      * @property events
       
 10829      * @type {EventTarget}
       
 10830      */
       
 10831     // this.events = null;
       
 10832 
       
 10833     /**
       
 10834      * This listener only reacts to the event once
       
 10835      * @property once
       
 10836      */
       
 10837     // this.once = false;
       
 10838 
       
 10839 };
       
 10840 
       
 10841 Y.Subscriber.prototype = {
       
 10842     constructor: Y.Subscriber,
       
 10843 
       
 10844     _notify: function(c, args, ce) {
       
 10845         if (this.deleted && !this.postponed) {
       
 10846             if (this.postponed) {
       
 10847                 delete this.fn;
       
 10848                 delete this.context;
       
 10849             } else {
       
 10850                 delete this.postponed;
       
 10851                 return null;
       
 10852             }
       
 10853         }
       
 10854         var a = this.args, ret;
       
 10855         switch (ce.signature) {
       
 10856             case 0:
       
 10857                 ret = this.fn.call(c, ce.type, args, c);
       
 10858                 break;
       
 10859             case 1:
       
 10860                 ret = this.fn.call(c, args[0] || null, c);
       
 10861                 break;
       
 10862             default:
       
 10863                 if (a || args) {
       
 10864                     args = args || [];
       
 10865                     a = (a) ? args.concat(a) : args;
       
 10866                     ret = this.fn.apply(c, a);
       
 10867                 } else {
       
 10868                     ret = this.fn.call(c);
       
 10869                 }
       
 10870         }
       
 10871 
       
 10872         if (this.once) {
       
 10873             ce._delete(this);
       
 10874         }
       
 10875 
       
 10876         return ret;
       
 10877     },
       
 10878 
       
 10879     /**
       
 10880      * Executes the subscriber.
       
 10881      * @method notify
       
 10882      * @param args {Array} Arguments array for the subscriber.
       
 10883      * @param ce {CustomEvent} The custom event that sent the notification.
       
 10884      */
       
 10885     notify: function(args, ce) {
       
 10886         var c = this.context,
       
 10887             ret = true;
       
 10888 
       
 10889         if (!c) {
       
 10890             c = (ce.contextFn) ? ce.contextFn() : ce.context;
       
 10891         }
       
 10892 
       
 10893         // only catch errors if we will not re-throw them.
       
 10894         if (Y.config && Y.config.throwFail) {
       
 10895             ret = this._notify(c, args, ce);
       
 10896         } else {
       
 10897             try {
       
 10898                 ret = this._notify(c, args, ce);
       
 10899             } catch (e) {
       
 10900                 Y.error(this + ' failed: ' + e.message, e);
       
 10901             }
       
 10902         }
       
 10903 
       
 10904         return ret;
       
 10905     },
       
 10906 
       
 10907     /**
       
 10908      * Returns true if the fn and obj match this objects properties.
       
 10909      * Used by the unsubscribe method to match the right subscriber.
       
 10910      *
       
 10911      * @method contains
       
 10912      * @param {Function} fn the function to execute.
       
 10913      * @param {Object} context optional 'this' keyword for the listener.
       
 10914      * @return {boolean} true if the supplied arguments match this
       
 10915      *                   subscriber's signature.
       
 10916      */
       
 10917     contains: function(fn, context) {
       
 10918         if (context) {
       
 10919             return ((this.fn === fn) && this.context === context);
       
 10920         } else {
       
 10921             return (this.fn === fn);
       
 10922         }
       
 10923     },
       
 10924 
       
 10925     valueOf : function() {
       
 10926         return this.id;
       
 10927     }
       
 10928 
       
 10929 };
       
 10930 /**
       
 10931  * Return value from all subscribe operations
       
 10932  * @class EventHandle
       
 10933  * @constructor
       
 10934  * @param {CustomEvent} evt the custom event.
       
 10935  * @param {Subscriber} sub the subscriber.
       
 10936  */
       
 10937 Y.EventHandle = function(evt, sub) {
       
 10938 
       
 10939     /**
       
 10940      * The custom event
       
 10941      *
       
 10942      * @property evt
       
 10943      * @type CustomEvent
       
 10944      */
       
 10945     this.evt = evt;
       
 10946 
       
 10947     /**
       
 10948      * The subscriber object
       
 10949      *
       
 10950      * @property sub
       
 10951      * @type Subscriber
       
 10952      */
       
 10953     this.sub = sub;
       
 10954 };
       
 10955 
       
 10956 Y.EventHandle.prototype = {
       
 10957     batch: function(f, c) {
       
 10958         f.call(c || this, this);
       
 10959         if (Y.Lang.isArray(this.evt)) {
       
 10960             Y.Array.each(this.evt, function(h) {
       
 10961                 h.batch.call(c || h, f);
       
 10962             });
       
 10963         }
       
 10964     },
       
 10965 
       
 10966     /**
       
 10967      * Detaches this subscriber
       
 10968      * @method detach
       
 10969      * @return {int} the number of detached listeners
       
 10970      */
       
 10971     detach: function() {
       
 10972         var evt = this.evt, detached = 0, i;
       
 10973         if (evt) {
       
 10974             if (Y.Lang.isArray(evt)) {
       
 10975                 for (i = 0; i < evt.length; i++) {
       
 10976                     detached += evt[i].detach();
       
 10977                 }
       
 10978             } else {
       
 10979                 evt._delete(this.sub);
       
 10980                 detached = 1;
       
 10981             }
       
 10982 
       
 10983         }
       
 10984 
       
 10985         return detached;
       
 10986     },
       
 10987 
       
 10988     /**
       
 10989      * Monitor the event state for the subscribed event.  The first parameter
       
 10990      * is what should be monitored, the rest are the normal parameters when
       
 10991      * subscribing to an event.
       
 10992      * @method monitor
       
 10993      * @param what {string} what to monitor ('attach', 'detach', 'publish').
       
 10994      * @return {EventHandle} return value from the monitor event subscription.
       
 10995      */
       
 10996     monitor: function(what) {
       
 10997         return this.evt.monitor.apply(this.evt, arguments);
       
 10998     }
       
 10999 };
       
 11000 
       
 11001 /**
       
 11002  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 11003  * events.
       
 11004  * @module event-custom
       
 11005  * @submodule event-custom-base
       
 11006  */
       
 11007 
       
 11008 /**
       
 11009  * EventTarget provides the implementation for any object to
       
 11010  * publish, subscribe and fire to custom events, and also
       
 11011  * alows other EventTargets to target the object with events
       
 11012  * sourced from the other object.
       
 11013  * EventTarget is designed to be used with Y.augment to wrap
       
 11014  * EventCustom in an interface that allows events to be listened to
       
 11015  * and fired by name.  This makes it possible for implementing code to
       
 11016  * subscribe to an event that either has not been created yet, or will
       
 11017  * not be created at all.
       
 11018  * @class EventTarget
       
 11019  * @param opts a configuration object
       
 11020  * @config emitFacade {boolean} if true, all events will emit event
       
 11021  * facade payloads by default (default false)
       
 11022  * @config prefix {String} the prefix to apply to non-prefixed event names
       
 11023  */
       
 11024 
       
 11025 var L = Y.Lang,
       
 11026     PREFIX_DELIMITER = ':',
       
 11027     CATEGORY_DELIMITER = '|',
       
 11028     AFTER_PREFIX = '~AFTER~',
       
 11029     WILD_TYPE_RE = /(.*?)(:)(.*?)/,
       
 11030 
       
 11031     _wildType = Y.cached(function(type) {
       
 11032         return type.replace(WILD_TYPE_RE, "*$2$3");
       
 11033     }),
       
 11034 
       
 11035     /**
       
 11036      * If the instance has a prefix attribute and the
       
 11037      * event type is not prefixed, the instance prefix is
       
 11038      * applied to the supplied type.
       
 11039      * @method _getType
       
 11040      * @private
       
 11041      */
       
 11042     _getType = function(type, pre) {
       
 11043 
       
 11044         if (!pre || type.indexOf(PREFIX_DELIMITER) > -1) {
       
 11045             return type;
       
 11046         }
       
 11047 
       
 11048         return pre + PREFIX_DELIMITER + type;
       
 11049     },
       
 11050 
       
 11051     /**
       
 11052      * Returns an array with the detach key (if provided),
       
 11053      * and the prefixed event name from _getType
       
 11054      * Y.on('detachcategory| menu:click', fn)
       
 11055      * @method _parseType
       
 11056      * @private
       
 11057      */
       
 11058     _parseType = Y.cached(function(type, pre) {
       
 11059 
       
 11060         var t = type, detachcategory, after, i;
       
 11061 
       
 11062         if (!L.isString(t)) {
       
 11063             return t;
       
 11064         }
       
 11065 
       
 11066         i = t.indexOf(AFTER_PREFIX);
       
 11067 
       
 11068         if (i > -1) {
       
 11069             after = true;
       
 11070             t = t.substr(AFTER_PREFIX.length);
       
 11071         }
       
 11072 
       
 11073         i = t.indexOf(CATEGORY_DELIMITER);
       
 11074 
       
 11075         if (i > -1) {
       
 11076             detachcategory = t.substr(0, (i));
       
 11077             t = t.substr(i+1);
       
 11078             if (t === '*') {
       
 11079                 t = null;
       
 11080             }
       
 11081         }
       
 11082 
       
 11083         // detach category, full type with instance prefix, is this an after listener, short type
       
 11084         return [detachcategory, (pre) ? _getType(t, pre) : t, after, t];
       
 11085     }),
       
 11086 
       
 11087     ET = function(opts) {
       
 11088 
       
 11089         var etState = this._yuievt,
       
 11090             etConfig;
       
 11091 
       
 11092         if (!etState) {
       
 11093             etState = this._yuievt = {
       
 11094                 events: {},    // PERF: Not much point instantiating lazily. We're bound to have events
       
 11095                 targets: null, // PERF: Instantiate lazily, if user actually adds target,
       
 11096                 config: {
       
 11097                     host: this,
       
 11098                     context: this
       
 11099                 },
       
 11100                 chain: Y.config.chain
       
 11101             };
       
 11102         }
       
 11103 
       
 11104         etConfig = etState.config;
       
 11105 
       
 11106         if (opts) {
       
 11107             mixConfigs(etConfig, opts, true);
       
 11108 
       
 11109             if (opts.chain !== undefined) {
       
 11110                 etState.chain = opts.chain;
       
 11111             }
       
 11112 
       
 11113             if (opts.prefix) {
       
 11114                 etConfig.prefix = opts.prefix;
       
 11115             }
       
 11116         }
       
 11117     };
       
 11118 
       
 11119 ET.prototype = {
       
 11120 
       
 11121     constructor: ET,
       
 11122 
       
 11123     /**
       
 11124      * Listen to a custom event hosted by this object one time.
       
 11125      * This is the equivalent to <code>on</code> except the
       
 11126      * listener is immediatelly detached when it is executed.
       
 11127      * @method once
       
 11128      * @param {String} type The name of the event
       
 11129      * @param {Function} fn The callback to execute in response to the event
       
 11130      * @param {Object} [context] Override `this` object in callback
       
 11131      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11132      * @return {EventHandle} A subscription handle capable of detaching the
       
 11133      *                       subscription
       
 11134      */
       
 11135     once: function() {
       
 11136         var handle = this.on.apply(this, arguments);
       
 11137         handle.batch(function(hand) {
       
 11138             if (hand.sub) {
       
 11139                 hand.sub.once = true;
       
 11140             }
       
 11141         });
       
 11142         return handle;
       
 11143     },
       
 11144 
       
 11145     /**
       
 11146      * Listen to a custom event hosted by this object one time.
       
 11147      * This is the equivalent to <code>after</code> except the
       
 11148      * listener is immediatelly detached when it is executed.
       
 11149      * @method onceAfter
       
 11150      * @param {String} type The name of the event
       
 11151      * @param {Function} fn The callback to execute in response to the event
       
 11152      * @param {Object} [context] Override `this` object in callback
       
 11153      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11154      * @return {EventHandle} A subscription handle capable of detaching that
       
 11155      *                       subscription
       
 11156      */
       
 11157     onceAfter: function() {
       
 11158         var handle = this.after.apply(this, arguments);
       
 11159         handle.batch(function(hand) {
       
 11160             if (hand.sub) {
       
 11161                 hand.sub.once = true;
       
 11162             }
       
 11163         });
       
 11164         return handle;
       
 11165     },
       
 11166 
       
 11167     /**
       
 11168      * Takes the type parameter passed to 'on' and parses out the
       
 11169      * various pieces that could be included in the type.  If the
       
 11170      * event type is passed without a prefix, it will be expanded
       
 11171      * to include the prefix one is supplied or the event target
       
 11172      * is configured with a default prefix.
       
 11173      * @method parseType
       
 11174      * @param {String} type the type
       
 11175      * @param {String} [pre=this._yuievt.config.prefix] the prefix
       
 11176      * @since 3.3.0
       
 11177      * @return {Array} an array containing:
       
 11178      *  * the detach category, if supplied,
       
 11179      *  * the prefixed event type,
       
 11180      *  * whether or not this is an after listener,
       
 11181      *  * the supplied event type
       
 11182      */
       
 11183     parseType: function(type, pre) {
       
 11184         return _parseType(type, pre || this._yuievt.config.prefix);
       
 11185     },
       
 11186 
       
 11187     /**
       
 11188      * Subscribe a callback function to a custom event fired by this object or
       
 11189      * from an object that bubbles its events to this object.
       
 11190      *
       
 11191      * Callback functions for events published with `emitFacade = true` will
       
 11192      * receive an `EventFacade` as the first argument (typically named "e").
       
 11193      * These callbacks can then call `e.preventDefault()` to disable the
       
 11194      * behavior published to that event's `defaultFn`.  See the `EventFacade`
       
 11195      * API for all available properties and methods. Subscribers to
       
 11196      * non-`emitFacade` events will receive the arguments passed to `fire()`
       
 11197      * after the event name.
       
 11198      *
       
 11199      * To subscribe to multiple events at once, pass an object as the first
       
 11200      * argument, where the key:value pairs correspond to the eventName:callback,
       
 11201      * or pass an array of event names as the first argument to subscribe to
       
 11202      * all listed events with the same callback.
       
 11203      *
       
 11204      * Returning `false` from a callback is supported as an alternative to
       
 11205      * calling `e.preventDefault(); e.stopPropagation();`.  However, it is
       
 11206      * recommended to use the event methods whenever possible.
       
 11207      *
       
 11208      * @method on
       
 11209      * @param {String} type The name of the event
       
 11210      * @param {Function} fn The callback to execute in response to the event
       
 11211      * @param {Object} [context] Override `this` object in callback
       
 11212      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11213      * @return {EventHandle} A subscription handle capable of detaching that
       
 11214      *                       subscription
       
 11215      */
       
 11216     on: function(type, fn, context) {
       
 11217 
       
 11218         var yuievt = this._yuievt,
       
 11219             parts = _parseType(type, yuievt.config.prefix), f, c, args, ret, ce,
       
 11220             detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype,
       
 11221             Node = Y.Node, n, domevent, isArr;
       
 11222 
       
 11223         // full name, args, detachcategory, after
       
 11224         this._monitor('attach', parts[1], {
       
 11225             args: arguments,
       
 11226             category: parts[0],
       
 11227             after: parts[2]
       
 11228         });
       
 11229 
       
 11230         if (L.isObject(type)) {
       
 11231 
       
 11232             if (L.isFunction(type)) {
       
 11233                 return Y.Do.before.apply(Y.Do, arguments);
       
 11234             }
       
 11235 
       
 11236             f = fn;
       
 11237             c = context;
       
 11238             args = nativeSlice.call(arguments, 0);
       
 11239             ret = [];
       
 11240 
       
 11241             if (L.isArray(type)) {
       
 11242                 isArr = true;
       
 11243             }
       
 11244 
       
 11245             after = type._after;
       
 11246             delete type._after;
       
 11247 
       
 11248             Y.each(type, function(v, k) {
       
 11249 
       
 11250                 if (L.isObject(v)) {
       
 11251                     f = v.fn || ((L.isFunction(v)) ? v : f);
       
 11252                     c = v.context || c;
       
 11253                 }
       
 11254 
       
 11255                 var nv = (after) ? AFTER_PREFIX : '';
       
 11256 
       
 11257                 args[0] = nv + ((isArr) ? v : k);
       
 11258                 args[1] = f;
       
 11259                 args[2] = c;
       
 11260 
       
 11261                 ret.push(this.on.apply(this, args));
       
 11262 
       
 11263             }, this);
       
 11264 
       
 11265             return (yuievt.chain) ? this : new Y.EventHandle(ret);
       
 11266         }
       
 11267 
       
 11268         detachcategory = parts[0];
       
 11269         after = parts[2];
       
 11270         shorttype = parts[3];
       
 11271 
       
 11272         // extra redirection so we catch adaptor events too.  take a look at this.
       
 11273         if (Node && Y.instanceOf(this, Node) && (shorttype in Node.DOM_EVENTS)) {
       
 11274             args = nativeSlice.call(arguments, 0);
       
 11275             args.splice(2, 0, Node.getDOMNode(this));
       
 11276             return Y.on.apply(Y, args);
       
 11277         }
       
 11278 
       
 11279         type = parts[1];
       
 11280 
       
 11281         if (Y.instanceOf(this, YUI)) {
       
 11282 
       
 11283             adapt = Y.Env.evt.plugins[type];
       
 11284             args  = nativeSlice.call(arguments, 0);
       
 11285             args[0] = shorttype;
       
 11286 
       
 11287             if (Node) {
       
 11288                 n = args[2];
       
 11289 
       
 11290                 if (Y.instanceOf(n, Y.NodeList)) {
       
 11291                     n = Y.NodeList.getDOMNodes(n);
       
 11292                 } else if (Y.instanceOf(n, Node)) {
       
 11293                     n = Node.getDOMNode(n);
       
 11294                 }
       
 11295 
       
 11296                 domevent = (shorttype in Node.DOM_EVENTS);
       
 11297 
       
 11298                 // Captures both DOM events and event plugins.
       
 11299                 if (domevent) {
       
 11300                     args[2] = n;
       
 11301                 }
       
 11302             }
       
 11303 
       
 11304             // check for the existance of an event adaptor
       
 11305             if (adapt) {
       
 11306                 handle = adapt.on.apply(Y, args);
       
 11307             } else if ((!type) || domevent) {
       
 11308                 handle = Y.Event._attach(args);
       
 11309             }
       
 11310 
       
 11311         }
       
 11312 
       
 11313         if (!handle) {
       
 11314             ce = yuievt.events[type] || this.publish(type);
       
 11315             handle = ce._on(fn, context, (arguments.length > 3) ? nativeSlice.call(arguments, 3) : null, (after) ? 'after' : true);
       
 11316 
       
 11317             // TODO: More robust regex, accounting for category
       
 11318             if (type.indexOf("*:") !== -1) {
       
 11319                 this._hasSiblings = true;
       
 11320             }
       
 11321         }
       
 11322 
       
 11323         if (detachcategory) {
       
 11324             store[detachcategory] = store[detachcategory] || {};
       
 11325             store[detachcategory][type] = store[detachcategory][type] || [];
       
 11326             store[detachcategory][type].push(handle);
       
 11327         }
       
 11328 
       
 11329         return (yuievt.chain) ? this : handle;
       
 11330 
       
 11331     },
       
 11332 
       
 11333     /**
       
 11334      * subscribe to an event
       
 11335      * @method subscribe
       
 11336      * @deprecated use on
       
 11337      */
       
 11338     subscribe: function() {
       
 11339         return this.on.apply(this, arguments);
       
 11340     },
       
 11341 
       
 11342     /**
       
 11343      * Detach one or more listeners the from the specified event
       
 11344      * @method detach
       
 11345      * @param type {string|Object}   Either the handle to the subscriber or the
       
 11346      *                        type of event.  If the type
       
 11347      *                        is not specified, it will attempt to remove
       
 11348      *                        the listener from all hosted events.
       
 11349      * @param fn   {Function} The subscribed function to unsubscribe, if not
       
 11350      *                          supplied, all subscribers will be removed.
       
 11351      * @param context  {Object}   The custom object passed to subscribe.  This is
       
 11352      *                        optional, but if supplied will be used to
       
 11353      *                        disambiguate multiple listeners that are the same
       
 11354      *                        (e.g., you subscribe many object using a function
       
 11355      *                        that lives on the prototype)
       
 11356      * @return {EventTarget} the host
       
 11357      */
       
 11358     detach: function(type, fn, context) {
       
 11359 
       
 11360         var evts = this._yuievt.events,
       
 11361             i,
       
 11362             Node = Y.Node,
       
 11363             isNode = Node && (Y.instanceOf(this, Node));
       
 11364 
       
 11365         // detachAll disabled on the Y instance.
       
 11366         if (!type && (this !== Y)) {
       
 11367             for (i in evts) {
       
 11368                 if (evts.hasOwnProperty(i)) {
       
 11369                     evts[i].detach(fn, context);
       
 11370                 }
       
 11371             }
       
 11372             if (isNode) {
       
 11373                 Y.Event.purgeElement(Node.getDOMNode(this));
       
 11374             }
       
 11375 
       
 11376             return this;
       
 11377         }
       
 11378 
       
 11379         var parts = _parseType(type, this._yuievt.config.prefix),
       
 11380         detachcategory = L.isArray(parts) ? parts[0] : null,
       
 11381         shorttype = (parts) ? parts[3] : null,
       
 11382         adapt, store = Y.Env.evt.handles, detachhost, cat, args,
       
 11383         ce,
       
 11384 
       
 11385         keyDetacher = function(lcat, ltype, host) {
       
 11386             var handles = lcat[ltype], ce, i;
       
 11387             if (handles) {
       
 11388                 for (i = handles.length - 1; i >= 0; --i) {
       
 11389                     ce = handles[i].evt;
       
 11390                     if (ce.host === host || ce.el === host) {
       
 11391                         handles[i].detach();
       
 11392                     }
       
 11393                 }
       
 11394             }
       
 11395         };
       
 11396 
       
 11397         if (detachcategory) {
       
 11398 
       
 11399             cat = store[detachcategory];
       
 11400             type = parts[1];
       
 11401             detachhost = (isNode) ? Y.Node.getDOMNode(this) : this;
       
 11402 
       
 11403             if (cat) {
       
 11404                 if (type) {
       
 11405                     keyDetacher(cat, type, detachhost);
       
 11406                 } else {
       
 11407                     for (i in cat) {
       
 11408                         if (cat.hasOwnProperty(i)) {
       
 11409                             keyDetacher(cat, i, detachhost);
       
 11410                         }
       
 11411                     }
       
 11412                 }
       
 11413 
       
 11414                 return this;
       
 11415             }
       
 11416 
       
 11417         // If this is an event handle, use it to detach
       
 11418         } else if (L.isObject(type) && type.detach) {
       
 11419             type.detach();
       
 11420             return this;
       
 11421         // extra redirection so we catch adaptor events too.  take a look at this.
       
 11422         } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) {
       
 11423             args = nativeSlice.call(arguments, 0);
       
 11424             args[2] = Node.getDOMNode(this);
       
 11425             Y.detach.apply(Y, args);
       
 11426             return this;
       
 11427         }
       
 11428 
       
 11429         adapt = Y.Env.evt.plugins[shorttype];
       
 11430 
       
 11431         // The YUI instance handles DOM events and adaptors
       
 11432         if (Y.instanceOf(this, YUI)) {
       
 11433             args = nativeSlice.call(arguments, 0);
       
 11434             // use the adaptor specific detach code if
       
 11435             if (adapt && adapt.detach) {
       
 11436                 adapt.detach.apply(Y, args);
       
 11437                 return this;
       
 11438             // DOM event fork
       
 11439             } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
       
 11440                 args[0] = type;
       
 11441                 Y.Event.detach.apply(Y.Event, args);
       
 11442                 return this;
       
 11443             }
       
 11444         }
       
 11445 
       
 11446         // ce = evts[type];
       
 11447         ce = evts[parts[1]];
       
 11448         if (ce) {
       
 11449             ce.detach(fn, context);
       
 11450         }
       
 11451 
       
 11452         return this;
       
 11453     },
       
 11454 
       
 11455     /**
       
 11456      * detach a listener
       
 11457      * @method unsubscribe
       
 11458      * @deprecated use detach
       
 11459      */
       
 11460     unsubscribe: function() {
       
 11461         return this.detach.apply(this, arguments);
       
 11462     },
       
 11463 
       
 11464     /**
       
 11465      * Removes all listeners from the specified event.  If the event type
       
 11466      * is not specified, all listeners from all hosted custom events will
       
 11467      * be removed.
       
 11468      * @method detachAll
       
 11469      * @param type {String}   The type, or name of the event
       
 11470      */
       
 11471     detachAll: function(type) {
       
 11472         return this.detach(type);
       
 11473     },
       
 11474 
       
 11475     /**
       
 11476      * Removes all listeners from the specified event.  If the event type
       
 11477      * is not specified, all listeners from all hosted custom events will
       
 11478      * be removed.
       
 11479      * @method unsubscribeAll
       
 11480      * @param type {String}   The type, or name of the event
       
 11481      * @deprecated use detachAll
       
 11482      */
       
 11483     unsubscribeAll: function() {
       
 11484         return this.detachAll.apply(this, arguments);
       
 11485     },
       
 11486 
       
 11487     /**
       
 11488      * Creates a new custom event of the specified type.  If a custom event
       
 11489      * by that name already exists, it will not be re-created.  In either
       
 11490      * case the custom event is returned.
       
 11491      *
       
 11492      * @method publish
       
 11493      *
       
 11494      * @param type {String} the type, or name of the event
       
 11495      * @param opts {object} optional config params.  Valid properties are:
       
 11496      *
       
 11497      *  <ul>
       
 11498      *    <li>
       
 11499      *   'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
       
 11500      *    </li>
       
 11501      *    <li>
       
 11502      *   'bubbles': whether or not this event bubbles (true)
       
 11503      *              Events can only bubble if emitFacade is true.
       
 11504      *    </li>
       
 11505      *    <li>
       
 11506      *   'context': the default execution context for the listeners (this)
       
 11507      *    </li>
       
 11508      *    <li>
       
 11509      *   'defaultFn': the default function to execute when this event fires if preventDefault was not called
       
 11510      *    </li>
       
 11511      *    <li>
       
 11512      *   'emitFacade': whether or not this event emits a facade (false)
       
 11513      *    </li>
       
 11514      *    <li>
       
 11515      *   'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click'
       
 11516      *    </li>
       
 11517      *    <li>
       
 11518      *   'fireOnce': if an event is configured to fire once, new subscribers after
       
 11519      *   the fire will be notified immediately.
       
 11520      *    </li>
       
 11521      *    <li>
       
 11522      *   'async': fireOnce event listeners will fire synchronously if the event has already
       
 11523      *    fired unless async is true.
       
 11524      *    </li>
       
 11525      *    <li>
       
 11526      *   'preventable': whether or not preventDefault() has an effect (true)
       
 11527      *    </li>
       
 11528      *    <li>
       
 11529      *   'preventedFn': a function that is executed when preventDefault is called
       
 11530      *    </li>
       
 11531      *    <li>
       
 11532      *   'queuable': whether or not this event can be queued during bubbling (false)
       
 11533      *    </li>
       
 11534      *    <li>
       
 11535      *   'silent': if silent is true, debug messages are not provided for this event.
       
 11536      *    </li>
       
 11537      *    <li>
       
 11538      *   'stoppedFn': a function that is executed when stopPropagation is called
       
 11539      *    </li>
       
 11540      *
       
 11541      *    <li>
       
 11542      *   'monitored': specifies whether or not this event should send notifications about
       
 11543      *   when the event has been attached, detached, or published.
       
 11544      *    </li>
       
 11545      *    <li>
       
 11546      *   'type': the event type (valid option if not provided as the first parameter to publish)
       
 11547      *    </li>
       
 11548      *  </ul>
       
 11549      *
       
 11550      *  @return {CustomEvent} the custom event
       
 11551      *
       
 11552      */
       
 11553     publish: function(type, opts) {
       
 11554 
       
 11555         var ret,
       
 11556             etState = this._yuievt,
       
 11557             etConfig = etState.config,
       
 11558             pre = etConfig.prefix;
       
 11559 
       
 11560         if (typeof type === "string")  {
       
 11561             if (pre) {
       
 11562                 type = _getType(type, pre);
       
 11563             }
       
 11564             ret = this._publish(type, etConfig, opts);
       
 11565         } else {
       
 11566             ret = {};
       
 11567 
       
 11568             Y.each(type, function(v, k) {
       
 11569                 if (pre) {
       
 11570                     k = _getType(k, pre);
       
 11571                 }
       
 11572                 ret[k] = this._publish(k, etConfig, v || opts);
       
 11573             }, this);
       
 11574 
       
 11575         }
       
 11576 
       
 11577         return ret;
       
 11578     },
       
 11579 
       
 11580     /**
       
 11581      * Returns the fully qualified type, given a short type string.
       
 11582      * That is, returns "foo:bar" when given "bar" if "foo" is the configured prefix.
       
 11583      *
       
 11584      * NOTE: This method, unlike _getType, does no checking of the value passed in, and
       
 11585      * is designed to be used with the low level _publish() method, for critical path
       
 11586      * implementations which need to fast-track publish for performance reasons.
       
 11587      *
       
 11588      * @method _getFullType
       
 11589      * @private
       
 11590      * @param {String} type The short type to prefix
       
 11591      * @return {String} The prefixed type, if a prefix is set, otherwise the type passed in
       
 11592      */
       
 11593     _getFullType : function(type) {
       
 11594 
       
 11595         var pre = this._yuievt.config.prefix;
       
 11596 
       
 11597         if (pre) {
       
 11598             return pre + PREFIX_DELIMITER + type;
       
 11599         } else {
       
 11600             return type;
       
 11601         }
       
 11602     },
       
 11603 
       
 11604     /**
       
 11605      * The low level event publish implementation. It expects all the massaging to have been done
       
 11606      * outside of this method. e.g. the `type` to `fullType` conversion. It's designed to be a fast
       
 11607      * path publish, which can be used by critical code paths to improve performance.
       
 11608      *
       
 11609      * @method _publish
       
 11610      * @private
       
 11611      * @param {String} fullType The prefixed type of the event to publish.
       
 11612      * @param {Object} etOpts The EventTarget specific configuration to mix into the published event.
       
 11613      * @param {Object} ceOpts The publish specific configuration to mix into the published event.
       
 11614      * @return {CustomEvent} The published event. If called without `etOpts` or `ceOpts`, this will
       
 11615      * be the default `CustomEvent` instance, and can be configured independently.
       
 11616      */
       
 11617     _publish : function(fullType, etOpts, ceOpts) {
       
 11618 
       
 11619         var ce,
       
 11620             etState = this._yuievt,
       
 11621             etConfig = etState.config,
       
 11622             host = etConfig.host,
       
 11623             context = etConfig.context,
       
 11624             events = etState.events;
       
 11625 
       
 11626         ce = events[fullType];
       
 11627 
       
 11628         // PERF: Hate to pull the check out of monitor, but trying to keep critical path tight.
       
 11629         if ((etConfig.monitored && !ce) || (ce && ce.monitored)) {
       
 11630             this._monitor('publish', fullType, {
       
 11631                 args: arguments
       
 11632             });
       
 11633         }
       
 11634 
       
 11635         if (!ce) {
       
 11636             // Publish event
       
 11637             ce = events[fullType] = new Y.CustomEvent(fullType, etOpts);
       
 11638 
       
 11639             if (!etOpts) {
       
 11640                 ce.host = host;
       
 11641                 ce.context = context;
       
 11642             }
       
 11643         }
       
 11644 
       
 11645         if (ceOpts) {
       
 11646             mixConfigs(ce, ceOpts, true);
       
 11647         }
       
 11648 
       
 11649         return ce;
       
 11650     },
       
 11651 
       
 11652     /**
       
 11653      * This is the entry point for the event monitoring system.
       
 11654      * You can monitor 'attach', 'detach', 'fire', and 'publish'.
       
 11655      * When configured, these events generate an event.  click ->
       
 11656      * click_attach, click_detach, click_publish -- these can
       
 11657      * be subscribed to like other events to monitor the event
       
 11658      * system.  Inividual published events can have monitoring
       
 11659      * turned on or off (publish can't be turned off before it
       
 11660      * it published) by setting the events 'monitor' config.
       
 11661      *
       
 11662      * @method _monitor
       
 11663      * @param what {String} 'attach', 'detach', 'fire', or 'publish'
       
 11664      * @param eventType {String|CustomEvent} The prefixed name of the event being monitored, or the CustomEvent object.
       
 11665      * @param o {Object} Information about the event interaction, such as
       
 11666      *                  fire() args, subscription category, publish config
       
 11667      * @private
       
 11668      */
       
 11669     _monitor: function(what, eventType, o) {
       
 11670         var monitorevt, ce, type;
       
 11671 
       
 11672         if (eventType) {
       
 11673             if (typeof eventType === "string") {
       
 11674                 type = eventType;
       
 11675                 ce = this.getEvent(eventType, true);
       
 11676             } else {
       
 11677                 ce = eventType;
       
 11678                 type = eventType.type;
       
 11679             }
       
 11680 
       
 11681             if ((this._yuievt.config.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) {
       
 11682                 monitorevt = type + '_' + what;
       
 11683                 o.monitored = what;
       
 11684                 this.fire.call(this, monitorevt, o);
       
 11685             }
       
 11686         }
       
 11687     },
       
 11688 
       
 11689     /**
       
 11690      * Fire a custom event by name.  The callback functions will be executed
       
 11691      * from the context specified when the event was created, and with the
       
 11692      * following parameters.
       
 11693      *
       
 11694      * If the custom event object hasn't been created, then the event hasn't
       
 11695      * been published and it has no subscribers.  For performance sake, we
       
 11696      * immediate exit in this case.  This means the event won't bubble, so
       
 11697      * if the intention is that a bubble target be notified, the event must
       
 11698      * be published on this object first.
       
 11699      *
       
 11700      * The first argument is the event type, and any additional arguments are
       
 11701      * passed to the listeners as parameters.  If the first of these is an
       
 11702      * object literal, and the event is configured to emit an event facade,
       
 11703      * that object is mixed into the event facade and the facade is provided
       
 11704      * in place of the original object.
       
 11705      *
       
 11706      * @method fire
       
 11707      * @param type {String|Object} The type of the event, or an object that contains
       
 11708      * a 'type' property.
       
 11709      * @param arguments {Object*} an arbitrary set of parameters to pass to
       
 11710      * the handler.  If the first of these is an object literal and the event is
       
 11711      * configured to emit an event facade, the event facade will replace that
       
 11712      * parameter after the properties the object literal contains are copied to
       
 11713      * the event facade.
       
 11714      * @return {EventTarget} the event host
       
 11715      */
       
 11716     fire: function(type) {
       
 11717 
       
 11718         var typeIncluded = (typeof type === "string"),
       
 11719             argCount = arguments.length,
       
 11720             t = type,
       
 11721             yuievt = this._yuievt,
       
 11722             etConfig = yuievt.config,
       
 11723             pre = etConfig.prefix,
       
 11724             ret,
       
 11725             ce,
       
 11726             ce2,
       
 11727             args;
       
 11728 
       
 11729         if (typeIncluded && argCount <= 3) {
       
 11730 
       
 11731             // PERF: Try to avoid slice/iteration for the common signatures
       
 11732 
       
 11733             // Most common
       
 11734             if (argCount === 2) {
       
 11735                 args = [arguments[1]]; // fire("foo", {})
       
 11736             } else if (argCount === 3) {
       
 11737                 args = [arguments[1], arguments[2]]; // fire("foo", {}, opts)
       
 11738             } else {
       
 11739                 args = []; // fire("foo")
       
 11740             }
       
 11741 
       
 11742         } else {
       
 11743             args = nativeSlice.call(arguments, ((typeIncluded) ? 1 : 0));
       
 11744         }
       
 11745 
       
 11746         if (!typeIncluded) {
       
 11747             t = (type && type.type);
       
 11748         }
       
 11749 
       
 11750         if (pre) {
       
 11751             t = _getType(t, pre);
       
 11752         }
       
 11753 
       
 11754         ce = yuievt.events[t];
       
 11755 
       
 11756         if (this._hasSiblings) {
       
 11757             ce2 = this.getSibling(t, ce);
       
 11758 
       
 11759             if (ce2 && !ce) {
       
 11760                 ce = this.publish(t);
       
 11761             }
       
 11762         }
       
 11763 
       
 11764         // PERF: trying to avoid function call, since this is a critical path
       
 11765         if ((etConfig.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) {
       
 11766             this._monitor('fire', (ce || t), {
       
 11767                 args: args
       
 11768             });
       
 11769         }
       
 11770 
       
 11771         // this event has not been published or subscribed to
       
 11772         if (!ce) {
       
 11773             if (yuievt.hasTargets) {
       
 11774                 return this.bubble({ type: t }, args, this);
       
 11775             }
       
 11776 
       
 11777             // otherwise there is nothing to be done
       
 11778             ret = true;
       
 11779         } else {
       
 11780 
       
 11781             if (ce2) {
       
 11782                 ce.sibling = ce2;
       
 11783             }
       
 11784 
       
 11785             ret = ce._fire(args);
       
 11786         }
       
 11787 
       
 11788         return (yuievt.chain) ? this : ret;
       
 11789     },
       
 11790 
       
 11791     getSibling: function(type, ce) {
       
 11792         var ce2;
       
 11793 
       
 11794         // delegate to *:type events if there are subscribers
       
 11795         if (type.indexOf(PREFIX_DELIMITER) > -1) {
       
 11796             type = _wildType(type);
       
 11797             ce2 = this.getEvent(type, true);
       
 11798             if (ce2) {
       
 11799                 ce2.applyConfig(ce);
       
 11800                 ce2.bubbles = false;
       
 11801                 ce2.broadcast = 0;
       
 11802             }
       
 11803         }
       
 11804 
       
 11805         return ce2;
       
 11806     },
       
 11807 
       
 11808     /**
       
 11809      * Returns the custom event of the provided type has been created, a
       
 11810      * falsy value otherwise
       
 11811      * @method getEvent
       
 11812      * @param type {String} the type, or name of the event
       
 11813      * @param prefixed {String} if true, the type is prefixed already
       
 11814      * @return {CustomEvent} the custom event or null
       
 11815      */
       
 11816     getEvent: function(type, prefixed) {
       
 11817         var pre, e;
       
 11818 
       
 11819         if (!prefixed) {
       
 11820             pre = this._yuievt.config.prefix;
       
 11821             type = (pre) ? _getType(type, pre) : type;
       
 11822         }
       
 11823         e = this._yuievt.events;
       
 11824         return e[type] || null;
       
 11825     },
       
 11826 
       
 11827     /**
       
 11828      * Subscribe to a custom event hosted by this object.  The
       
 11829      * supplied callback will execute after any listeners add
       
 11830      * via the subscribe method, and after the default function,
       
 11831      * if configured for the event, has executed.
       
 11832      *
       
 11833      * @method after
       
 11834      * @param {String} type The name of the event
       
 11835      * @param {Function} fn The callback to execute in response to the event
       
 11836      * @param {Object} [context] Override `this` object in callback
       
 11837      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11838      * @return {EventHandle} A subscription handle capable of detaching the
       
 11839      *                       subscription
       
 11840      */
       
 11841     after: function(type, fn) {
       
 11842 
       
 11843         var a = nativeSlice.call(arguments, 0);
       
 11844 
       
 11845         switch (L.type(type)) {
       
 11846             case 'function':
       
 11847                 return Y.Do.after.apply(Y.Do, arguments);
       
 11848             case 'array':
       
 11849             //     YArray.each(a[0], function(v) {
       
 11850             //         v = AFTER_PREFIX + v;
       
 11851             //     });
       
 11852             //     break;
       
 11853             case 'object':
       
 11854                 a[0]._after = true;
       
 11855                 break;
       
 11856             default:
       
 11857                 a[0] = AFTER_PREFIX + type;
       
 11858         }
       
 11859 
       
 11860         return this.on.apply(this, a);
       
 11861 
       
 11862     },
       
 11863 
       
 11864     /**
       
 11865      * Executes the callback before a DOM event, custom event
       
 11866      * or method.  If the first argument is a function, it
       
 11867      * is assumed the target is a method.  For DOM and custom
       
 11868      * events, this is an alias for Y.on.
       
 11869      *
       
 11870      * For DOM and custom events:
       
 11871      * type, callback, context, 0-n arguments
       
 11872      *
       
 11873      * For methods:
       
 11874      * callback, object (method host), methodName, context, 0-n arguments
       
 11875      *
       
 11876      * @method before
       
 11877      * @return detach handle
       
 11878      */
       
 11879     before: function() {
       
 11880         return this.on.apply(this, arguments);
       
 11881     }
       
 11882 
       
 11883 };
       
 11884 
       
 11885 Y.EventTarget = ET;
       
 11886 
       
 11887 // make Y an event target
       
 11888 Y.mix(Y, ET.prototype);
       
 11889 ET.call(Y, { bubbles: false });
       
 11890 
       
 11891 YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
       
 11892 
       
 11893 /**
       
 11894  * Hosts YUI page level events.  This is where events bubble to
       
 11895  * when the broadcast config is set to 2.  This property is
       
 11896  * only available if the custom event module is loaded.
       
 11897  * @property Global
       
 11898  * @type EventTarget
       
 11899  * @for YUI
       
 11900  */
       
 11901 Y.Global = YUI.Env.globalEvents;
       
 11902 
       
 11903 // @TODO implement a global namespace function on Y.Global?
       
 11904 
       
 11905 /**
       
 11906 `Y.on()` can do many things:
       
 11907 
       
 11908 <ul>
       
 11909     <li>Subscribe to custom events `publish`ed and `fire`d from Y</li>
       
 11910     <li>Subscribe to custom events `publish`ed with `broadcast` 1 or 2 and
       
 11911         `fire`d from any object in the YUI instance sandbox</li>
       
 11912     <li>Subscribe to DOM events</li>
       
 11913     <li>Subscribe to the execution of a method on any object, effectively
       
 11914     treating that method as an event</li>
       
 11915 </ul>
       
 11916 
       
 11917 For custom event subscriptions, pass the custom event name as the first argument
       
 11918 and callback as the second. The `this` object in the callback will be `Y` unless
       
 11919 an override is passed as the third argument.
       
 11920 
       
 11921     Y.on('io:complete', function () {
       
 11922         Y.MyApp.updateStatus('Transaction complete');
       
 11923     });
       
 11924 
       
 11925 To subscribe to DOM events, pass the name of a DOM event as the first argument
       
 11926 and a CSS selector string as the third argument after the callback function.
       
 11927 Alternately, the third argument can be a `Node`, `NodeList`, `HTMLElement`,
       
 11928 array, or simply omitted (the default is the `window` object).
       
 11929 
       
 11930     Y.on('click', function (e) {
       
 11931         e.preventDefault();
       
 11932 
       
 11933         // proceed with ajax form submission
       
 11934         var url = this.get('action');
       
 11935         ...
       
 11936     }, '#my-form');
       
 11937 
       
 11938 The `this` object in DOM event callbacks will be the `Node` targeted by the CSS
       
 11939 selector or other identifier.
       
 11940 
       
 11941 `on()` subscribers for DOM events or custom events `publish`ed with a
       
 11942 `defaultFn` can prevent the default behavior with `e.preventDefault()` from the
       
 11943 event object passed as the first parameter to the subscription callback.
       
 11944 
       
 11945 To subscribe to the execution of an object method, pass arguments corresponding to the call signature for
       
 11946 <a href="../classes/Do.html#methods_before">`Y.Do.before(...)`</a>.
       
 11947 
       
 11948 NOTE: The formal parameter list below is for events, not for function
       
 11949 injection.  See `Y.Do.before` for that signature.
       
 11950 
       
 11951 @method on
       
 11952 @param {String} type DOM or custom event name
       
 11953 @param {Function} fn The callback to execute in response to the event
       
 11954 @param {Object} [context] Override `this` object in callback
       
 11955 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11956 @return {EventHandle} A subscription handle capable of detaching the
       
 11957                       subscription
       
 11958 @see Do.before
       
 11959 @for YUI
       
 11960 **/
       
 11961 
       
 11962 /**
       
 11963 Listen for an event one time.  Equivalent to `on()`, except that
       
 11964 the listener is immediately detached when executed.
       
 11965 
       
 11966 See the <a href="#methods_on">`on()` method</a> for additional subscription
       
 11967 options.
       
 11968 
       
 11969 @see on
       
 11970 @method once
       
 11971 @param {String} type DOM or custom event name
       
 11972 @param {Function} fn The callback to execute in response to the event
       
 11973 @param {Object} [context] Override `this` object in callback
       
 11974 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11975 @return {EventHandle} A subscription handle capable of detaching the
       
 11976                       subscription
       
 11977 @for YUI
       
 11978 **/
       
 11979 
       
 11980 /**
       
 11981 Listen for an event one time.  Equivalent to `once()`, except, like `after()`,
       
 11982 the subscription callback executes after all `on()` subscribers and the event's
       
 11983 `defaultFn` (if configured) have executed.  Like `after()` if any `on()` phase
       
 11984 subscriber calls `e.preventDefault()`, neither the `defaultFn` nor the `after()`
       
 11985 subscribers will execute.
       
 11986 
       
 11987 The listener is immediately detached when executed.
       
 11988 
       
 11989 See the <a href="#methods_on">`on()` method</a> for additional subscription
       
 11990 options.
       
 11991 
       
 11992 @see once
       
 11993 @method onceAfter
       
 11994 @param {String} type The custom event name
       
 11995 @param {Function} fn The callback to execute in response to the event
       
 11996 @param {Object} [context] Override `this` object in callback
       
 11997 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11998 @return {EventHandle} A subscription handle capable of detaching the
       
 11999                       subscription
       
 12000 @for YUI
       
 12001 **/
       
 12002 
       
 12003 /**
       
 12004 Like `on()`, this method creates a subscription to a custom event or to the
       
 12005 execution of a method on an object.
       
 12006 
       
 12007 For events, `after()` subscribers are executed after the event's
       
 12008 `defaultFn` unless `e.preventDefault()` was called from an `on()` subscriber.
       
 12009 
       
 12010 See the <a href="#methods_on">`on()` method</a> for additional subscription
       
 12011 options.
       
 12012 
       
 12013 NOTE: The subscription signature shown is for events, not for function
       
 12014 injection.  See <a href="../classes/Do.html#methods_after">`Y.Do.after`</a>
       
 12015 for that signature.
       
 12016 
       
 12017 @see on
       
 12018 @see Do.after
       
 12019 @method after
       
 12020 @param {String} type The custom event name
       
 12021 @param {Function} fn The callback to execute in response to the event
       
 12022 @param {Object} [context] Override `this` object in callback
       
 12023 @param {Any} [args*] 0..n additional arguments to supply to the subscriber
       
 12024 @return {EventHandle} A subscription handle capable of detaching the
       
 12025                       subscription
       
 12026 @for YUI
       
 12027 **/
       
 12028 
       
 12029 
       
 12030 }, '@VERSION@', {"requires": ["oop"]});
       
 12031 YUI.add('event-custom-complex', function (Y, NAME) {
       
 12032 
       
 12033 
       
 12034 /**
       
 12035  * Adds event facades, preventable default behavior, and bubbling.
       
 12036  * events.
       
 12037  * @module event-custom
       
 12038  * @submodule event-custom-complex
       
 12039  */
       
 12040 
       
 12041 var FACADE,
       
 12042     FACADE_KEYS,
       
 12043     YObject = Y.Object,
       
 12044     key,
       
 12045     EMPTY = {},
       
 12046     CEProto = Y.CustomEvent.prototype,
       
 12047     ETProto = Y.EventTarget.prototype,
       
 12048 
       
 12049     mixFacadeProps = function(facade, payload) {
       
 12050         var p;
       
 12051 
       
 12052         for (p in payload) {
       
 12053             if (!(FACADE_KEYS.hasOwnProperty(p))) {
       
 12054                 facade[p] = payload[p];
       
 12055             }
       
 12056         }
       
 12057     };
       
 12058 
       
 12059 /**
       
 12060  * Wraps and protects a custom event for use when emitFacade is set to true.
       
 12061  * Requires the event-custom-complex module
       
 12062  * @class EventFacade
       
 12063  * @param e {Event} the custom event
       
 12064  * @param currentTarget {HTMLElement} the element the listener was attached to
       
 12065  */
       
 12066 
       
 12067 Y.EventFacade = function(e, currentTarget) {
       
 12068 
       
 12069     if (!e) {
       
 12070         e = EMPTY;
       
 12071     }
       
 12072 
       
 12073     this._event = e;
       
 12074 
       
 12075     /**
       
 12076      * The arguments passed to fire
       
 12077      * @property details
       
 12078      * @type Array
       
 12079      */
       
 12080     this.details = e.details;
       
 12081 
       
 12082     /**
       
 12083      * The event type, this can be overridden by the fire() payload
       
 12084      * @property type
       
 12085      * @type string
       
 12086      */
       
 12087     this.type = e.type;
       
 12088 
       
 12089     /**
       
 12090      * The real event type
       
 12091      * @property _type
       
 12092      * @type string
       
 12093      * @private
       
 12094      */
       
 12095     this._type = e.type;
       
 12096 
       
 12097     //////////////////////////////////////////////////////
       
 12098 
       
 12099     /**
       
 12100      * Node reference for the targeted eventtarget
       
 12101      * @property target
       
 12102      * @type Node
       
 12103      */
       
 12104     this.target = e.target;
       
 12105 
       
 12106     /**
       
 12107      * Node reference for the element that the listener was attached to.
       
 12108      * @property currentTarget
       
 12109      * @type Node
       
 12110      */
       
 12111     this.currentTarget = currentTarget;
       
 12112 
       
 12113     /**
       
 12114      * Node reference to the relatedTarget
       
 12115      * @property relatedTarget
       
 12116      * @type Node
       
 12117      */
       
 12118     this.relatedTarget = e.relatedTarget;
       
 12119 
       
 12120 };
       
 12121 
       
 12122 Y.mix(Y.EventFacade.prototype, {
       
 12123 
       
 12124     /**
       
 12125      * Stops the propagation to the next bubble target
       
 12126      * @method stopPropagation
       
 12127      */
       
 12128     stopPropagation: function() {
       
 12129         this._event.stopPropagation();
       
 12130         this.stopped = 1;
       
 12131     },
       
 12132 
       
 12133     /**
       
 12134      * Stops the propagation to the next bubble target and
       
 12135      * prevents any additional listeners from being exectued
       
 12136      * on the current target.
       
 12137      * @method stopImmediatePropagation
       
 12138      */
       
 12139     stopImmediatePropagation: function() {
       
 12140         this._event.stopImmediatePropagation();
       
 12141         this.stopped = 2;
       
 12142     },
       
 12143 
       
 12144     /**
       
 12145      * Prevents the event's default behavior
       
 12146      * @method preventDefault
       
 12147      */
       
 12148     preventDefault: function() {
       
 12149         this._event.preventDefault();
       
 12150         this.prevented = 1;
       
 12151     },
       
 12152 
       
 12153     /**
       
 12154      * Stops the event propagation and prevents the default
       
 12155      * event behavior.
       
 12156      * @method halt
       
 12157      * @param immediate {boolean} if true additional listeners
       
 12158      * on the current target will not be executed
       
 12159      */
       
 12160     halt: function(immediate) {
       
 12161         this._event.halt(immediate);
       
 12162         this.prevented = 1;
       
 12163         this.stopped = (immediate) ? 2 : 1;
       
 12164     }
       
 12165 
       
 12166 });
       
 12167 
       
 12168 CEProto.fireComplex = function(args) {
       
 12169 
       
 12170     var es,
       
 12171         ef,
       
 12172         q,
       
 12173         queue,
       
 12174         ce,
       
 12175         ret = true,
       
 12176         events,
       
 12177         subs,
       
 12178         ons,
       
 12179         afters,
       
 12180         afterQueue,
       
 12181         postponed,
       
 12182         prevented,
       
 12183         preventedFn,
       
 12184         defaultFn,
       
 12185         self = this,
       
 12186         host = self.host || self,
       
 12187         next,
       
 12188         oldbubble,
       
 12189         stack,
       
 12190         yuievt = host._yuievt,
       
 12191         hasPotentialSubscribers;
       
 12192 
       
 12193     stack = self.stack;
       
 12194 
       
 12195     if (stack) {
       
 12196 
       
 12197         // queue this event if the current item in the queue bubbles
       
 12198         if (self.queuable && self.type !== stack.next.type) {
       
 12199             self.log('queue ' + self.type);
       
 12200 
       
 12201             if (!stack.queue) {
       
 12202                 stack.queue = [];
       
 12203             }
       
 12204             stack.queue.push([self, args]);
       
 12205 
       
 12206             return true;
       
 12207         }
       
 12208     }
       
 12209 
       
 12210     hasPotentialSubscribers = self.hasSubs() || yuievt.hasTargets || self.broadcast;
       
 12211 
       
 12212     self.target = self.target || host;
       
 12213     self.currentTarget = host;
       
 12214 
       
 12215     self.details = args.concat();
       
 12216 
       
 12217     if (hasPotentialSubscribers) {
       
 12218 
       
 12219         es = stack || {
       
 12220 
       
 12221            id: self.id, // id of the first event in the stack
       
 12222            next: self,
       
 12223            silent: self.silent,
       
 12224            stopped: 0,
       
 12225            prevented: 0,
       
 12226            bubbling: null,
       
 12227            type: self.type,
       
 12228            // defaultFnQueue: new Y.Queue(),
       
 12229            defaultTargetOnly: self.defaultTargetOnly
       
 12230 
       
 12231         };
       
 12232 
       
 12233         subs = self.getSubs();
       
 12234         ons = subs[0];
       
 12235         afters = subs[1];
       
 12236 
       
 12237         self.stopped = (self.type !== es.type) ? 0 : es.stopped;
       
 12238         self.prevented = (self.type !== es.type) ? 0 : es.prevented;
       
 12239 
       
 12240         if (self.stoppedFn) {
       
 12241             // PERF TODO: Can we replace with callback, like preventedFn. Look into history
       
 12242             events = new Y.EventTarget({
       
 12243                 fireOnce: true,
       
 12244                 context: host
       
 12245             });
       
 12246             self.events = events;
       
 12247             events.on('stopped', self.stoppedFn);
       
 12248         }
       
 12249 
       
 12250         // self.log("Firing " + self  + ", " + "args: " + args);
       
 12251         self.log("Firing " + self.type);
       
 12252 
       
 12253         self._facade = null; // kill facade to eliminate stale properties
       
 12254 
       
 12255         ef = self._getFacade(args);
       
 12256 
       
 12257         if (ons) {
       
 12258             self._procSubs(ons, args, ef);
       
 12259         }
       
 12260 
       
 12261         // bubble if this is hosted in an event target and propagation has not been stopped
       
 12262         if (self.bubbles && host.bubble && !self.stopped) {
       
 12263             oldbubble = es.bubbling;
       
 12264 
       
 12265             es.bubbling = self.type;
       
 12266 
       
 12267             if (es.type !== self.type) {
       
 12268                 es.stopped = 0;
       
 12269                 es.prevented = 0;
       
 12270             }
       
 12271 
       
 12272             ret = host.bubble(self, args, null, es);
       
 12273 
       
 12274             self.stopped = Math.max(self.stopped, es.stopped);
       
 12275             self.prevented = Math.max(self.prevented, es.prevented);
       
 12276 
       
 12277             es.bubbling = oldbubble;
       
 12278         }
       
 12279 
       
 12280         prevented = self.prevented;
       
 12281 
       
 12282         if (prevented) {
       
 12283             preventedFn = self.preventedFn;
       
 12284             if (preventedFn) {
       
 12285                 preventedFn.apply(host, args);
       
 12286             }
       
 12287         } else {
       
 12288             defaultFn = self.defaultFn;
       
 12289 
       
 12290             if (defaultFn && ((!self.defaultTargetOnly && !es.defaultTargetOnly) || host === ef.target)) {
       
 12291                 defaultFn.apply(host, args);
       
 12292             }
       
 12293         }
       
 12294 
       
 12295         // broadcast listeners are fired as discreet events on the
       
 12296         // YUI instance and potentially the YUI global.
       
 12297         if (self.broadcast) {
       
 12298             self._broadcast(args);
       
 12299         }
       
 12300 
       
 12301         if (afters && !self.prevented && self.stopped < 2) {
       
 12302 
       
 12303             // Queue the after
       
 12304             afterQueue = es.afterQueue;
       
 12305 
       
 12306             if (es.id === self.id || self.type !== yuievt.bubbling) {
       
 12307 
       
 12308                 self._procSubs(afters, args, ef);
       
 12309 
       
 12310                 if (afterQueue) {
       
 12311                     while ((next = afterQueue.last())) {
       
 12312                         next();
       
 12313                     }
       
 12314                 }
       
 12315             } else {
       
 12316                 postponed = afters;
       
 12317 
       
 12318                 if (es.execDefaultCnt) {
       
 12319                     postponed = Y.merge(postponed);
       
 12320 
       
 12321                     Y.each(postponed, function(s) {
       
 12322                         s.postponed = true;
       
 12323                     });
       
 12324                 }
       
 12325 
       
 12326                 if (!afterQueue) {
       
 12327                     es.afterQueue = new Y.Queue();
       
 12328                 }
       
 12329 
       
 12330                 es.afterQueue.add(function() {
       
 12331                     self._procSubs(postponed, args, ef);
       
 12332                 });
       
 12333             }
       
 12334 
       
 12335         }
       
 12336 
       
 12337         self.target = null;
       
 12338 
       
 12339         if (es.id === self.id) {
       
 12340 
       
 12341             queue = es.queue;
       
 12342 
       
 12343             if (queue) {
       
 12344                 while (queue.length) {
       
 12345                     q = queue.pop();
       
 12346                     ce = q[0];
       
 12347                     // set up stack to allow the next item to be processed
       
 12348                     es.next = ce;
       
 12349                     ce._fire(q[1]);
       
 12350                 }
       
 12351             }
       
 12352 
       
 12353             self.stack = null;
       
 12354         }
       
 12355 
       
 12356         ret = !(self.stopped);
       
 12357 
       
 12358         if (self.type !== yuievt.bubbling) {
       
 12359             es.stopped = 0;
       
 12360             es.prevented = 0;
       
 12361             self.stopped = 0;
       
 12362             self.prevented = 0;
       
 12363         }
       
 12364 
       
 12365     } else {
       
 12366         defaultFn = self.defaultFn;
       
 12367 
       
 12368         if(defaultFn) {
       
 12369             ef = self._getFacade(args);
       
 12370 
       
 12371             if ((!self.defaultTargetOnly) || (host === ef.target)) {
       
 12372                 defaultFn.apply(host, args);
       
 12373             }
       
 12374         }
       
 12375     }
       
 12376 
       
 12377     // Kill the cached facade to free up memory.
       
 12378     // Otherwise we have the facade from the last fire, sitting around forever.
       
 12379     self._facade = null;
       
 12380 
       
 12381     return ret;
       
 12382 };
       
 12383 
       
 12384 CEProto._getFacade = function(fireArgs) {
       
 12385 
       
 12386     var userArgs = this.details,
       
 12387         firstArg = userArgs && userArgs[0],
       
 12388         firstArgIsObj = (firstArg && (typeof firstArg === "object")),
       
 12389         ef = this._facade;
       
 12390 
       
 12391     if (!ef) {
       
 12392         ef = new Y.EventFacade(this, this.currentTarget);
       
 12393     }
       
 12394 
       
 12395     if (firstArgIsObj) {
       
 12396         // protect the event facade properties
       
 12397         mixFacadeProps(ef, firstArg);
       
 12398 
       
 12399         // Allow the event type to be faked http://yuilibrary.com/projects/yui3/ticket/2528376
       
 12400         if (firstArg.type) {
       
 12401             ef.type = firstArg.type;
       
 12402         }
       
 12403 
       
 12404         if (fireArgs) {
       
 12405             fireArgs[0] = ef;
       
 12406         }
       
 12407     } else {
       
 12408         if (fireArgs) {
       
 12409             fireArgs.unshift(ef);
       
 12410         }
       
 12411     }
       
 12412 
       
 12413     // update the details field with the arguments
       
 12414     ef.details = this.details;
       
 12415 
       
 12416     // use the original target when the event bubbled to this target
       
 12417     ef.target = this.originalTarget || this.target;
       
 12418 
       
 12419     ef.currentTarget = this.currentTarget;
       
 12420     ef.stopped = 0;
       
 12421     ef.prevented = 0;
       
 12422 
       
 12423     this._facade = ef;
       
 12424 
       
 12425     return this._facade;
       
 12426 };
       
 12427 
       
 12428 /**
       
 12429  * Stop propagation to bubble targets
       
 12430  * @for CustomEvent
       
 12431  * @method stopPropagation
       
 12432  */
       
 12433 CEProto.stopPropagation = function() {
       
 12434     this.stopped = 1;
       
 12435     if (this.stack) {
       
 12436         this.stack.stopped = 1;
       
 12437     }
       
 12438     if (this.events) {
       
 12439         this.events.fire('stopped', this);
       
 12440     }
       
 12441 };
       
 12442 
       
 12443 /**
       
 12444  * Stops propagation to bubble targets, and prevents any remaining
       
 12445  * subscribers on the current target from executing.
       
 12446  * @method stopImmediatePropagation
       
 12447  */
       
 12448 CEProto.stopImmediatePropagation = function() {
       
 12449     this.stopped = 2;
       
 12450     if (this.stack) {
       
 12451         this.stack.stopped = 2;
       
 12452     }
       
 12453     if (this.events) {
       
 12454         this.events.fire('stopped', this);
       
 12455     }
       
 12456 };
       
 12457 
       
 12458 /**
       
 12459  * Prevents the execution of this event's defaultFn
       
 12460  * @method preventDefault
       
 12461  */
       
 12462 CEProto.preventDefault = function() {
       
 12463     if (this.preventable) {
       
 12464         this.prevented = 1;
       
 12465         if (this.stack) {
       
 12466             this.stack.prevented = 1;
       
 12467         }
       
 12468     }
       
 12469 };
       
 12470 
       
 12471 /**
       
 12472  * Stops the event propagation and prevents the default
       
 12473  * event behavior.
       
 12474  * @method halt
       
 12475  * @param immediate {boolean} if true additional listeners
       
 12476  * on the current target will not be executed
       
 12477  */
       
 12478 CEProto.halt = function(immediate) {
       
 12479     if (immediate) {
       
 12480         this.stopImmediatePropagation();
       
 12481     } else {
       
 12482         this.stopPropagation();
       
 12483     }
       
 12484     this.preventDefault();
       
 12485 };
       
 12486 
       
 12487 /**
       
 12488  * Registers another EventTarget as a bubble target.  Bubble order
       
 12489  * is determined by the order registered.  Multiple targets can
       
 12490  * be specified.
       
 12491  *
       
 12492  * Events can only bubble if emitFacade is true.
       
 12493  *
       
 12494  * Included in the event-custom-complex submodule.
       
 12495  *
       
 12496  * @method addTarget
       
 12497  * @param o {EventTarget} the target to add
       
 12498  * @for EventTarget
       
 12499  */
       
 12500 ETProto.addTarget = function(o) {
       
 12501     var etState = this._yuievt;
       
 12502 
       
 12503     if (!etState.targets) {
       
 12504         etState.targets = {};
       
 12505     }
       
 12506 
       
 12507     etState.targets[Y.stamp(o)] = o;
       
 12508     etState.hasTargets = true;
       
 12509 };
       
 12510 
       
 12511 /**
       
 12512  * Returns an array of bubble targets for this object.
       
 12513  * @method getTargets
       
 12514  * @return EventTarget[]
       
 12515  */
       
 12516 ETProto.getTargets = function() {
       
 12517     var targets = this._yuievt.targets;
       
 12518     return targets ? YObject.values(targets) : [];
       
 12519 };
       
 12520 
       
 12521 /**
       
 12522  * Removes a bubble target
       
 12523  * @method removeTarget
       
 12524  * @param o {EventTarget} the target to remove
       
 12525  * @for EventTarget
       
 12526  */
       
 12527 ETProto.removeTarget = function(o) {
       
 12528     var targets = this._yuievt.targets;
       
 12529 
       
 12530     if (targets) {
       
 12531         delete targets[Y.stamp(o, true)];
       
 12532 
       
 12533         if (YObject.size(targets) === 0) {
       
 12534             this._yuievt.hasTargets = false;
       
 12535         }
       
 12536     }
       
 12537 };
       
 12538 
       
 12539 /**
       
 12540  * Propagate an event.  Requires the event-custom-complex module.
       
 12541  * @method bubble
       
 12542  * @param evt {CustomEvent} the custom event to propagate
       
 12543  * @return {boolean} the aggregated return value from Event.Custom.fire
       
 12544  * @for EventTarget
       
 12545  */
       
 12546 ETProto.bubble = function(evt, args, target, es) {
       
 12547 
       
 12548     var targs = this._yuievt.targets,
       
 12549         ret = true,
       
 12550         t,
       
 12551         ce,
       
 12552         i,
       
 12553         bc,
       
 12554         ce2,
       
 12555         type = evt && evt.type,
       
 12556         originalTarget = target || (evt && evt.target) || this,
       
 12557         oldbubble;
       
 12558 
       
 12559     if (!evt || ((!evt.stopped) && targs)) {
       
 12560 
       
 12561         for (i in targs) {
       
 12562             if (targs.hasOwnProperty(i)) {
       
 12563 
       
 12564                 t = targs[i];
       
 12565 
       
 12566                 ce = t._yuievt.events[type];
       
 12567 
       
 12568                 if (t._hasSiblings) {
       
 12569                     ce2 = t.getSibling(type, ce);
       
 12570                 }
       
 12571 
       
 12572                 if (ce2 && !ce) {
       
 12573                     ce = t.publish(type);
       
 12574                 }
       
 12575 
       
 12576                 oldbubble = t._yuievt.bubbling;
       
 12577                 t._yuievt.bubbling = type;
       
 12578 
       
 12579                 // if this event was not published on the bubble target,
       
 12580                 // continue propagating the event.
       
 12581                 if (!ce) {
       
 12582                     if (t._yuievt.hasTargets) {
       
 12583                         t.bubble(evt, args, originalTarget, es);
       
 12584                     }
       
 12585                 } else {
       
 12586 
       
 12587                     if (ce2) {
       
 12588                         ce.sibling = ce2;
       
 12589                     }
       
 12590 
       
 12591                     // set the original target to that the target payload on the facade is correct.
       
 12592                     ce.target = originalTarget;
       
 12593                     ce.originalTarget = originalTarget;
       
 12594                     ce.currentTarget = t;
       
 12595                     bc = ce.broadcast;
       
 12596                     ce.broadcast = false;
       
 12597 
       
 12598                     // default publish may not have emitFacade true -- that
       
 12599                     // shouldn't be what the implementer meant to do
       
 12600                     ce.emitFacade = true;
       
 12601 
       
 12602                     ce.stack = es;
       
 12603 
       
 12604                     // TODO: See what's getting in the way of changing this to use
       
 12605                     // the more performant ce._fire(args || evt.details || []).
       
 12606 
       
 12607                     // Something in Widget Parent/Child tests is not happy if we
       
 12608                     // change it - maybe evt.details related?
       
 12609                     ret = ret && ce.fire.apply(ce, args || evt.details || []);
       
 12610 
       
 12611                     ce.broadcast = bc;
       
 12612                     ce.originalTarget = null;
       
 12613 
       
 12614                     // stopPropagation() was called
       
 12615                     if (ce.stopped) {
       
 12616                         break;
       
 12617                     }
       
 12618                 }
       
 12619 
       
 12620                 t._yuievt.bubbling = oldbubble;
       
 12621             }
       
 12622         }
       
 12623     }
       
 12624 
       
 12625     return ret;
       
 12626 };
       
 12627 
       
 12628 FACADE = new Y.EventFacade();
       
 12629 FACADE_KEYS = {};
       
 12630 
       
 12631 // Flatten whitelist
       
 12632 for (key in FACADE) {
       
 12633     FACADE_KEYS[key] = true;
       
 12634 }
       
 12635 
       
 12636 
       
 12637 }, '@VERSION@', {"requires": ["event-custom-base"]});
       
 12638 YUI.add('node-core', function (Y, NAME) {
       
 12639 
       
 12640 /**
       
 12641  * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
       
 12642  * @module node
       
 12643  * @main node
       
 12644  * @submodule node-core
       
 12645  */
       
 12646 
       
 12647 /**
       
 12648  * The Node class provides a wrapper for manipulating DOM Nodes.
       
 12649  * Node properties can be accessed via the set/get methods.
       
 12650  * Use `Y.one()` to retrieve Node instances.
       
 12651  *
       
 12652  * <strong>NOTE:</strong> Node properties are accessed using
       
 12653  * the <code>set</code> and <code>get</code> methods.
       
 12654  *
       
 12655  * @class Node
       
 12656  * @constructor
       
 12657  * @param {DOMNode} node the DOM node to be mapped to the Node instance.
       
 12658  * @uses EventTarget
       
 12659  */
       
 12660 
       
 12661 // "globals"
       
 12662 var DOT = '.',
       
 12663     NODE_NAME = 'nodeName',
       
 12664     NODE_TYPE = 'nodeType',
       
 12665     OWNER_DOCUMENT = 'ownerDocument',
       
 12666     TAG_NAME = 'tagName',
       
 12667     UID = '_yuid',
       
 12668     EMPTY_OBJ = {},
       
 12669 
       
 12670     _slice = Array.prototype.slice,
       
 12671 
       
 12672     Y_DOM = Y.DOM,
       
 12673 
       
 12674     Y_Node = function(node) {
       
 12675         if (!this.getDOMNode) { // support optional "new"
       
 12676             return new Y_Node(node);
       
 12677         }
       
 12678 
       
 12679         if (typeof node == 'string') {
       
 12680             node = Y_Node._fromString(node);
       
 12681             if (!node) {
       
 12682                 return null; // NOTE: return
       
 12683             }
       
 12684         }
       
 12685 
       
 12686         var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID];
       
 12687 
       
 12688         if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) {
       
 12689             node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
       
 12690         }
       
 12691 
       
 12692         uid = uid || Y.stamp(node);
       
 12693         if (!uid) { // stamp failed; likely IE non-HTMLElement
       
 12694             uid = Y.guid();
       
 12695         }
       
 12696 
       
 12697         this[UID] = uid;
       
 12698 
       
 12699         /**
       
 12700          * The underlying DOM node bound to the Y.Node instance
       
 12701          * @property _node
       
 12702          * @type DOMNode
       
 12703          * @private
       
 12704          */
       
 12705         this._node = node;
       
 12706 
       
 12707         this._stateProxy = node; // when augmented with Attribute
       
 12708 
       
 12709         if (this._initPlugins) { // when augmented with Plugin.Host
       
 12710             this._initPlugins();
       
 12711         }
       
 12712     },
       
 12713 
       
 12714     // used with previous/next/ancestor tests
       
 12715     _wrapFn = function(fn) {
       
 12716         var ret = null;
       
 12717         if (fn) {
       
 12718             ret = (typeof fn == 'string') ?
       
 12719             function(n) {
       
 12720                 return Y.Selector.test(n, fn);
       
 12721             } :
       
 12722             function(n) {
       
 12723                 return fn(Y.one(n));
       
 12724             };
       
 12725         }
       
 12726 
       
 12727         return ret;
       
 12728     };
       
 12729 // end "globals"
       
 12730 
       
 12731 Y_Node.ATTRS = {};
       
 12732 Y_Node.DOM_EVENTS = {};
       
 12733 
       
 12734 Y_Node._fromString = function(node) {
       
 12735     if (node) {
       
 12736         if (node.indexOf('doc') === 0) { // doc OR document
       
 12737             node = Y.config.doc;
       
 12738         } else if (node.indexOf('win') === 0) { // win OR window
       
 12739             node = Y.config.win;
       
 12740         } else {
       
 12741             node = Y.Selector.query(node, null, true);
       
 12742         }
       
 12743     }
       
 12744 
       
 12745     return node || null;
       
 12746 };
       
 12747 
       
 12748 /**
       
 12749  * The name of the component
       
 12750  * @static
       
 12751  * @type String
       
 12752  * @property NAME
       
 12753  */
       
 12754 Y_Node.NAME = 'node';
       
 12755 
       
 12756 /*
       
 12757  * The pattern used to identify ARIA attributes
       
 12758  */
       
 12759 Y_Node.re_aria = /^(?:role$|aria-)/;
       
 12760 
       
 12761 Y_Node.SHOW_TRANSITION = 'fadeIn';
       
 12762 Y_Node.HIDE_TRANSITION = 'fadeOut';
       
 12763 
       
 12764 /**
       
 12765  * A list of Node instances that have been created
       
 12766  * @private
       
 12767  * @type Object
       
 12768  * @property _instances
       
 12769  * @static
       
 12770  *
       
 12771  */
       
 12772 Y_Node._instances = {};
       
 12773 
       
 12774 /**
       
 12775  * Retrieves the DOM node bound to a Node instance
       
 12776  * @method getDOMNode
       
 12777  * @static
       
 12778  *
       
 12779  * @param {Node | HTMLNode} node The Node instance or an HTMLNode
       
 12780  * @return {HTMLNode} The DOM node bound to the Node instance.  If a DOM node is passed
       
 12781  * as the node argument, it is simply returned.
       
 12782  */
       
 12783 Y_Node.getDOMNode = function(node) {
       
 12784     if (node) {
       
 12785         return (node.nodeType) ? node : node._node || null;
       
 12786     }
       
 12787     return null;
       
 12788 };
       
 12789 
       
 12790 /**
       
 12791  * Checks Node return values and wraps DOM Nodes as Y.Node instances
       
 12792  * and DOM Collections / Arrays as Y.NodeList instances.
       
 12793  * Other return values just pass thru.  If undefined is returned (e.g. no return)
       
 12794  * then the Node instance is returned for chainability.
       
 12795  * @method scrubVal
       
 12796  * @static
       
 12797  *
       
 12798  * @param {any} node The Node instance or an HTMLNode
       
 12799  * @return {Node | NodeList | Any} Depends on what is returned from the DOM node.
       
 12800  */
       
 12801 Y_Node.scrubVal = function(val, node) {
       
 12802     if (val) { // only truthy values are risky
       
 12803          if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function
       
 12804             if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window
       
 12805                 val = Y.one(val);
       
 12806             } else if ((val.item && !val._nodes) || // dom collection or Node instance
       
 12807                     (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
       
 12808                 val = Y.all(val);
       
 12809             }
       
 12810         }
       
 12811     } else if (typeof val === 'undefined') {
       
 12812         val = node; // for chaining
       
 12813     } else if (val === null) {
       
 12814         val = null; // IE: DOM null not the same as null
       
 12815     }
       
 12816 
       
 12817     return val;
       
 12818 };
       
 12819 
       
 12820 /**
       
 12821  * Adds methods to the Y.Node prototype, routing through scrubVal.
       
 12822  * @method addMethod
       
 12823  * @static
       
 12824  *
       
 12825  * @param {String} name The name of the method to add
       
 12826  * @param {Function} fn The function that becomes the method
       
 12827  * @param {Object} context An optional context to call the method with
       
 12828  * (defaults to the Node instance)
       
 12829  * @return {any} Depends on what is returned from the DOM node.
       
 12830  */
       
 12831 Y_Node.addMethod = function(name, fn, context) {
       
 12832     if (name && fn && typeof fn == 'function') {
       
 12833         Y_Node.prototype[name] = function() {
       
 12834             var args = _slice.call(arguments),
       
 12835                 node = this,
       
 12836                 ret;
       
 12837 
       
 12838             if (args[0] && args[0]._node) {
       
 12839                 args[0] = args[0]._node;
       
 12840             }
       
 12841 
       
 12842             if (args[1] && args[1]._node) {
       
 12843                 args[1] = args[1]._node;
       
 12844             }
       
 12845             args.unshift(node._node);
       
 12846 
       
 12847             ret = fn.apply(node, args);
       
 12848 
       
 12849             if (ret) { // scrub truthy
       
 12850                 ret = Y_Node.scrubVal(ret, node);
       
 12851             }
       
 12852 
       
 12853             (typeof ret != 'undefined') || (ret = node);
       
 12854             return ret;
       
 12855         };
       
 12856     } else {
       
 12857     }
       
 12858 };
       
 12859 
       
 12860 /**
       
 12861  * Imports utility methods to be added as Y.Node methods.
       
 12862  * @method importMethod
       
 12863  * @static
       
 12864  *
       
 12865  * @param {Object} host The object that contains the method to import.
       
 12866  * @param {String} name The name of the method to import
       
 12867  * @param {String} altName An optional name to use in place of the host name
       
 12868  * @param {Object} context An optional context to call the method with
       
 12869  */
       
 12870 Y_Node.importMethod = function(host, name, altName) {
       
 12871     if (typeof name == 'string') {
       
 12872         altName = altName || name;
       
 12873         Y_Node.addMethod(altName, host[name], host);
       
 12874     } else {
       
 12875         Y.Array.each(name, function(n) {
       
 12876             Y_Node.importMethod(host, n);
       
 12877         });
       
 12878     }
       
 12879 };
       
 12880 
       
 12881 /**
       
 12882  * Retrieves a NodeList based on the given CSS selector.
       
 12883  * @method all
       
 12884  *
       
 12885  * @param {string} selector The CSS selector to test against.
       
 12886  * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
 12887  * @for YUI
       
 12888  */
       
 12889 
       
 12890 /**
       
 12891  * Returns a single Node instance bound to the node or the
       
 12892  * first element matching the given selector. Returns null if no match found.
       
 12893  * <strong>Note:</strong> For chaining purposes you may want to
       
 12894  * use <code>Y.all</code>, which returns a NodeList when no match is found.
       
 12895  * @method one
       
 12896  * @param {String | HTMLElement} node a node or Selector
       
 12897  * @return {Node | null} a Node instance or null if no match found.
       
 12898  * @for YUI
       
 12899  */
       
 12900 
       
 12901 /**
       
 12902  * Returns a single Node instance bound to the node or the
       
 12903  * first element matching the given selector. Returns null if no match found.
       
 12904  * <strong>Note:</strong> For chaining purposes you may want to
       
 12905  * use <code>Y.all</code>, which returns a NodeList when no match is found.
       
 12906  * @method one
       
 12907  * @static
       
 12908  * @param {String | HTMLElement} node a node or Selector
       
 12909  * @return {Node | null} a Node instance or null if no match found.
       
 12910  * @for Node
       
 12911  */
       
 12912 Y_Node.one = function(node) {
       
 12913     var instance = null,
       
 12914         cachedNode,
       
 12915         uid;
       
 12916 
       
 12917     if (node) {
       
 12918         if (typeof node == 'string') {
       
 12919             node = Y_Node._fromString(node);
       
 12920             if (!node) {
       
 12921                 return null; // NOTE: return
       
 12922             }
       
 12923         } else if (node.getDOMNode) {
       
 12924             return node; // NOTE: return
       
 12925         }
       
 12926 
       
 12927         if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc)
       
 12928             uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid;
       
 12929             instance = Y_Node._instances[uid]; // reuse exising instances
       
 12930             cachedNode = instance ? instance._node : null;
       
 12931             if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
       
 12932                 instance = new Y_Node(node);
       
 12933                 if (node.nodeType != 11) { // dont cache document fragment
       
 12934                     Y_Node._instances[instance[UID]] = instance; // cache node
       
 12935                 }
       
 12936             }
       
 12937         }
       
 12938     }
       
 12939 
       
 12940     return instance;
       
 12941 };
       
 12942 
       
 12943 /**
       
 12944  * The default setter for DOM properties
       
 12945  * Called with instance context (this === the Node instance)
       
 12946  * @method DEFAULT_SETTER
       
 12947  * @static
       
 12948  * @param {String} name The attribute/property being set
       
 12949  * @param {any} val The value to be set
       
 12950  * @return {any} The value
       
 12951  */
       
 12952 Y_Node.DEFAULT_SETTER = function(name, val) {
       
 12953     var node = this._stateProxy,
       
 12954         strPath;
       
 12955 
       
 12956     if (name.indexOf(DOT) > -1) {
       
 12957         strPath = name;
       
 12958         name = name.split(DOT);
       
 12959         // only allow when defined on node
       
 12960         Y.Object.setValue(node, name, val);
       
 12961     } else if (typeof node[name] != 'undefined') { // pass thru DOM properties
       
 12962         node[name] = val;
       
 12963     }
       
 12964 
       
 12965     return val;
       
 12966 };
       
 12967 
       
 12968 /**
       
 12969  * The default getter for DOM properties
       
 12970  * Called with instance context (this === the Node instance)
       
 12971  * @method DEFAULT_GETTER
       
 12972  * @static
       
 12973  * @param {String} name The attribute/property to look up
       
 12974  * @return {any} The current value
       
 12975  */
       
 12976 Y_Node.DEFAULT_GETTER = function(name) {
       
 12977     var node = this._stateProxy,
       
 12978         val;
       
 12979 
       
 12980     if (name.indexOf && name.indexOf(DOT) > -1) {
       
 12981         val = Y.Object.getValue(node, name.split(DOT));
       
 12982     } else if (typeof node[name] != 'undefined') { // pass thru from DOM
       
 12983         val = node[name];
       
 12984     }
       
 12985 
       
 12986     return val;
       
 12987 };
       
 12988 
       
 12989 Y.mix(Y_Node.prototype, {
       
 12990     DATA_PREFIX: 'data-',
       
 12991 
       
 12992     /**
       
 12993      * The method called when outputting Node instances as strings
       
 12994      * @method toString
       
 12995      * @return {String} A string representation of the Node instance
       
 12996      */
       
 12997     toString: function() {
       
 12998         var str = this[UID] + ': not bound to a node',
       
 12999             node = this._node,
       
 13000             attrs, id, className;
       
 13001 
       
 13002         if (node) {
       
 13003             attrs = node.attributes;
       
 13004             id = (attrs && attrs.id) ? node.getAttribute('id') : null;
       
 13005             className = (attrs && attrs.className) ? node.getAttribute('className') : null;
       
 13006             str = node[NODE_NAME];
       
 13007 
       
 13008             if (id) {
       
 13009                 str += '#' + id;
       
 13010             }
       
 13011 
       
 13012             if (className) {
       
 13013                 str += '.' + className.replace(' ', '.');
       
 13014             }
       
 13015 
       
 13016             // TODO: add yuid?
       
 13017             str += ' ' + this[UID];
       
 13018         }
       
 13019         return str;
       
 13020     },
       
 13021 
       
 13022     /**
       
 13023      * Returns an attribute value on the Node instance.
       
 13024      * Unless pre-configured (via `Node.ATTRS`), get hands
       
 13025      * off to the underlying DOM node.  Only valid
       
 13026      * attributes/properties for the node will be queried.
       
 13027      * @method get
       
 13028      * @param {String} attr The attribute
       
 13029      * @return {any} The current value of the attribute
       
 13030      */
       
 13031     get: function(attr) {
       
 13032         var val;
       
 13033 
       
 13034         if (this._getAttr) { // use Attribute imple
       
 13035             val = this._getAttr(attr);
       
 13036         } else {
       
 13037             val = this._get(attr);
       
 13038         }
       
 13039 
       
 13040         if (val) {
       
 13041             val = Y_Node.scrubVal(val, this);
       
 13042         } else if (val === null) {
       
 13043             val = null; // IE: DOM null is not true null (even though they ===)
       
 13044         }
       
 13045         return val;
       
 13046     },
       
 13047 
       
 13048     /**
       
 13049      * Helper method for get.
       
 13050      * @method _get
       
 13051      * @private
       
 13052      * @param {String} attr The attribute
       
 13053      * @return {any} The current value of the attribute
       
 13054      */
       
 13055     _get: function(attr) {
       
 13056         var attrConfig = Y_Node.ATTRS[attr],
       
 13057             val;
       
 13058 
       
 13059         if (attrConfig && attrConfig.getter) {
       
 13060             val = attrConfig.getter.call(this);
       
 13061         } else if (Y_Node.re_aria.test(attr)) {
       
 13062             val = this._node.getAttribute(attr, 2);
       
 13063         } else {
       
 13064             val = Y_Node.DEFAULT_GETTER.apply(this, arguments);
       
 13065         }
       
 13066 
       
 13067         return val;
       
 13068     },
       
 13069 
       
 13070     /**
       
 13071      * Sets an attribute on the Node instance.
       
 13072      * Unless pre-configured (via Node.ATTRS), set hands
       
 13073      * off to the underlying DOM node.  Only valid
       
 13074      * attributes/properties for the node will be set.
       
 13075      * To set custom attributes use setAttribute.
       
 13076      * @method set
       
 13077      * @param {String} attr The attribute to be set.
       
 13078      * @param {any} val The value to set the attribute to.
       
 13079      * @chainable
       
 13080      */
       
 13081     set: function(attr, val) {
       
 13082         var attrConfig = Y_Node.ATTRS[attr];
       
 13083 
       
 13084         if (this._setAttr) { // use Attribute imple
       
 13085             this._setAttr.apply(this, arguments);
       
 13086         } else { // use setters inline
       
 13087             if (attrConfig && attrConfig.setter) {
       
 13088                 attrConfig.setter.call(this, val, attr);
       
 13089             } else if (Y_Node.re_aria.test(attr)) { // special case Aria
       
 13090                 this._node.setAttribute(attr, val);
       
 13091             } else {
       
 13092                 Y_Node.DEFAULT_SETTER.apply(this, arguments);
       
 13093             }
       
 13094         }
       
 13095 
       
 13096         return this;
       
 13097     },
       
 13098 
       
 13099     /**
       
 13100      * Sets multiple attributes.
       
 13101      * @method setAttrs
       
 13102      * @param {Object} attrMap an object of name/value pairs to set
       
 13103      * @chainable
       
 13104      */
       
 13105     setAttrs: function(attrMap) {
       
 13106         if (this._setAttrs) { // use Attribute imple
       
 13107             this._setAttrs(attrMap);
       
 13108         } else { // use setters inline
       
 13109             Y.Object.each(attrMap, function(v, n) {
       
 13110                 this.set(n, v);
       
 13111             }, this);
       
 13112         }
       
 13113 
       
 13114         return this;
       
 13115     },
       
 13116 
       
 13117     /**
       
 13118      * Returns an object containing the values for the requested attributes.
       
 13119      * @method getAttrs
       
 13120      * @param {Array} attrs an array of attributes to get values
       
 13121      * @return {Object} An object with attribute name/value pairs.
       
 13122      */
       
 13123     getAttrs: function(attrs) {
       
 13124         var ret = {};
       
 13125         if (this._getAttrs) { // use Attribute imple
       
 13126             this._getAttrs(attrs);
       
 13127         } else { // use setters inline
       
 13128             Y.Array.each(attrs, function(v, n) {
       
 13129                 ret[v] = this.get(v);
       
 13130             }, this);
       
 13131         }
       
 13132 
       
 13133         return ret;
       
 13134     },
       
 13135 
       
 13136     /**
       
 13137      * Compares nodes to determine if they match.
       
 13138      * Node instances can be compared to each other and/or HTMLElements.
       
 13139      * @method compareTo
       
 13140      * @param {HTMLElement | Node} refNode The reference node to compare to the node.
       
 13141      * @return {Boolean} True if the nodes match, false if they do not.
       
 13142      */
       
 13143     compareTo: function(refNode) {
       
 13144         var node = this._node;
       
 13145 
       
 13146         if (refNode && refNode._node) {
       
 13147             refNode = refNode._node;
       
 13148         }
       
 13149         return node === refNode;
       
 13150     },
       
 13151 
       
 13152     /**
       
 13153      * Determines whether the node is appended to the document.
       
 13154      * @method inDoc
       
 13155      * @param {Node|HTMLElement} doc optional An optional document to check against.
       
 13156      * Defaults to current document.
       
 13157      * @return {Boolean} Whether or not this node is appended to the document.
       
 13158      */
       
 13159     inDoc: function(doc) {
       
 13160         var node = this._node;
       
 13161         doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
       
 13162         if (doc.documentElement) {
       
 13163             return Y_DOM.contains(doc.documentElement, node);
       
 13164         }
       
 13165     },
       
 13166 
       
 13167     getById: function(id) {
       
 13168         var node = this._node,
       
 13169             ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]);
       
 13170         if (ret && Y_DOM.contains(node, ret)) {
       
 13171             ret = Y.one(ret);
       
 13172         } else {
       
 13173             ret = null;
       
 13174         }
       
 13175         return ret;
       
 13176     },
       
 13177 
       
 13178    /**
       
 13179      * Returns the nearest ancestor that passes the test applied by supplied boolean method.
       
 13180      * @method ancestor
       
 13181      * @param {String | Function} fn A selector string or boolean method for testing elements.
       
 13182      * If a function is used, it receives the current node being tested as the only argument.
       
 13183      * If fn is not passed as an argument, the parent node will be returned.
       
 13184      * @param {Boolean} testSelf optional Whether or not to include the element in the scan
       
 13185      * @param {String | Function} stopFn optional A selector string or boolean
       
 13186      * method to indicate when the search should stop. The search bails when the function
       
 13187      * returns true or the selector matches.
       
 13188      * If a function is used, it receives the current node being tested as the only argument.
       
 13189      * @return {Node} The matching Node instance or null if not found
       
 13190      */
       
 13191     ancestor: function(fn, testSelf, stopFn) {
       
 13192         // testSelf is optional, check for stopFn as 2nd arg
       
 13193         if (arguments.length === 2 &&
       
 13194                 (typeof testSelf == 'string' || typeof testSelf == 'function')) {
       
 13195             stopFn = testSelf;
       
 13196         }
       
 13197 
       
 13198         return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
       
 13199     },
       
 13200 
       
 13201    /**
       
 13202      * Returns the ancestors that pass the test applied by supplied boolean method.
       
 13203      * @method ancestors
       
 13204      * @param {String | Function} fn A selector string or boolean method for testing elements.
       
 13205      * @param {Boolean} testSelf optional Whether or not to include the element in the scan
       
 13206      * If a function is used, it receives the current node being tested as the only argument.
       
 13207      * @return {NodeList} A NodeList instance containing the matching elements
       
 13208      */
       
 13209     ancestors: function(fn, testSelf, stopFn) {
       
 13210         if (arguments.length === 2 &&
       
 13211                 (typeof testSelf == 'string' || typeof testSelf == 'function')) {
       
 13212             stopFn = testSelf;
       
 13213         }
       
 13214         return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
       
 13215     },
       
 13216 
       
 13217     /**
       
 13218      * Returns the previous matching sibling.
       
 13219      * Returns the nearest element node sibling if no method provided.
       
 13220      * @method previous
       
 13221      * @param {String | Function} fn A selector or boolean method for testing elements.
       
 13222      * If a function is used, it receives the current node being tested as the only argument.
       
 13223      * @return {Node} Node instance or null if not found
       
 13224      */
       
 13225     previous: function(fn, all) {
       
 13226         return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
       
 13227     },
       
 13228 
       
 13229     /**
       
 13230      * Returns the next matching sibling.
       
 13231      * Returns the nearest element node sibling if no method provided.
       
 13232      * @method next
       
 13233      * @param {String | Function} fn A selector or boolean method for testing elements.
       
 13234      * If a function is used, it receives the current node being tested as the only argument.
       
 13235      * @return {Node} Node instance or null if not found
       
 13236      */
       
 13237     next: function(fn, all) {
       
 13238         return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
       
 13239     },
       
 13240 
       
 13241     /**
       
 13242      * Returns all matching siblings.
       
 13243      * Returns all siblings if no method provided.
       
 13244      * @method siblings
       
 13245      * @param {String | Function} fn A selector or boolean method for testing elements.
       
 13246      * If a function is used, it receives the current node being tested as the only argument.
       
 13247      * @return {NodeList} NodeList instance bound to found siblings
       
 13248      */
       
 13249     siblings: function(fn) {
       
 13250         return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn)));
       
 13251     },
       
 13252 
       
 13253     /**
       
 13254      * Retrieves a single Node instance, the first element matching the given 
       
 13255      * CSS selector.
       
 13256      * Returns null if no match found.
       
 13257      * @method one
       
 13258      *
       
 13259      * @param {string} selector The CSS selector to test against.
       
 13260      * @return {Node | null} A Node instance for the matching HTMLElement or null 
       
 13261      * if no match found.
       
 13262      */
       
 13263     one: function(selector) {
       
 13264         return Y.one(Y.Selector.query(selector, this._node, true));
       
 13265     },
       
 13266 
       
 13267     /**
       
 13268      * Retrieves a NodeList based on the given CSS selector.
       
 13269      * @method all
       
 13270      *
       
 13271      * @param {string} selector The CSS selector to test against.
       
 13272      * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
 13273      */
       
 13274     all: function(selector) {
       
 13275         var nodelist;
       
 13276         
       
 13277         if (this._node) {
       
 13278             nodelist = Y.all(Y.Selector.query(selector, this._node));
       
 13279             nodelist._query = selector;
       
 13280             nodelist._queryRoot = this._node;
       
 13281         }
       
 13282 
       
 13283         return nodelist || Y.all([]);
       
 13284     },
       
 13285 
       
 13286     // TODO: allow fn test
       
 13287     /**
       
 13288      * Test if the supplied node matches the supplied selector.
       
 13289      * @method test
       
 13290      *
       
 13291      * @param {string} selector The CSS selector to test against.
       
 13292      * @return {boolean} Whether or not the node matches the selector.
       
 13293      */
       
 13294     test: function(selector) {
       
 13295         return Y.Selector.test(this._node, selector);
       
 13296     },
       
 13297 
       
 13298     /**
       
 13299      * Removes the node from its parent.
       
 13300      * Shortcut for myNode.get('parentNode').removeChild(myNode);
       
 13301      * @method remove
       
 13302      * @param {Boolean} destroy whether or not to call destroy() on the node
       
 13303      * after removal.
       
 13304      * @chainable
       
 13305      *
       
 13306      */
       
 13307     remove: function(destroy) {
       
 13308         var node = this._node;
       
 13309 
       
 13310         if (node && node.parentNode) {
       
 13311             node.parentNode.removeChild(node);
       
 13312         }
       
 13313 
       
 13314         if (destroy) {
       
 13315             this.destroy();
       
 13316         }
       
 13317 
       
 13318         return this;
       
 13319     },
       
 13320 
       
 13321     /**
       
 13322      * Replace the node with the other node. This is a DOM update only
       
 13323      * and does not change the node bound to the Node instance.
       
 13324      * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
       
 13325      * @method replace
       
 13326      * @param {Node | HTMLNode} newNode Node to be inserted
       
 13327      * @chainable
       
 13328      *
       
 13329      */
       
 13330     replace: function(newNode) {
       
 13331         var node = this._node;
       
 13332         if (typeof newNode == 'string') {
       
 13333             newNode = Y_Node.create(newNode);
       
 13334         }
       
 13335         node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node);
       
 13336         return this;
       
 13337     },
       
 13338 
       
 13339     /**
       
 13340      * @method replaceChild
       
 13341      * @for Node
       
 13342      * @param {String | HTMLElement | Node} node Node to be inserted
       
 13343      * @param {HTMLElement | Node} refNode Node to be replaced
       
 13344      * @return {Node} The replaced node
       
 13345      */
       
 13346     replaceChild: function(node, refNode) {
       
 13347         if (typeof node == 'string') {
       
 13348             node = Y_DOM.create(node);
       
 13349         }
       
 13350 
       
 13351         return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode)));
       
 13352     },
       
 13353 
       
 13354     /**
       
 13355      * Nulls internal node references, removes any plugins and event listeners.
       
 13356      * Note that destroy() will not remove the node from its parent or from the DOM. For that
       
 13357      * functionality, call remove(true).
       
 13358      * @method destroy
       
 13359      * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the
       
 13360      * node's subtree (default is false)
       
 13361      *
       
 13362      */
       
 13363     destroy: function(recursive) {
       
 13364         var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid',
       
 13365             instance;
       
 13366 
       
 13367         this.purge(); // TODO: only remove events add via this Node
       
 13368 
       
 13369         if (this.unplug) { // may not be a PluginHost
       
 13370             this.unplug();
       
 13371         }
       
 13372 
       
 13373         this.clearData();
       
 13374 
       
 13375         if (recursive) {
       
 13376             Y.NodeList.each(this.all('*'), function(node) {
       
 13377                 instance = Y_Node._instances[node[UID]];
       
 13378                 if (instance) {
       
 13379                    instance.destroy();
       
 13380                 } else { // purge in case added by other means
       
 13381                     Y.Event.purgeElement(node);
       
 13382                 }
       
 13383             });
       
 13384         }
       
 13385 
       
 13386         this._node = null;
       
 13387         this._stateProxy = null;
       
 13388 
       
 13389         delete Y_Node._instances[this._yuid];
       
 13390     },
       
 13391 
       
 13392     /**
       
 13393      * Invokes a method on the Node instance
       
 13394      * @method invoke
       
 13395      * @param {String} method The name of the method to invoke
       
 13396      * @param {Any}  a, b, c, etc. Arguments to invoke the method with.
       
 13397      * @return Whatever the underly method returns.
       
 13398      * DOM Nodes and Collections return values
       
 13399      * are converted to Node/NodeList instances.
       
 13400      *
       
 13401      */
       
 13402     invoke: function(method, a, b, c, d, e) {
       
 13403         var node = this._node,
       
 13404             ret;
       
 13405 
       
 13406         if (a && a._node) {
       
 13407             a = a._node;
       
 13408         }
       
 13409 
       
 13410         if (b && b._node) {
       
 13411             b = b._node;
       
 13412         }
       
 13413 
       
 13414         ret = node[method](a, b, c, d, e);
       
 13415         return Y_Node.scrubVal(ret, this);
       
 13416     },
       
 13417 
       
 13418     /**
       
 13419     * @method swap
       
 13420     * @description Swap DOM locations with the given node.
       
 13421     * This does not change which DOM node each Node instance refers to.
       
 13422     * @param {Node} otherNode The node to swap with
       
 13423      * @chainable
       
 13424     */
       
 13425     swap: Y.config.doc.documentElement.swapNode ?
       
 13426         function(otherNode) {
       
 13427             this._node.swapNode(Y_Node.getDOMNode(otherNode));
       
 13428         } :
       
 13429         function(otherNode) {
       
 13430             otherNode = Y_Node.getDOMNode(otherNode);
       
 13431             var node = this._node,
       
 13432                 parent = otherNode.parentNode,
       
 13433                 nextSibling = otherNode.nextSibling;
       
 13434 
       
 13435             if (nextSibling === node) {
       
 13436                 parent.insertBefore(node, otherNode);
       
 13437             } else if (otherNode === node.nextSibling) {
       
 13438                 parent.insertBefore(otherNode, node);
       
 13439             } else {
       
 13440                 node.parentNode.replaceChild(otherNode, node);
       
 13441                 Y_DOM.addHTML(parent, node, nextSibling);
       
 13442             }
       
 13443             return this;
       
 13444         },
       
 13445 
       
 13446 
       
 13447     hasMethod: function(method) {
       
 13448         var node = this._node;
       
 13449         return !!(node && method in node &&
       
 13450                 typeof node[method] != 'unknown' &&
       
 13451             (typeof node[method] == 'function' ||
       
 13452                 String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space
       
 13453     },
       
 13454 
       
 13455     isFragment: function() {
       
 13456         return (this.get('nodeType') === 11);
       
 13457     },
       
 13458 
       
 13459     /**
       
 13460      * Removes and destroys all of the nodes within the node.
       
 13461      * @method empty
       
 13462      * @chainable
       
 13463      */
       
 13464     empty: function() {
       
 13465         this.get('childNodes').remove().destroy(true);
       
 13466         return this;
       
 13467     },
       
 13468 
       
 13469     /**
       
 13470      * Returns the DOM node bound to the Node instance
       
 13471      * @method getDOMNode
       
 13472      * @return {DOMNode}
       
 13473      */
       
 13474     getDOMNode: function() {
       
 13475         return this._node;
       
 13476     }
       
 13477 }, true);
       
 13478 
       
 13479 Y.Node = Y_Node;
       
 13480 Y.one = Y_Node.one;
       
 13481 /**
       
 13482  * The NodeList module provides support for managing collections of Nodes.
       
 13483  * @module node
       
 13484  * @submodule node-core
       
 13485  */
       
 13486 
       
 13487 /**
       
 13488  * The NodeList class provides a wrapper for manipulating DOM NodeLists.
       
 13489  * NodeList properties can be accessed via the set/get methods.
       
 13490  * Use Y.all() to retrieve NodeList instances.
       
 13491  *
       
 13492  * @class NodeList
       
 13493  * @constructor
       
 13494  * @param nodes {String|element|Node|Array} A selector, DOM element, Node, list of DOM elements, or list of Nodes with which to populate this NodeList.
       
 13495  */
       
 13496 
       
 13497 var NodeList = function(nodes) {
       
 13498     var tmp = [];
       
 13499 
       
 13500     if (nodes) {
       
 13501         if (typeof nodes === 'string') { // selector query
       
 13502             this._query = nodes;
       
 13503             nodes = Y.Selector.query(nodes);
       
 13504         } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window
       
 13505             nodes = [nodes];
       
 13506         } else if (nodes._node) { // Y.Node
       
 13507             nodes = [nodes._node];
       
 13508         } else if (nodes[0] && nodes[0]._node) { // allow array of Y.Nodes
       
 13509             Y.Array.each(nodes, function(node) {
       
 13510                 if (node._node) {
       
 13511                     tmp.push(node._node);
       
 13512                 }
       
 13513             });
       
 13514             nodes = tmp;
       
 13515         } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes)
       
 13516             nodes = Y.Array(nodes, 0, true);
       
 13517         }
       
 13518     }
       
 13519 
       
 13520     /**
       
 13521      * The underlying array of DOM nodes bound to the Y.NodeList instance
       
 13522      * @property _nodes
       
 13523      * @private
       
 13524      */
       
 13525     this._nodes = nodes || [];
       
 13526 };
       
 13527 
       
 13528 NodeList.NAME = 'NodeList';
       
 13529 
       
 13530 /**
       
 13531  * Retrieves the DOM nodes bound to a NodeList instance
       
 13532  * @method getDOMNodes
       
 13533  * @static
       
 13534  *
       
 13535  * @param {NodeList} nodelist The NodeList instance
       
 13536  * @return {Array} The array of DOM nodes bound to the NodeList
       
 13537  */
       
 13538 NodeList.getDOMNodes = function(nodelist) {
       
 13539     return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist;
       
 13540 };
       
 13541 
       
 13542 NodeList.each = function(instance, fn, context) {
       
 13543     var nodes = instance._nodes;
       
 13544     if (nodes && nodes.length) {
       
 13545         Y.Array.each(nodes, fn, context || instance);
       
 13546     } else {
       
 13547     }
       
 13548 };
       
 13549 
       
 13550 NodeList.addMethod = function(name, fn, context) {
       
 13551     if (name && fn) {
       
 13552         NodeList.prototype[name] = function() {
       
 13553             var ret = [],
       
 13554                 args = arguments;
       
 13555 
       
 13556             Y.Array.each(this._nodes, function(node) {
       
 13557                 var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid',
       
 13558                     instance = Y.Node._instances[node[UID]],
       
 13559                     ctx,
       
 13560                     result;
       
 13561 
       
 13562                 if (!instance) {
       
 13563                     instance = NodeList._getTempNode(node);
       
 13564                 }
       
 13565                 ctx = context || instance;
       
 13566                 result = fn.apply(ctx, args);
       
 13567                 if (result !== undefined && result !== instance) {
       
 13568                     ret[ret.length] = result;
       
 13569                 }
       
 13570             });
       
 13571 
       
 13572             // TODO: remove tmp pointer
       
 13573             return ret.length ? ret : this;
       
 13574         };
       
 13575     } else {
       
 13576     }
       
 13577 };
       
 13578 
       
 13579 NodeList.importMethod = function(host, name, altName) {
       
 13580     if (typeof name === 'string') {
       
 13581         altName = altName || name;
       
 13582         NodeList.addMethod(name, host[name]);
       
 13583     } else {
       
 13584         Y.Array.each(name, function(n) {
       
 13585             NodeList.importMethod(host, n);
       
 13586         });
       
 13587     }
       
 13588 };
       
 13589 
       
 13590 NodeList._getTempNode = function(node) {
       
 13591     var tmp = NodeList._tempNode;
       
 13592     if (!tmp) {
       
 13593         tmp = Y.Node.create('<div></div>');
       
 13594         NodeList._tempNode = tmp;
       
 13595     }
       
 13596 
       
 13597     tmp._node = node;
       
 13598     tmp._stateProxy = node;
       
 13599     return tmp;
       
 13600 };
       
 13601 
       
 13602 Y.mix(NodeList.prototype, {
       
 13603     _invoke: function(method, args, getter) {
       
 13604         var ret = (getter) ? [] : this;
       
 13605 
       
 13606         this.each(function(node) {
       
 13607             var val = node[method].apply(node, args);
       
 13608             if (getter) {
       
 13609                 ret.push(val);
       
 13610             }
       
 13611         });
       
 13612 
       
 13613         return ret;
       
 13614     },
       
 13615 
       
 13616     /**
       
 13617      * Retrieves the Node instance at the given index.
       
 13618      * @method item
       
 13619      *
       
 13620      * @param {Number} index The index of the target Node.
       
 13621      * @return {Node} The Node instance at the given index.
       
 13622      */
       
 13623     item: function(index) {
       
 13624         return Y.one((this._nodes || [])[index]);
       
 13625     },
       
 13626 
       
 13627     /**
       
 13628      * Applies the given function to each Node in the NodeList.
       
 13629      * @method each
       
 13630      * @param {Function} fn The function to apply. It receives 3 arguments:
       
 13631      * the current node instance, the node's index, and the NodeList instance
       
 13632      * @param {Object} context optional An optional context to apply the function with
       
 13633      * Default context is the current Node instance
       
 13634      * @chainable
       
 13635      */
       
 13636     each: function(fn, context) {
       
 13637         var instance = this;
       
 13638         Y.Array.each(this._nodes, function(node, index) {
       
 13639             node = Y.one(node);
       
 13640             return fn.call(context || node, node, index, instance);
       
 13641         });
       
 13642         return instance;
       
 13643     },
       
 13644 
       
 13645     batch: function(fn, context) {
       
 13646         var nodelist = this;
       
 13647 
       
 13648         Y.Array.each(this._nodes, function(node, index) {
       
 13649             var instance = Y.Node._instances[node[UID]];
       
 13650             if (!instance) {
       
 13651                 instance = NodeList._getTempNode(node);
       
 13652             }
       
 13653 
       
 13654             return fn.call(context || instance, instance, index, nodelist);
       
 13655         });
       
 13656         return nodelist;
       
 13657     },
       
 13658 
       
 13659     /**
       
 13660      * Executes the function once for each node until a true value is returned.
       
 13661      * @method some
       
 13662      * @param {Function} fn The function to apply. It receives 3 arguments:
       
 13663      * the current node instance, the node's index, and the NodeList instance
       
 13664      * @param {Object} context optional An optional context to execute the function from.
       
 13665      * Default context is the current Node instance
       
 13666      * @return {Boolean} Whether or not the function returned true for any node.
       
 13667      */
       
 13668     some: function(fn, context) {
       
 13669         var instance = this;
       
 13670         return Y.Array.some(this._nodes, function(node, index) {
       
 13671             node = Y.one(node);
       
 13672             context = context || node;
       
 13673             return fn.call(context, node, index, instance);
       
 13674         });
       
 13675     },
       
 13676 
       
 13677     /**
       
 13678      * Creates a documenFragment from the nodes bound to the NodeList instance
       
 13679      * @method toFrag
       
 13680      * @return {Node} a Node instance bound to the documentFragment
       
 13681      */
       
 13682     toFrag: function() {
       
 13683         return Y.one(Y.DOM._nl2frag(this._nodes));
       
 13684     },
       
 13685 
       
 13686     /**
       
 13687      * Returns the index of the node in the NodeList instance
       
 13688      * or -1 if the node isn't found.
       
 13689      * @method indexOf
       
 13690      * @param {Node | DOMNode} node the node to search for
       
 13691      * @return {Int} the index of the node value or -1 if not found
       
 13692      */
       
 13693     indexOf: function(node) {
       
 13694         return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
       
 13695     },
       
 13696 
       
 13697     /**
       
 13698      * Filters the NodeList instance down to only nodes matching the given selector.
       
 13699      * @method filter
       
 13700      * @param {String} selector The selector to filter against
       
 13701      * @return {NodeList} NodeList containing the updated collection
       
 13702      * @see Selector
       
 13703      */
       
 13704     filter: function(selector) {
       
 13705         return Y.all(Y.Selector.filter(this._nodes, selector));
       
 13706     },
       
 13707 
       
 13708 
       
 13709     /**
       
 13710      * Creates a new NodeList containing all nodes at every n indices, where
       
 13711      * remainder n % index equals r.
       
 13712      * (zero-based index).
       
 13713      * @method modulus
       
 13714      * @param {Int} n The offset to use (return every nth node)
       
 13715      * @param {Int} r An optional remainder to use with the modulus operation (defaults to zero)
       
 13716      * @return {NodeList} NodeList containing the updated collection
       
 13717      */
       
 13718     modulus: function(n, r) {
       
 13719         r = r || 0;
       
 13720         var nodes = [];
       
 13721         NodeList.each(this, function(node, i) {
       
 13722             if (i % n === r) {
       
 13723                 nodes.push(node);
       
 13724             }
       
 13725         });
       
 13726 
       
 13727         return Y.all(nodes);
       
 13728     },
       
 13729 
       
 13730     /**
       
 13731      * Creates a new NodeList containing all nodes at odd indices
       
 13732      * (zero-based index).
       
 13733      * @method odd
       
 13734      * @return {NodeList} NodeList containing the updated collection
       
 13735      */
       
 13736     odd: function() {
       
 13737         return this.modulus(2, 1);
       
 13738     },
       
 13739 
       
 13740     /**
       
 13741      * Creates a new NodeList containing all nodes at even indices
       
 13742      * (zero-based index), including zero.
       
 13743      * @method even
       
 13744      * @return {NodeList} NodeList containing the updated collection
       
 13745      */
       
 13746     even: function() {
       
 13747         return this.modulus(2);
       
 13748     },
       
 13749 
       
 13750     destructor: function() {
       
 13751     },
       
 13752 
       
 13753     /**
       
 13754      * Reruns the initial query, when created using a selector query
       
 13755      * @method refresh
       
 13756      * @chainable
       
 13757      */
       
 13758     refresh: function() {
       
 13759         var doc,
       
 13760             nodes = this._nodes,
       
 13761             query = this._query,
       
 13762             root = this._queryRoot;
       
 13763 
       
 13764         if (query) {
       
 13765             if (!root) {
       
 13766                 if (nodes && nodes[0] && nodes[0].ownerDocument) {
       
 13767                     root = nodes[0].ownerDocument;
       
 13768                 }
       
 13769             }
       
 13770 
       
 13771             this._nodes = Y.Selector.query(query, root);
       
 13772         }
       
 13773 
       
 13774         return this;
       
 13775     },
       
 13776 
       
 13777     /**
       
 13778      * Returns the current number of items in the NodeList.
       
 13779      * @method size
       
 13780      * @return {Int} The number of items in the NodeList.
       
 13781      */
       
 13782     size: function() {
       
 13783         return this._nodes.length;
       
 13784     },
       
 13785 
       
 13786     /**
       
 13787      * Determines if the instance is bound to any nodes
       
 13788      * @method isEmpty
       
 13789      * @return {Boolean} Whether or not the NodeList is bound to any nodes
       
 13790      */
       
 13791     isEmpty: function() {
       
 13792         return this._nodes.length < 1;
       
 13793     },
       
 13794 
       
 13795     toString: function() {
       
 13796         var str = '',
       
 13797             errorMsg = this[UID] + ': not bound to any nodes',
       
 13798             nodes = this._nodes,
       
 13799             node;
       
 13800 
       
 13801         if (nodes && nodes[0]) {
       
 13802             node = nodes[0];
       
 13803             str += node[NODE_NAME];
       
 13804             if (node.id) {
       
 13805                 str += '#' + node.id;
       
 13806             }
       
 13807 
       
 13808             if (node.className) {
       
 13809                 str += '.' + node.className.replace(' ', '.');
       
 13810             }
       
 13811 
       
 13812             if (nodes.length > 1) {
       
 13813                 str += '...[' + nodes.length + ' items]';
       
 13814             }
       
 13815         }
       
 13816         return str || errorMsg;
       
 13817     },
       
 13818 
       
 13819     /**
       
 13820      * Returns the DOM node bound to the Node instance
       
 13821      * @method getDOMNodes
       
 13822      * @return {Array}
       
 13823      */
       
 13824     getDOMNodes: function() {
       
 13825         return this._nodes;
       
 13826     }
       
 13827 }, true);
       
 13828 
       
 13829 NodeList.importMethod(Y.Node.prototype, [
       
 13830      /** 
       
 13831       * Called on each Node instance. Nulls internal node references, 
       
 13832       * removes any plugins and event listeners
       
 13833       * @method destroy
       
 13834       * @param {Boolean} recursivePurge (optional) Whether or not to 
       
 13835       * remove listeners from the node's subtree (default is false)
       
 13836       * @see Node.destroy
       
 13837       */
       
 13838     'destroy',
       
 13839 
       
 13840      /** 
       
 13841       * Called on each Node instance. Removes and destroys all of the nodes 
       
 13842       * within the node
       
 13843       * @method empty
       
 13844       * @chainable
       
 13845       * @see Node.empty
       
 13846       */
       
 13847     'empty',
       
 13848 
       
 13849      /** 
       
 13850       * Called on each Node instance. Removes the node from its parent.
       
 13851       * Shortcut for myNode.get('parentNode').removeChild(myNode);
       
 13852       * @method remove
       
 13853       * @param {Boolean} destroy whether or not to call destroy() on the node
       
 13854       * after removal.
       
 13855       * @chainable
       
 13856       * @see Node.remove
       
 13857       */
       
 13858     'remove',
       
 13859 
       
 13860      /** 
       
 13861       * Called on each Node instance. Sets an attribute on the Node instance.
       
 13862       * Unless pre-configured (via Node.ATTRS), set hands
       
 13863       * off to the underlying DOM node.  Only valid
       
 13864       * attributes/properties for the node will be set.
       
 13865       * To set custom attributes use setAttribute.
       
 13866       * @method set
       
 13867       * @param {String} attr The attribute to be set.
       
 13868       * @param {any} val The value to set the attribute to.
       
 13869       * @chainable
       
 13870       * @see Node.set
       
 13871       */
       
 13872     'set'
       
 13873 ]);
       
 13874 
       
 13875 // one-off implementation to convert array of Nodes to NodeList
       
 13876 // e.g. Y.all('input').get('parentNode');
       
 13877 
       
 13878 /** Called on each Node instance
       
 13879   * @method get
       
 13880   * @see Node
       
 13881   */
       
 13882 NodeList.prototype.get = function(attr) {
       
 13883     var ret = [],
       
 13884         nodes = this._nodes,
       
 13885         isNodeList = false,
       
 13886         getTemp = NodeList._getTempNode,
       
 13887         instance,
       
 13888         val;
       
 13889 
       
 13890     if (nodes[0]) {
       
 13891         instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
       
 13892         val = instance._get(attr);
       
 13893         if (val && val.nodeType) {
       
 13894             isNodeList = true;
       
 13895         }
       
 13896     }
       
 13897 
       
 13898     Y.Array.each(nodes, function(node) {
       
 13899         instance = Y.Node._instances[node._yuid];
       
 13900 
       
 13901         if (!instance) {
       
 13902             instance = getTemp(node);
       
 13903         }
       
 13904 
       
 13905         val = instance._get(attr);
       
 13906         if (!isNodeList) { // convert array of Nodes to NodeList
       
 13907             val = Y.Node.scrubVal(val, instance);
       
 13908         }
       
 13909 
       
 13910         ret.push(val);
       
 13911     });
       
 13912 
       
 13913     return (isNodeList) ? Y.all(ret) : ret;
       
 13914 };
       
 13915 
       
 13916 Y.NodeList = NodeList;
       
 13917 
       
 13918 Y.all = function(nodes) {
       
 13919     return new NodeList(nodes);
       
 13920 };
       
 13921 
       
 13922 Y.Node.all = Y.all;
       
 13923 /**
       
 13924  * @module node
       
 13925  * @submodule node-core
       
 13926  */
       
 13927 
       
 13928 var Y_NodeList = Y.NodeList,
       
 13929     ArrayProto = Array.prototype,
       
 13930     ArrayMethods = {
       
 13931         /** Returns a new NodeList combining the given NodeList(s)
       
 13932           * @for NodeList
       
 13933           * @method concat
       
 13934           * @param {NodeList | Array} valueN Arrays/NodeLists and/or values to
       
 13935           * concatenate to the resulting NodeList
       
 13936           * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
       
 13937           */
       
 13938         'concat': 1,
       
 13939         /** Removes the last from the NodeList and returns it.
       
 13940           * @for NodeList
       
 13941           * @method pop
       
 13942           * @return {Node | null} The last item in the NodeList, or null if the list is empty.
       
 13943           */
       
 13944         'pop': 0,
       
 13945         /** Adds the given Node(s) to the end of the NodeList.
       
 13946           * @for NodeList
       
 13947           * @method push
       
 13948           * @param {Node | DOMNode} nodes One or more nodes to add to the end of the NodeList.
       
 13949           */
       
 13950         'push': 0,
       
 13951         /** Removes the first item from the NodeList and returns it.
       
 13952           * @for NodeList
       
 13953           * @method shift
       
 13954           * @return {Node | null} The first item in the NodeList, or null if the NodeList is empty.
       
 13955           */
       
 13956         'shift': 0,
       
 13957         /** Returns a new NodeList comprising the Nodes in the given range.
       
 13958           * @for NodeList
       
 13959           * @method slice
       
 13960           * @param {Number} begin Zero-based index at which to begin extraction.
       
 13961           As a negative index, start indicates an offset from the end of the sequence. slice(-2) extracts the second-to-last element and the last element in the sequence.
       
 13962           * @param {Number} end Zero-based index at which to end extraction. slice extracts up to but not including end.
       
 13963           slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
       
 13964           As a negative index, end indicates an offset from the end of the sequence. slice(2,-1) extracts the third element through the second-to-last element in the sequence.
       
 13965           If end is omitted, slice extracts to the end of the sequence.
       
 13966           * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
       
 13967           */
       
 13968         'slice': 1,
       
 13969         /** Changes the content of the NodeList, adding new elements while removing old elements.
       
 13970           * @for NodeList
       
 13971           * @method splice
       
 13972           * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
       
 13973           * @param {Number} howMany An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed. In this case, you should specify at least one new element. If no howMany parameter is specified (second syntax above, which is a SpiderMonkey extension), all elements after index are removed.
       
 13974           * {Node | DOMNode| element1, ..., elementN
       
 13975           The elements to add to the array. If you don't specify any elements, splice simply removes elements from the array.
       
 13976           * @return {NodeList} The element(s) removed.
       
 13977           */
       
 13978         'splice': 1,
       
 13979         /** Adds the given Node(s) to the beginning of the NodeList.
       
 13980           * @for NodeList
       
 13981           * @method unshift
       
 13982           * @param {Node | DOMNode} nodes One or more nodes to add to the NodeList.
       
 13983           */
       
 13984         'unshift': 0
       
 13985     };
       
 13986 
       
 13987 
       
 13988 Y.Object.each(ArrayMethods, function(returnNodeList, name) {
       
 13989     Y_NodeList.prototype[name] = function() {
       
 13990         var args = [],
       
 13991             i = 0,
       
 13992             arg,
       
 13993             ret;
       
 13994 
       
 13995         while (typeof (arg = arguments[i++]) != 'undefined') { // use DOM nodes/nodeLists
       
 13996             args.push(arg._node || arg._nodes || arg);
       
 13997         }
       
 13998 
       
 13999         ret = ArrayProto[name].apply(this._nodes, args);
       
 14000 
       
 14001         if (returnNodeList) {
       
 14002             ret = Y.all(ret);
       
 14003         } else {
       
 14004             ret = Y.Node.scrubVal(ret);
       
 14005         }
       
 14006 
       
 14007         return ret;
       
 14008     };
       
 14009 });
       
 14010 /**
       
 14011  * @module node
       
 14012  * @submodule node-core
       
 14013  */
       
 14014 
       
 14015 Y.Array.each([
       
 14016     /**
       
 14017      * Passes through to DOM method.
       
 14018      * @for Node
       
 14019      * @method removeChild
       
 14020      * @param {HTMLElement | Node} node Node to be removed
       
 14021      * @return {Node} The removed node
       
 14022      */
       
 14023     'removeChild',
       
 14024 
       
 14025     /**
       
 14026      * Passes through to DOM method.
       
 14027      * @method hasChildNodes
       
 14028      * @return {Boolean} Whether or not the node has any childNodes
       
 14029      */
       
 14030     'hasChildNodes',
       
 14031 
       
 14032     /**
       
 14033      * Passes through to DOM method.
       
 14034      * @method cloneNode
       
 14035      * @param {Boolean} deep Whether or not to perform a deep clone, which includes
       
 14036      * subtree and attributes
       
 14037      * @return {Node} The clone
       
 14038      */
       
 14039     'cloneNode',
       
 14040 
       
 14041     /**
       
 14042      * Passes through to DOM method.
       
 14043      * @method hasAttribute
       
 14044      * @param {String} attribute The attribute to test for
       
 14045      * @return {Boolean} Whether or not the attribute is present
       
 14046      */
       
 14047     'hasAttribute',
       
 14048 
       
 14049     /**
       
 14050      * Passes through to DOM method.
       
 14051      * @method scrollIntoView
       
 14052      * @chainable
       
 14053      */
       
 14054     'scrollIntoView',
       
 14055 
       
 14056     /**
       
 14057      * Passes through to DOM method.
       
 14058      * @method getElementsByTagName
       
 14059      * @param {String} tagName The tagName to collect
       
 14060      * @return {NodeList} A NodeList representing the HTMLCollection
       
 14061      */
       
 14062     'getElementsByTagName',
       
 14063 
       
 14064     /**
       
 14065      * Passes through to DOM method.
       
 14066      * @method focus
       
 14067      * @chainable
       
 14068      */
       
 14069     'focus',
       
 14070 
       
 14071     /**
       
 14072      * Passes through to DOM method.
       
 14073      * @method blur
       
 14074      * @chainable
       
 14075      */
       
 14076     'blur',
       
 14077 
       
 14078     /**
       
 14079      * Passes through to DOM method.
       
 14080      * Only valid on FORM elements
       
 14081      * @method submit
       
 14082      * @chainable
       
 14083      */
       
 14084     'submit',
       
 14085 
       
 14086     /**
       
 14087      * Passes through to DOM method.
       
 14088      * Only valid on FORM elements
       
 14089      * @method reset
       
 14090      * @chainable
       
 14091      */
       
 14092     'reset',
       
 14093 
       
 14094     /**
       
 14095      * Passes through to DOM method.
       
 14096      * @method select
       
 14097      * @chainable
       
 14098      */
       
 14099      'select',
       
 14100 
       
 14101     /**
       
 14102      * Passes through to DOM method.
       
 14103      * Only valid on TABLE elements
       
 14104      * @method createCaption
       
 14105      * @chainable
       
 14106      */
       
 14107     'createCaption'
       
 14108 
       
 14109 ], function(method) {
       
 14110     Y.Node.prototype[method] = function(arg1, arg2, arg3) {
       
 14111         var ret = this.invoke(method, arg1, arg2, arg3);
       
 14112         return ret;
       
 14113     };
       
 14114 });
       
 14115 
       
 14116 /**
       
 14117  * Passes through to DOM method.
       
 14118  * @method removeAttribute
       
 14119  * @param {String} attribute The attribute to be removed
       
 14120  * @chainable
       
 14121  */
       
 14122  // one-off implementation due to IE returning boolean, breaking chaining
       
 14123 Y.Node.prototype.removeAttribute = function(attr) {
       
 14124     var node = this._node;
       
 14125     if (node) {
       
 14126         node.removeAttribute(attr, 0); // comma zero for IE < 8 to force case-insensitive
       
 14127     }
       
 14128 
       
 14129     return this;
       
 14130 };
       
 14131 
       
 14132 Y.Node.importMethod(Y.DOM, [
       
 14133     /**
       
 14134      * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
       
 14135      * @method contains
       
 14136      * @param {Node | HTMLElement} needle The possible node or descendent
       
 14137      * @return {Boolean} Whether or not this node is the needle its ancestor
       
 14138      */
       
 14139     'contains',
       
 14140     /**
       
 14141      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
 14142      * This passes through to the DOM node, allowing for custom attributes.
       
 14143      * @method setAttribute
       
 14144      * @for Node
       
 14145      * @chainable
       
 14146      * @param {string} name The attribute name
       
 14147      * @param {string} value The value to set
       
 14148      */
       
 14149     'setAttribute',
       
 14150     /**
       
 14151      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
 14152      * This passes through to the DOM node, allowing for custom attributes.
       
 14153      * @method getAttribute
       
 14154      * @for Node
       
 14155      * @param {string} name The attribute name
       
 14156      * @return {string} The attribute value
       
 14157      */
       
 14158     'getAttribute',
       
 14159 
       
 14160     /**
       
 14161      * Wraps the given HTML around the node.
       
 14162      * @method wrap
       
 14163      * @param {String} html The markup to wrap around the node.
       
 14164      * @chainable
       
 14165      * @for Node
       
 14166      */
       
 14167     'wrap',
       
 14168 
       
 14169     /**
       
 14170      * Removes the node's parent node.
       
 14171      * @method unwrap
       
 14172      * @chainable
       
 14173      */
       
 14174     'unwrap',
       
 14175 
       
 14176     /**
       
 14177      * Applies a unique ID to the node if none exists
       
 14178      * @method generateID
       
 14179      * @return {String} The existing or generated ID
       
 14180      */
       
 14181     'generateID'
       
 14182 ]);
       
 14183 
       
 14184 Y.NodeList.importMethod(Y.Node.prototype, [
       
 14185 /**
       
 14186  * Allows getting attributes on DOM nodes, normalizing in some cases.
       
 14187  * This passes through to the DOM node, allowing for custom attributes.
       
 14188  * @method getAttribute
       
 14189  * @see Node
       
 14190  * @for NodeList
       
 14191  * @param {string} name The attribute name
       
 14192  * @return {string} The attribute value
       
 14193  */
       
 14194 
       
 14195     'getAttribute',
       
 14196 /**
       
 14197  * Allows setting attributes on DOM nodes, normalizing in some cases.
       
 14198  * This passes through to the DOM node, allowing for custom attributes.
       
 14199  * @method setAttribute
       
 14200  * @see Node
       
 14201  * @for NodeList
       
 14202  * @chainable
       
 14203  * @param {string} name The attribute name
       
 14204  * @param {string} value The value to set
       
 14205  */
       
 14206     'setAttribute',
       
 14207 
       
 14208 /**
       
 14209  * Allows for removing attributes on DOM nodes.
       
 14210  * This passes through to the DOM node, allowing for custom attributes.
       
 14211  * @method removeAttribute
       
 14212  * @see Node
       
 14213  * @for NodeList
       
 14214  * @param {string} name The attribute to remove
       
 14215  */
       
 14216     'removeAttribute',
       
 14217 /**
       
 14218  * Removes the parent node from node in the list.
       
 14219  * @method unwrap
       
 14220  * @chainable
       
 14221  */
       
 14222     'unwrap',
       
 14223 /**
       
 14224  * Wraps the given HTML around each node.
       
 14225  * @method wrap
       
 14226  * @param {String} html The markup to wrap around the node.
       
 14227  * @chainable
       
 14228  */
       
 14229     'wrap',
       
 14230 
       
 14231 /**
       
 14232  * Applies a unique ID to each node if none exists
       
 14233  * @method generateID
       
 14234  * @return {String} The existing or generated ID
       
 14235  */
       
 14236     'generateID'
       
 14237 ]);
       
 14238 
       
 14239 
       
 14240 }, '@VERSION@', {"requires": ["dom-core", "selector"]});
       
 14241 YUI.add('node-base', function (Y, NAME) {
       
 14242 
       
 14243 /**
       
 14244  * @module node
       
 14245  * @submodule node-base
       
 14246  */
       
 14247 
       
 14248 var methods = [
       
 14249 /**
       
 14250  * Determines whether each node has the given className.
       
 14251  * @method hasClass
       
 14252  * @for Node
       
 14253  * @param {String} className the class name to search for
       
 14254  * @return {Boolean} Whether or not the element has the specified class
       
 14255  */
       
 14256  'hasClass',
       
 14257 
       
 14258 /**
       
 14259  * Adds a class name to each node.
       
 14260  * @method addClass
       
 14261  * @param {String} className the class name to add to the node's class attribute
       
 14262  * @chainable
       
 14263  */
       
 14264  'addClass',
       
 14265 
       
 14266 /**
       
 14267  * Removes a class name from each node.
       
 14268  * @method removeClass
       
 14269  * @param {String} className the class name to remove from the node's class attribute
       
 14270  * @chainable
       
 14271  */
       
 14272  'removeClass',
       
 14273 
       
 14274 /**
       
 14275  * Replace a class with another class for each node.
       
 14276  * If no oldClassName is present, the newClassName is simply added.
       
 14277  * @method replaceClass
       
 14278  * @param {String} oldClassName the class name to be replaced
       
 14279  * @param {String} newClassName the class name that will be replacing the old class name
       
 14280  * @chainable
       
 14281  */
       
 14282  'replaceClass',
       
 14283 
       
 14284 /**
       
 14285  * If the className exists on the node it is removed, if it doesn't exist it is added.
       
 14286  * @method toggleClass
       
 14287  * @param {String} className the class name to be toggled
       
 14288  * @param {Boolean} force Option to force adding or removing the class.
       
 14289  * @chainable
       
 14290  */
       
 14291  'toggleClass'
       
 14292 ];
       
 14293 
       
 14294 Y.Node.importMethod(Y.DOM, methods);
       
 14295 /**
       
 14296  * Determines whether each node has the given className.
       
 14297  * @method hasClass
       
 14298  * @see Node.hasClass
       
 14299  * @for NodeList
       
 14300  * @param {String} className the class name to search for
       
 14301  * @return {Array} An array of booleans for each node bound to the NodeList.
       
 14302  */
       
 14303 
       
 14304 /**
       
 14305  * Adds a class name to each node.
       
 14306  * @method addClass
       
 14307  * @see Node.addClass
       
 14308  * @param {String} className the class name to add to the node's class attribute
       
 14309  * @chainable
       
 14310  */
       
 14311 
       
 14312 /**
       
 14313  * Removes a class name from each node.
       
 14314  * @method removeClass
       
 14315  * @see Node.removeClass
       
 14316  * @param {String} className the class name to remove from the node's class attribute
       
 14317  * @chainable
       
 14318  */
       
 14319 
       
 14320 /**
       
 14321  * Replace a class with another class for each node.
       
 14322  * If no oldClassName is present, the newClassName is simply added.
       
 14323  * @method replaceClass
       
 14324  * @see Node.replaceClass
       
 14325  * @param {String} oldClassName the class name to be replaced
       
 14326  * @param {String} newClassName the class name that will be replacing the old class name
       
 14327  * @chainable
       
 14328  */
       
 14329 
       
 14330 /**
       
 14331  * If the className exists on the node it is removed, if it doesn't exist it is added.
       
 14332  * @method toggleClass
       
 14333  * @see Node.toggleClass
       
 14334  * @param {String} className the class name to be toggled
       
 14335  * @chainable
       
 14336  */
       
 14337 Y.NodeList.importMethod(Y.Node.prototype, methods);
       
 14338 /**
       
 14339  * @module node
       
 14340  * @submodule node-base
       
 14341  */
       
 14342 
       
 14343 var Y_Node = Y.Node,
       
 14344     Y_DOM = Y.DOM;
       
 14345 
       
 14346 /**
       
 14347  * Returns a new dom node using the provided markup string.
       
 14348  * @method create
       
 14349  * @static
       
 14350  * @param {String} html The markup used to create the element
       
 14351  * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14352  * to escape html content.
       
 14353  * @param {HTMLDocument} doc An optional document context
       
 14354  * @return {Node} A Node instance bound to a DOM node or fragment
       
 14355  * @for Node
       
 14356  */
       
 14357 Y_Node.create = function(html, doc) {
       
 14358     if (doc && doc._node) {
       
 14359         doc = doc._node;
       
 14360     }
       
 14361     return Y.one(Y_DOM.create(html, doc));
       
 14362 };
       
 14363 
       
 14364 Y.mix(Y_Node.prototype, {
       
 14365     /**
       
 14366      * Creates a new Node using the provided markup string.
       
 14367      * @method create
       
 14368      * @param {String} html The markup used to create the element.
       
 14369      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14370      * to escape html content.
       
 14371      * @param {HTMLDocument} doc An optional document context
       
 14372      * @return {Node} A Node instance bound to a DOM node or fragment
       
 14373      */
       
 14374     create: Y_Node.create,
       
 14375 
       
 14376     /**
       
 14377      * Inserts the content before the reference node.
       
 14378      * @method insert
       
 14379      * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
 14380      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14381      * to escape html content.
       
 14382      * @param {Int | Node | HTMLElement | String} where The position to insert at.
       
 14383      * Possible "where" arguments
       
 14384      * <dl>
       
 14385      * <dt>Y.Node</dt>
       
 14386      * <dd>The Node to insert before</dd>
       
 14387      * <dt>HTMLElement</dt>
       
 14388      * <dd>The element to insert before</dd>
       
 14389      * <dt>Int</dt>
       
 14390      * <dd>The index of the child element to insert before</dd>
       
 14391      * <dt>"replace"</dt>
       
 14392      * <dd>Replaces the existing HTML</dd>
       
 14393      * <dt>"before"</dt>
       
 14394      * <dd>Inserts before the existing HTML</dd>
       
 14395      * <dt>"before"</dt>
       
 14396      * <dd>Inserts content before the node</dd>
       
 14397      * <dt>"after"</dt>
       
 14398      * <dd>Inserts content after the node</dd>
       
 14399      * </dl>
       
 14400      * @chainable
       
 14401      */
       
 14402     insert: function(content, where) {
       
 14403         this._insert(content, where);
       
 14404         return this;
       
 14405     },
       
 14406 
       
 14407     _insert: function(content, where) {
       
 14408         var node = this._node,
       
 14409             ret = null;
       
 14410 
       
 14411         if (typeof where == 'number') { // allow index
       
 14412             where = this._node.childNodes[where];
       
 14413         } else if (where && where._node) { // Node
       
 14414             where = where._node;
       
 14415         }
       
 14416 
       
 14417         if (content && typeof content != 'string') { // allow Node or NodeList/Array instances
       
 14418             content = content._node || content._nodes || content;
       
 14419         }
       
 14420         ret = Y_DOM.addHTML(node, content, where);
       
 14421 
       
 14422         return ret;
       
 14423     },
       
 14424 
       
 14425     /**
       
 14426      * Inserts the content as the firstChild of the node.
       
 14427      * @method prepend
       
 14428      * @param {String | Node | HTMLElement} content The content to insert
       
 14429      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14430      * to escape html content.
       
 14431      * @chainable
       
 14432      */
       
 14433     prepend: function(content) {
       
 14434         return this.insert(content, 0);
       
 14435     },
       
 14436 
       
 14437     /**
       
 14438      * Inserts the content as the lastChild of the node.
       
 14439      * @method append
       
 14440      * @param {String | Node | HTMLElement} content The content to insert
       
 14441      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14442      * to escape html content.
       
 14443      * @chainable
       
 14444      */
       
 14445     append: function(content) {
       
 14446         return this.insert(content, null);
       
 14447     },
       
 14448 
       
 14449     /**
       
 14450      * @method appendChild
       
 14451      * @param {String | HTMLElement | Node} node Node to be appended
       
 14452      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14453      * to escape html content.
       
 14454      * @return {Node} The appended node
       
 14455      */
       
 14456     appendChild: function(node) {
       
 14457         return Y_Node.scrubVal(this._insert(node));
       
 14458     },
       
 14459 
       
 14460     /**
       
 14461      * @method insertBefore
       
 14462      * @param {String | HTMLElement | Node} newNode Node to be appended
       
 14463      * @param {HTMLElement | Node} refNode Node to be inserted before
       
 14464      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14465      * to escape html content.
       
 14466      * @return {Node} The inserted node
       
 14467      */
       
 14468     insertBefore: function(newNode, refNode) {
       
 14469         return Y.Node.scrubVal(this._insert(newNode, refNode));
       
 14470     },
       
 14471 
       
 14472     /**
       
 14473      * Appends the node to the given node.
       
 14474      * @method appendTo
       
 14475      * @param {Node | HTMLElement} node The node to append to
       
 14476      * @chainable
       
 14477      */
       
 14478     appendTo: function(node) {
       
 14479         Y.one(node).append(this);
       
 14480         return this;
       
 14481     },
       
 14482 
       
 14483     /**
       
 14484      * Replaces the node's current content with the content.
       
 14485      * Note that this passes to innerHTML and is not escaped.
       
 14486      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14487      * to escape html content or `set('text')` to add as text.
       
 14488      * @method setContent
       
 14489      * @deprecated Use setHTML
       
 14490      * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
 14491      * @chainable
       
 14492      */
       
 14493     setContent: function(content) {
       
 14494         this._insert(content, 'replace');
       
 14495         return this;
       
 14496     },
       
 14497 
       
 14498     /**
       
 14499      * Returns the node's current content (e.g. innerHTML)
       
 14500      * @method getContent
       
 14501      * @deprecated Use getHTML
       
 14502      * @return {String} The current content
       
 14503      */
       
 14504     getContent: function(content) {
       
 14505         return this.get('innerHTML');
       
 14506     }
       
 14507 });
       
 14508 
       
 14509 /**
       
 14510  * Replaces the node's current html content with the content provided.
       
 14511  * Note that this passes to innerHTML and is not escaped.
       
 14512  * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
 14513  * @method setHTML
       
 14514  * @param {String | HTML | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
 14515  * @chainable
       
 14516  */
       
 14517 Y.Node.prototype.setHTML = Y.Node.prototype.setContent;
       
 14518 
       
 14519 /**
       
 14520  * Returns the node's current html content (e.g. innerHTML)
       
 14521  * @method getHTML
       
 14522  * @return {String} The html content
       
 14523  */
       
 14524 Y.Node.prototype.getHTML = Y.Node.prototype.getContent;
       
 14525 
       
 14526 Y.NodeList.importMethod(Y.Node.prototype, [
       
 14527     /**
       
 14528      * Called on each Node instance
       
 14529      * @for NodeList
       
 14530      * @method append
       
 14531      * @see Node.append
       
 14532      */
       
 14533     'append',
       
 14534 
       
 14535     /**
       
 14536      * Called on each Node instance
       
 14537      * @for NodeList
       
 14538      * @method insert
       
 14539      * @see Node.insert
       
 14540      */
       
 14541     'insert',
       
 14542 
       
 14543     /**
       
 14544      * Called on each Node instance
       
 14545      * @for NodeList
       
 14546      * @method appendChild
       
 14547      * @see Node.appendChild
       
 14548      */
       
 14549     'appendChild',
       
 14550 
       
 14551     /**
       
 14552      * Called on each Node instance
       
 14553      * @for NodeList
       
 14554      * @method insertBefore
       
 14555      * @see Node.insertBefore
       
 14556      */
       
 14557     'insertBefore',
       
 14558 
       
 14559     /**
       
 14560      * Called on each Node instance
       
 14561      * @for NodeList
       
 14562      * @method prepend
       
 14563      * @see Node.prepend
       
 14564      */
       
 14565     'prepend',
       
 14566 
       
 14567     /**
       
 14568      * Called on each Node instance
       
 14569      * Note that this passes to innerHTML and is not escaped.
       
 14570      * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
 14571      * @for NodeList
       
 14572      * @method setContent
       
 14573      * @deprecated Use setHTML
       
 14574      */
       
 14575     'setContent',
       
 14576 
       
 14577     /**
       
 14578      * Called on each Node instance
       
 14579      * @for NodeList
       
 14580      * @method getContent
       
 14581      * @deprecated Use getHTML
       
 14582      */
       
 14583     'getContent',
       
 14584 
       
 14585     /**
       
 14586      * Called on each Node instance
       
 14587      * Note that this passes to innerHTML and is not escaped.
       
 14588      * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
 14589      * @for NodeList
       
 14590      * @method setHTML
       
 14591      * @see Node.setHTML
       
 14592      */
       
 14593     'setHTML',
       
 14594 
       
 14595     /**
       
 14596      * Called on each Node instance
       
 14597      * @for NodeList
       
 14598      * @method getHTML
       
 14599      * @see Node.getHTML
       
 14600      */
       
 14601     'getHTML'
       
 14602 ]);
       
 14603 /**
       
 14604  * @module node
       
 14605  * @submodule node-base
       
 14606  */
       
 14607 
       
 14608 var Y_Node = Y.Node,
       
 14609     Y_DOM = Y.DOM;
       
 14610 
       
 14611 /**
       
 14612  * Static collection of configuration attributes for special handling
       
 14613  * @property ATTRS
       
 14614  * @static
       
 14615  * @type object
       
 14616  */
       
 14617 Y_Node.ATTRS = {
       
 14618     /**
       
 14619      * Allows for getting and setting the text of an element.
       
 14620      * Formatting is preserved and special characters are treated literally.
       
 14621      * @config text
       
 14622      * @type String
       
 14623      */
       
 14624     text: {
       
 14625         getter: function() {
       
 14626             return Y_DOM.getText(this._node);
       
 14627         },
       
 14628 
       
 14629         setter: function(content) {
       
 14630             Y_DOM.setText(this._node, content);
       
 14631             return content;
       
 14632         }
       
 14633     },
       
 14634 
       
 14635     /**
       
 14636      * Allows for getting and setting the text of an element.
       
 14637      * Formatting is preserved and special characters are treated literally.
       
 14638      * @config for
       
 14639      * @type String
       
 14640      */
       
 14641     'for': {
       
 14642         getter: function() {
       
 14643             return Y_DOM.getAttribute(this._node, 'for');
       
 14644         },
       
 14645 
       
 14646         setter: function(val) {
       
 14647             Y_DOM.setAttribute(this._node, 'for', val);
       
 14648             return val;
       
 14649         }
       
 14650     },
       
 14651 
       
 14652     'options': {
       
 14653         getter: function() {
       
 14654             return this._node.getElementsByTagName('option');
       
 14655         }
       
 14656     },
       
 14657 
       
 14658     /**
       
 14659      * Returns a NodeList instance of all HTMLElement children.
       
 14660      * @readOnly
       
 14661      * @config children
       
 14662      * @type NodeList
       
 14663      */
       
 14664     'children': {
       
 14665         getter: function() {
       
 14666             var node = this._node,
       
 14667                 children = node.children,
       
 14668                 childNodes, i, len;
       
 14669 
       
 14670             if (!children) {
       
 14671                 childNodes = node.childNodes;
       
 14672                 children = [];
       
 14673 
       
 14674                 for (i = 0, len = childNodes.length; i < len; ++i) {
       
 14675                     if (childNodes[i].tagName) {
       
 14676                         children[children.length] = childNodes[i];
       
 14677                     }
       
 14678                 }
       
 14679             }
       
 14680             return Y.all(children);
       
 14681         }
       
 14682     },
       
 14683 
       
 14684     value: {
       
 14685         getter: function() {
       
 14686             return Y_DOM.getValue(this._node);
       
 14687         },
       
 14688 
       
 14689         setter: function(val) {
       
 14690             Y_DOM.setValue(this._node, val);
       
 14691             return val;
       
 14692         }
       
 14693     }
       
 14694 };
       
 14695 
       
 14696 Y.Node.importMethod(Y.DOM, [
       
 14697     /**
       
 14698      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
 14699      * This passes through to the DOM node, allowing for custom attributes.
       
 14700      * @method setAttribute
       
 14701      * @for Node
       
 14702      * @for NodeList
       
 14703      * @chainable
       
 14704      * @param {string} name The attribute name
       
 14705      * @param {string} value The value to set
       
 14706      */
       
 14707     'setAttribute',
       
 14708     /**
       
 14709      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
 14710      * This passes through to the DOM node, allowing for custom attributes.
       
 14711      * @method getAttribute
       
 14712      * @for Node
       
 14713      * @for NodeList
       
 14714      * @param {string} name The attribute name
       
 14715      * @return {string} The attribute value
       
 14716      */
       
 14717     'getAttribute'
       
 14718 
       
 14719 ]);
       
 14720 /**
       
 14721  * @module node
       
 14722  * @submodule node-base
       
 14723  */
       
 14724 
       
 14725 var Y_Node = Y.Node;
       
 14726 var Y_NodeList = Y.NodeList;
       
 14727 /**
       
 14728  * List of events that route to DOM events
       
 14729  * @static
       
 14730  * @property DOM_EVENTS
       
 14731  * @for Node
       
 14732  */
       
 14733 
       
 14734 Y_Node.DOM_EVENTS = {
       
 14735     abort: 1,
       
 14736     beforeunload: 1,
       
 14737     blur: 1,
       
 14738     change: 1,
       
 14739     click: 1,
       
 14740     close: 1,
       
 14741     command: 1,
       
 14742     contextmenu: 1,
       
 14743     dblclick: 1,
       
 14744     DOMMouseScroll: 1,
       
 14745     drag: 1,
       
 14746     dragstart: 1,
       
 14747     dragenter: 1,
       
 14748     dragover: 1,
       
 14749     dragleave: 1,
       
 14750     dragend: 1,
       
 14751     drop: 1,
       
 14752     error: 1,
       
 14753     focus: 1,
       
 14754     key: 1,
       
 14755     keydown: 1,
       
 14756     keypress: 1,
       
 14757     keyup: 1,
       
 14758     load: 1,
       
 14759     message: 1,
       
 14760     mousedown: 1,
       
 14761     mouseenter: 1,
       
 14762     mouseleave: 1,
       
 14763     mousemove: 1,
       
 14764     mousemultiwheel: 1,
       
 14765     mouseout: 1,
       
 14766     mouseover: 1,
       
 14767     mouseup: 1,
       
 14768     mousewheel: 1,
       
 14769     orientationchange: 1,
       
 14770     reset: 1,
       
 14771     resize: 1,
       
 14772     select: 1,
       
 14773     selectstart: 1,
       
 14774     submit: 1,
       
 14775     scroll: 1,
       
 14776     textInput: 1,
       
 14777     unload: 1
       
 14778 };
       
 14779 
       
 14780 // Add custom event adaptors to this list.  This will make it so
       
 14781 // that delegate, key, available, contentready, etc all will
       
 14782 // be available through Node.on
       
 14783 Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
       
 14784 
       
 14785 Y.augment(Y_Node, Y.EventTarget);
       
 14786 
       
 14787 Y.mix(Y_Node.prototype, {
       
 14788     /**
       
 14789      * Removes event listeners from the node and (optionally) its subtree
       
 14790      * @method purge
       
 14791      * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
       
 14792      * node's subtree
       
 14793      * @param {String} type (optional) Only remove listeners of the specified type
       
 14794      * @chainable
       
 14795      *
       
 14796      */
       
 14797     purge: function(recurse, type) {
       
 14798         Y.Event.purgeElement(this._node, recurse, type);
       
 14799         return this;
       
 14800     }
       
 14801 
       
 14802 });
       
 14803 
       
 14804 Y.mix(Y.NodeList.prototype, {
       
 14805     _prepEvtArgs: function(type, fn, context) {
       
 14806         // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
       
 14807         var args = Y.Array(arguments, 0, true);
       
 14808 
       
 14809         if (args.length < 2) { // type only (event hash) just add nodes
       
 14810             args[2] = this._nodes;
       
 14811         } else {
       
 14812             args.splice(2, 0, this._nodes);
       
 14813         }
       
 14814 
       
 14815         args[3] = context || this; // default to NodeList instance as context
       
 14816 
       
 14817         return args;
       
 14818     },
       
 14819 
       
 14820     /**
       
 14821     Subscribe a callback function for each `Node` in the collection to execute
       
 14822     in response to a DOM event.
       
 14823 
       
 14824     NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in
       
 14825     favor of using event delegation from a parent Node.  See the Event user
       
 14826     guide for details.
       
 14827 
       
 14828     Most DOM events are associated with a preventable default behavior, such as
       
 14829     link clicks navigating to a new page.  Callbacks are passed a
       
 14830     `DOMEventFacade` object as their first argument (usually called `e`) that
       
 14831     can be used to prevent this default behavior with `e.preventDefault()`. See
       
 14832     the `DOMEventFacade` API for all available properties and methods on the
       
 14833     object.
       
 14834 
       
 14835     By default, the `this` object will be the `NodeList` that the subscription
       
 14836     came from, <em>not the `Node` that received the event</em>.  Use
       
 14837     `e.currentTarget` to refer to the `Node`.
       
 14838 
       
 14839     Returning `false` from a callback is supported as an alternative to calling
       
 14840     `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to
       
 14841     use the event methods.
       
 14842 
       
 14843     @example
       
 14844 
       
 14845         Y.all(".sku").on("keydown", function (e) {
       
 14846             if (e.keyCode === 13) {
       
 14847                 e.preventDefault();
       
 14848 
       
 14849                 // Use e.currentTarget to refer to the individual Node
       
 14850                 var item = Y.MyApp.searchInventory( e.currentTarget.get('value') );
       
 14851                 // etc ...
       
 14852             }
       
 14853         });
       
 14854 
       
 14855     @method on
       
 14856     @param {String} type The name of the event
       
 14857     @param {Function} fn The callback to execute in response to the event
       
 14858     @param {Object} [context] Override `this` object in callback
       
 14859     @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 14860     @return {EventHandle} A subscription handle capable of detaching that
       
 14861                           subscription
       
 14862     @for NodeList
       
 14863     **/
       
 14864     on: function(type, fn, context) {
       
 14865         return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 14866     },
       
 14867 
       
 14868     /**
       
 14869      * Applies an one-time event listener to each Node bound to the NodeList.
       
 14870      * @method once
       
 14871      * @param {String} type The event being listened for
       
 14872      * @param {Function} fn The handler to call when the event fires
       
 14873      * @param {Object} context The context to call the handler with.
       
 14874      * Default is the NodeList instance.
       
 14875      * @return {EventHandle} A subscription handle capable of detaching that
       
 14876      *                    subscription
       
 14877      * @for NodeList
       
 14878      */
       
 14879     once: function(type, fn, context) {
       
 14880         return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 14881     },
       
 14882 
       
 14883     /**
       
 14884      * Applies an event listener to each Node bound to the NodeList.
       
 14885      * The handler is called only after all on() handlers are called
       
 14886      * and the event is not prevented.
       
 14887      * @method after
       
 14888      * @param {String} type The event being listened for
       
 14889      * @param {Function} fn The handler to call when the event fires
       
 14890      * @param {Object} context The context to call the handler with.
       
 14891      * Default is the NodeList instance.
       
 14892      * @return {EventHandle} A subscription handle capable of detaching that
       
 14893      *                    subscription
       
 14894      * @for NodeList
       
 14895      */
       
 14896     after: function(type, fn, context) {
       
 14897         return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 14898     },
       
 14899 
       
 14900     /**
       
 14901      * Applies an one-time event listener to each Node bound to the NodeList
       
 14902      * that will be called only after all on() handlers are called and the
       
 14903      * event is not prevented.
       
 14904      *
       
 14905      * @method onceAfter
       
 14906      * @param {String} type The event being listened for
       
 14907      * @param {Function} fn The handler to call when the event fires
       
 14908      * @param {Object} context The context to call the handler with.
       
 14909      * Default is the NodeList instance.
       
 14910      * @return {EventHandle} A subscription handle capable of detaching that
       
 14911      *                    subscription
       
 14912      * @for NodeList
       
 14913      */
       
 14914     onceAfter: function(type, fn, context) {
       
 14915         return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 14916     }
       
 14917 });
       
 14918 
       
 14919 Y_NodeList.importMethod(Y.Node.prototype, [
       
 14920     /**
       
 14921       * Called on each Node instance
       
 14922       * @method detach
       
 14923       * @see Node.detach
       
 14924       * @for NodeList
       
 14925       */
       
 14926     'detach',
       
 14927 
       
 14928     /** Called on each Node instance
       
 14929       * @method detachAll
       
 14930       * @see Node.detachAll
       
 14931       * @for NodeList
       
 14932       */
       
 14933     'detachAll'
       
 14934 ]);
       
 14935 
       
 14936 /**
       
 14937 Subscribe a callback function to execute in response to a DOM event or custom
       
 14938 event.
       
 14939 
       
 14940 Most DOM events are associated with a preventable default behavior such as
       
 14941 link clicks navigating to a new page.  Callbacks are passed a `DOMEventFacade`
       
 14942 object as their first argument (usually called `e`) that can be used to
       
 14943 prevent this default behavior with `e.preventDefault()`. See the
       
 14944 `DOMEventFacade` API for all available properties and methods on the object.
       
 14945 
       
 14946 If the event name passed as the first parameter is not a whitelisted DOM event,
       
 14947 it will be treated as a custom event subscriptions, allowing
       
 14948 `node.fire('customEventName')` later in the code.  Refer to the Event user guide
       
 14949 for the full DOM event whitelist.
       
 14950 
       
 14951 By default, the `this` object in the callback will refer to the subscribed
       
 14952 `Node`.
       
 14953 
       
 14954 Returning `false` from a callback is supported as an alternative to calling
       
 14955 `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to use
       
 14956 the event methods.
       
 14957 
       
 14958 @example
       
 14959 
       
 14960     Y.one("#my-form").on("submit", function (e) {
       
 14961         e.preventDefault();
       
 14962 
       
 14963         // proceed with ajax form submission instead...
       
 14964     });
       
 14965 
       
 14966 @method on
       
 14967 @param {String} type The name of the event
       
 14968 @param {Function} fn The callback to execute in response to the event
       
 14969 @param {Object} [context] Override `this` object in callback
       
 14970 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 14971 @return {EventHandle} A subscription handle capable of detaching that
       
 14972                       subscription
       
 14973 @for Node
       
 14974 **/
       
 14975 
       
 14976 Y.mix(Y.Node.ATTRS, {
       
 14977     offsetHeight: {
       
 14978         setter: function(h) {
       
 14979             Y.DOM.setHeight(this._node, h);
       
 14980             return h;
       
 14981         },
       
 14982 
       
 14983         getter: function() {
       
 14984             return this._node.offsetHeight;
       
 14985         }
       
 14986     },
       
 14987 
       
 14988     offsetWidth: {
       
 14989         setter: function(w) {
       
 14990             Y.DOM.setWidth(this._node, w);
       
 14991             return w;
       
 14992         },
       
 14993 
       
 14994         getter: function() {
       
 14995             return this._node.offsetWidth;
       
 14996         }
       
 14997     }
       
 14998 });
       
 14999 
       
 15000 Y.mix(Y.Node.prototype, {
       
 15001     sizeTo: function(w, h) {
       
 15002         var node;
       
 15003         if (arguments.length < 2) {
       
 15004             node = Y.one(w);
       
 15005             w = node.get('offsetWidth');
       
 15006             h = node.get('offsetHeight');
       
 15007         }
       
 15008 
       
 15009         this.setAttrs({
       
 15010             offsetWidth: w,
       
 15011             offsetHeight: h
       
 15012         });
       
 15013     }
       
 15014 });
       
 15015 /**
       
 15016  * @module node
       
 15017  * @submodule node-base
       
 15018  */
       
 15019 
       
 15020 var Y_Node = Y.Node;
       
 15021 
       
 15022 Y.mix(Y_Node.prototype, {
       
 15023     /**
       
 15024      * Makes the node visible.
       
 15025      * If the "transition" module is loaded, show optionally
       
 15026      * animates the showing of the node using either the default
       
 15027      * transition effect ('fadeIn'), or the given named effect.
       
 15028      * @method show
       
 15029      * @for Node
       
 15030      * @param {String} name A named Transition effect to use as the show effect.
       
 15031      * @param {Object} config Options to use with the transition.
       
 15032      * @param {Function} callback An optional function to run after the transition completes.
       
 15033      * @chainable
       
 15034      */
       
 15035     show: function(callback) {
       
 15036         callback = arguments[arguments.length - 1];
       
 15037         this.toggleView(true, callback);
       
 15038         return this;
       
 15039     },
       
 15040 
       
 15041     /**
       
 15042      * The implementation for showing nodes.
       
 15043      * Default is to remove the hidden attribute and reset the CSS style.display property.
       
 15044      * @method _show
       
 15045      * @protected
       
 15046      * @chainable
       
 15047      */
       
 15048     _show: function() {
       
 15049         this.removeAttribute('hidden');
       
 15050 
       
 15051         // For back-compat we need to leave this in for browsers that
       
 15052         // do not visually hide a node via the hidden attribute
       
 15053         // and for users that check visibility based on style display.
       
 15054         this.setStyle('display', '');
       
 15055 
       
 15056     },
       
 15057 
       
 15058     _isHidden: function() {
       
 15059         return Y.DOM.getAttribute(this._node, 'hidden') === 'true';
       
 15060     },
       
 15061 
       
 15062     /**
       
 15063      * Displays or hides the node.
       
 15064      * If the "transition" module is loaded, toggleView optionally
       
 15065      * animates the toggling of the node using given named effect.
       
 15066      * @method toggleView
       
 15067      * @for Node
       
 15068      * @param {String} [name] An optional string value to use as transition effect.
       
 15069      * @param {Boolean} [on] An optional boolean value to force the node to be shown or hidden
       
 15070      * @param {Function} [callback] An optional function to run after the transition completes.
       
 15071      * @chainable
       
 15072      */
       
 15073     toggleView: function(on, callback) {
       
 15074         this._toggleView.apply(this, arguments);
       
 15075         return this;
       
 15076     },
       
 15077 
       
 15078     _toggleView: function(on, callback) {
       
 15079         callback = arguments[arguments.length - 1];
       
 15080 
       
 15081         // base on current state if not forcing
       
 15082         if (typeof on != 'boolean') {
       
 15083             on = (this._isHidden()) ? 1 : 0;
       
 15084         }
       
 15085 
       
 15086         if (on) {
       
 15087             this._show();
       
 15088         }  else {
       
 15089             this._hide();
       
 15090         }
       
 15091 
       
 15092         if (typeof callback == 'function') {
       
 15093             callback.call(this);
       
 15094         }
       
 15095 
       
 15096         return this;
       
 15097     },
       
 15098 
       
 15099     /**
       
 15100      * Hides the node.
       
 15101      * If the "transition" module is loaded, hide optionally
       
 15102      * animates the hiding of the node using either the default
       
 15103      * transition effect ('fadeOut'), or the given named effect.
       
 15104      * @method hide
       
 15105      * @param {String} name A named Transition effect to use as the show effect.
       
 15106      * @param {Object} config Options to use with the transition.
       
 15107      * @param {Function} callback An optional function to run after the transition completes.
       
 15108      * @chainable
       
 15109      */
       
 15110     hide: function(callback) {
       
 15111         callback = arguments[arguments.length - 1];
       
 15112         this.toggleView(false, callback);
       
 15113         return this;
       
 15114     },
       
 15115 
       
 15116     /**
       
 15117      * The implementation for hiding nodes.
       
 15118      * Default is to set the hidden attribute to true and set the CSS style.display to 'none'.
       
 15119      * @method _hide
       
 15120      * @protected
       
 15121      * @chainable
       
 15122      */
       
 15123     _hide: function() {
       
 15124         this.setAttribute('hidden', true);
       
 15125 
       
 15126         // For back-compat we need to leave this in for browsers that
       
 15127         // do not visually hide a node via the hidden attribute
       
 15128         // and for users that check visibility based on style display.
       
 15129         this.setStyle('display', 'none');
       
 15130     }
       
 15131 });
       
 15132 
       
 15133 Y.NodeList.importMethod(Y.Node.prototype, [
       
 15134     /**
       
 15135      * Makes each node visible.
       
 15136      * If the "transition" module is loaded, show optionally
       
 15137      * animates the showing of the node using either the default
       
 15138      * transition effect ('fadeIn'), or the given named effect.
       
 15139      * @method show
       
 15140      * @param {String} name A named Transition effect to use as the show effect.
       
 15141      * @param {Object} config Options to use with the transition.
       
 15142      * @param {Function} callback An optional function to run after the transition completes.
       
 15143      * @for NodeList
       
 15144      * @chainable
       
 15145      */
       
 15146     'show',
       
 15147 
       
 15148     /**
       
 15149      * Hides each node.
       
 15150      * If the "transition" module is loaded, hide optionally
       
 15151      * animates the hiding of the node using either the default
       
 15152      * transition effect ('fadeOut'), or the given named effect.
       
 15153      * @method hide
       
 15154      * @param {String} name A named Transition effect to use as the show effect.
       
 15155      * @param {Object} config Options to use with the transition.
       
 15156      * @param {Function} callback An optional function to run after the transition completes.
       
 15157      * @chainable
       
 15158      */
       
 15159     'hide',
       
 15160 
       
 15161     /**
       
 15162      * Displays or hides each node.
       
 15163      * If the "transition" module is loaded, toggleView optionally
       
 15164      * animates the toggling of the nodes using given named effect.
       
 15165      * @method toggleView
       
 15166      * @param {String} [name] An optional string value to use as transition effect.
       
 15167      * @param {Boolean} [on] An optional boolean value to force the nodes to be shown or hidden
       
 15168      * @param {Function} [callback] An optional function to run after the transition completes.
       
 15169      * @chainable
       
 15170      */
       
 15171     'toggleView'
       
 15172 ]);
       
 15173 
       
 15174 if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
       
 15175     Y.Node.prototype.hasAttribute = function(attr) {
       
 15176         if (attr === 'value') {
       
 15177             if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
       
 15178                 return true;
       
 15179             }
       
 15180         }
       
 15181         return !!(this._node.attributes[attr] &&
       
 15182                 this._node.attributes[attr].specified);
       
 15183     };
       
 15184 }
       
 15185 
       
 15186 // IE throws an error when calling focus() on an element that's invisible, not
       
 15187 // displayed, or disabled.
       
 15188 Y.Node.prototype.focus = function () {
       
 15189     try {
       
 15190         this._node.focus();
       
 15191     } catch (e) {
       
 15192     }
       
 15193 
       
 15194     return this;
       
 15195 };
       
 15196 
       
 15197 // IE throws error when setting input.type = 'hidden',
       
 15198 // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
       
 15199 Y.Node.ATTRS.type = {
       
 15200     setter: function(val) {
       
 15201         if (val === 'hidden') {
       
 15202             try {
       
 15203                 this._node.type = 'hidden';
       
 15204             } catch(e) {
       
 15205                 this.setStyle('display', 'none');
       
 15206                 this._inputType = 'hidden';
       
 15207             }
       
 15208         } else {
       
 15209             try { // IE errors when changing the type from "hidden'
       
 15210                 this._node.type = val;
       
 15211             } catch (e) {
       
 15212             }
       
 15213         }
       
 15214         return val;
       
 15215     },
       
 15216 
       
 15217     getter: function() {
       
 15218         return this._inputType || this._node.type;
       
 15219     },
       
 15220 
       
 15221     _bypassProxy: true // don't update DOM when using with Attribute
       
 15222 };
       
 15223 
       
 15224 if (Y.config.doc.createElement('form').elements.nodeType) {
       
 15225     // IE: elements collection is also FORM node which trips up scrubVal.
       
 15226     Y.Node.ATTRS.elements = {
       
 15227             getter: function() {
       
 15228                 return this.all('input, textarea, button, select');
       
 15229             }
       
 15230     };
       
 15231 }
       
 15232 
       
 15233 /**
       
 15234  * Provides methods for managing custom Node data.
       
 15235  * 
       
 15236  * @module node
       
 15237  * @main node
       
 15238  * @submodule node-data
       
 15239  */
       
 15240 
       
 15241 Y.mix(Y.Node.prototype, {
       
 15242     _initData: function() {
       
 15243         if (! ('_data' in this)) {
       
 15244             this._data = {};
       
 15245         }
       
 15246     },
       
 15247 
       
 15248     /**
       
 15249     * @method getData
       
 15250     * @for Node
       
 15251     * @description Retrieves arbitrary data stored on a Node instance.
       
 15252     * If no data is associated with the Node, it will attempt to retrieve
       
 15253     * a value from the corresponding HTML data attribute. (e.g. node.getData('foo')
       
 15254     * will check node.getAttribute('data-foo')).
       
 15255     * @param {string} name Optional name of the data field to retrieve.
       
 15256     * If no name is given, all data is returned.
       
 15257     * @return {any | Object} Whatever is stored at the given field,
       
 15258     * or an object hash of all fields.
       
 15259     */
       
 15260     getData: function(name) {
       
 15261         this._initData();
       
 15262         var data = this._data,
       
 15263             ret = data;
       
 15264 
       
 15265         if (arguments.length) { // single field
       
 15266             if (name in data) {
       
 15267                 ret = data[name];
       
 15268             } else { // initialize from HTML attribute
       
 15269                 ret = this._getDataAttribute(name);
       
 15270             }
       
 15271         } else if (typeof data == 'object' && data !== null) { // all fields
       
 15272             ret = {};
       
 15273             Y.Object.each(data, function(v, n) {
       
 15274                 ret[n] = v;
       
 15275             });
       
 15276 
       
 15277             ret = this._getDataAttributes(ret);
       
 15278         }
       
 15279 
       
 15280         return ret;
       
 15281 
       
 15282     },
       
 15283 
       
 15284     _getDataAttributes: function(ret) {
       
 15285         ret = ret || {};
       
 15286         var i = 0,
       
 15287             attrs = this._node.attributes,
       
 15288             len = attrs.length,
       
 15289             prefix = this.DATA_PREFIX,
       
 15290             prefixLength = prefix.length,
       
 15291             name;
       
 15292 
       
 15293         while (i < len) {
       
 15294             name = attrs[i].name;
       
 15295             if (name.indexOf(prefix) === 0) {
       
 15296                 name = name.substr(prefixLength);
       
 15297                 if (!(name in ret)) { // only merge if not already stored
       
 15298                     ret[name] = this._getDataAttribute(name);
       
 15299                 }
       
 15300             }
       
 15301 
       
 15302             i += 1;
       
 15303         }
       
 15304 
       
 15305         return ret;
       
 15306     },
       
 15307 
       
 15308     _getDataAttribute: function(name) {
       
 15309         name = this.DATA_PREFIX + name;
       
 15310 
       
 15311         var node = this._node,
       
 15312             attrs = node.attributes,
       
 15313             data = attrs && attrs[name] && attrs[name].value;
       
 15314 
       
 15315         return data;
       
 15316     },
       
 15317 
       
 15318     /**
       
 15319     * @method setData
       
 15320     * @for Node
       
 15321     * @description Stores arbitrary data on a Node instance.
       
 15322     * This is not stored with the DOM node.
       
 15323     * @param {string} name The name of the field to set. If no val
       
 15324     * is given, name is treated as the data and overrides any existing data.
       
 15325     * @param {any} val The value to be assigned to the field.
       
 15326     * @chainable
       
 15327     */
       
 15328     setData: function(name, val) {
       
 15329         this._initData();
       
 15330         if (arguments.length > 1) {
       
 15331             this._data[name] = val;
       
 15332         } else {
       
 15333             this._data = name;
       
 15334         }
       
 15335 
       
 15336        return this;
       
 15337     },
       
 15338 
       
 15339     /**
       
 15340     * @method clearData
       
 15341     * @for Node
       
 15342     * @description Clears internally stored data.
       
 15343     * @param {string} name The name of the field to clear. If no name
       
 15344     * is given, all data is cleared.
       
 15345     * @chainable
       
 15346     */
       
 15347     clearData: function(name) {
       
 15348         if ('_data' in this) {
       
 15349             if (typeof name != 'undefined') {
       
 15350                 delete this._data[name];
       
 15351             } else {
       
 15352                 delete this._data;
       
 15353             }
       
 15354         }
       
 15355 
       
 15356         return this;
       
 15357     }
       
 15358 });
       
 15359 
       
 15360 Y.mix(Y.NodeList.prototype, {
       
 15361     /**
       
 15362     * @method getData
       
 15363     * @for NodeList
       
 15364     * @description Retrieves arbitrary data stored on each Node instance
       
 15365     * bound to the NodeList.
       
 15366     * @see Node
       
 15367     * @param {string} name Optional name of the data field to retrieve.
       
 15368     * If no name is given, all data is returned.
       
 15369     * @return {Array} An array containing all of the data for each Node instance. 
       
 15370     * or an object hash of all fields.
       
 15371     */
       
 15372     getData: function(name) {
       
 15373         var args = (arguments.length) ? [name] : [];
       
 15374         return this._invoke('getData', args, true);
       
 15375     },
       
 15376 
       
 15377     /**
       
 15378     * @method setData
       
 15379     * @for NodeList
       
 15380     * @description Stores arbitrary data on each Node instance bound to the
       
 15381     *  NodeList. This is not stored with the DOM node.
       
 15382     * @param {string} name The name of the field to set. If no name
       
 15383     * is given, name is treated as the data and overrides any existing data.
       
 15384     * @param {any} val The value to be assigned to the field.
       
 15385     * @chainable
       
 15386     */
       
 15387     setData: function(name, val) {
       
 15388         var args = (arguments.length > 1) ? [name, val] : [name];
       
 15389         return this._invoke('setData', args);
       
 15390     },
       
 15391 
       
 15392     /**
       
 15393     * @method clearData
       
 15394     * @for NodeList
       
 15395     * @description Clears data on all Node instances bound to the NodeList.
       
 15396     * @param {string} name The name of the field to clear. If no name
       
 15397     * is given, all data is cleared.
       
 15398     * @chainable
       
 15399     */
       
 15400     clearData: function(name) {
       
 15401         var args = (arguments.length) ? [name] : [];
       
 15402         return this._invoke('clearData', [name]);
       
 15403     }
       
 15404 });
       
 15405 
       
 15406 
       
 15407 }, '@VERSION@', {"requires": ["event-base", "node-core", "dom-base"]});
       
 15408 (function () {
       
 15409 var GLOBAL_ENV = YUI.Env;
       
 15410 
       
 15411 if (!GLOBAL_ENV._ready) {
       
 15412     GLOBAL_ENV._ready = function() {
       
 15413         GLOBAL_ENV.DOMReady = true;
       
 15414         GLOBAL_ENV.remove(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
       
 15415     };
       
 15416 
       
 15417     GLOBAL_ENV.add(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
       
 15418 }
       
 15419 })();
       
 15420 YUI.add('event-base', function (Y, NAME) {
       
 15421 
       
 15422 /*
       
 15423  * DOM event listener abstraction layer
       
 15424  * @module event
       
 15425  * @submodule event-base
       
 15426  */
       
 15427 
       
 15428 /**
       
 15429  * The domready event fires at the moment the browser's DOM is
       
 15430  * usable. In most cases, this is before images are fully
       
 15431  * downloaded, allowing you to provide a more responsive user
       
 15432  * interface.
       
 15433  *
       
 15434  * In YUI 3, domready subscribers will be notified immediately if
       
 15435  * that moment has already passed when the subscription is created.
       
 15436  *
       
 15437  * One exception is if the yui.js file is dynamically injected into
       
 15438  * the page.  If this is done, you must tell the YUI instance that
       
 15439  * you did this in order for DOMReady (and window load events) to
       
 15440  * fire normally.  That configuration option is 'injected' -- set
       
 15441  * it to true if the yui.js script is not included inline.
       
 15442  *
       
 15443  * This method is part of the 'event-ready' module, which is a
       
 15444  * submodule of 'event'.
       
 15445  *
       
 15446  * @event domready
       
 15447  * @for YUI
       
 15448  */
       
 15449 Y.publish('domready', {
       
 15450     fireOnce: true,
       
 15451     async: true
       
 15452 });
       
 15453 
       
 15454 if (YUI.Env.DOMReady) {
       
 15455     Y.fire('domready');
       
 15456 } else {
       
 15457     Y.Do.before(function() { Y.fire('domready'); }, YUI.Env, '_ready');
       
 15458 }
       
 15459 
       
 15460 /**
       
 15461  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 15462  * events.
       
 15463  * @module event
       
 15464  * @submodule event-base
       
 15465  */
       
 15466 
       
 15467 /**
       
 15468  * Wraps a DOM event, properties requiring browser abstraction are
       
 15469  * fixed here.  Provids a security layer when required.
       
 15470  * @class DOMEventFacade
       
 15471  * @param ev {Event} the DOM event
       
 15472  * @param currentTarget {HTMLElement} the element the listener was attached to
       
 15473  * @param wrapper {Event.Custom} the custom event wrapper for this DOM event
       
 15474  */
       
 15475 
       
 15476     var ua = Y.UA,
       
 15477 
       
 15478     EMPTY = {},
       
 15479 
       
 15480     /**
       
 15481      * webkit key remapping required for Safari < 3.1
       
 15482      * @property webkitKeymap
       
 15483      * @private
       
 15484      */
       
 15485     webkitKeymap = {
       
 15486         63232: 38, // up
       
 15487         63233: 40, // down
       
 15488         63234: 37, // left
       
 15489         63235: 39, // right
       
 15490         63276: 33, // page up
       
 15491         63277: 34, // page down
       
 15492         25:     9, // SHIFT-TAB (Safari provides a different key code in
       
 15493                    // this case, even though the shiftKey modifier is set)
       
 15494         63272: 46, // delete
       
 15495         63273: 36, // home
       
 15496         63275: 35  // end
       
 15497     },
       
 15498 
       
 15499     /**
       
 15500      * Returns a wrapped node.  Intended to be used on event targets,
       
 15501      * so it will return the node's parent if the target is a text
       
 15502      * node.
       
 15503      *
       
 15504      * If accessing a property of the node throws an error, this is
       
 15505      * probably the anonymous div wrapper Gecko adds inside text
       
 15506      * nodes.  This likely will only occur when attempting to access
       
 15507      * the relatedTarget.  In this case, we now return null because
       
 15508      * the anonymous div is completely useless and we do not know
       
 15509      * what the related target was because we can't even get to
       
 15510      * the element's parent node.
       
 15511      *
       
 15512      * @method resolve
       
 15513      * @private
       
 15514      */
       
 15515     resolve = function(n) {
       
 15516         if (!n) {
       
 15517             return n;
       
 15518         }
       
 15519         try {
       
 15520             if (n && 3 == n.nodeType) {
       
 15521                 n = n.parentNode;
       
 15522             }
       
 15523         } catch(e) {
       
 15524             return null;
       
 15525         }
       
 15526 
       
 15527         return Y.one(n);
       
 15528     },
       
 15529 
       
 15530     DOMEventFacade = function(ev, currentTarget, wrapper) {
       
 15531         this._event = ev;
       
 15532         this._currentTarget = currentTarget;
       
 15533         this._wrapper = wrapper || EMPTY;
       
 15534 
       
 15535         // if not lazy init
       
 15536         this.init();
       
 15537     };
       
 15538 
       
 15539 Y.extend(DOMEventFacade, Object, {
       
 15540 
       
 15541     init: function() {
       
 15542 
       
 15543         var e = this._event,
       
 15544             overrides = this._wrapper.overrides,
       
 15545             x = e.pageX,
       
 15546             y = e.pageY,
       
 15547             c,
       
 15548             currentTarget = this._currentTarget;
       
 15549 
       
 15550         this.altKey   = e.altKey;
       
 15551         this.ctrlKey  = e.ctrlKey;
       
 15552         this.metaKey  = e.metaKey;
       
 15553         this.shiftKey = e.shiftKey;
       
 15554         this.type     = (overrides && overrides.type) || e.type;
       
 15555         this.clientX  = e.clientX;
       
 15556         this.clientY  = e.clientY;
       
 15557 
       
 15558         this.pageX = x;
       
 15559         this.pageY = y;
       
 15560 
       
 15561         // charCode is unknown in keyup, keydown. keyCode is unknown in keypress.
       
 15562         // FF 3.6 - 8+? pass 0 for keyCode in keypress events.
       
 15563         // Webkit, FF 3.6-8+?, and IE9+? pass 0 for charCode in keydown, keyup.
       
 15564         // Webkit and IE9+? duplicate charCode in keyCode.
       
 15565         // Opera never sets charCode, always keyCode (though with the charCode).
       
 15566         // IE6-8 don't set charCode or which.
       
 15567         // All browsers other than IE6-8 set which=keyCode in keydown, keyup, and
       
 15568         // which=charCode in keypress.
       
 15569         //
       
 15570         // Moral of the story: (e.which || e.keyCode) will always return the
       
 15571         // known code for that key event phase. e.keyCode is often different in
       
 15572         // keypress from keydown and keyup.
       
 15573         c = e.keyCode || e.charCode;
       
 15574 
       
 15575         if (ua.webkit && (c in webkitKeymap)) {
       
 15576             c = webkitKeymap[c];
       
 15577         }
       
 15578 
       
 15579         this.keyCode = c;
       
 15580         this.charCode = c;
       
 15581         // Fill in e.which for IE - implementers should always use this over
       
 15582         // e.keyCode or e.charCode.
       
 15583         this.which = e.which || e.charCode || c;
       
 15584         // this.button = e.button;
       
 15585         this.button = this.which;
       
 15586 
       
 15587         this.target = resolve(e.target);
       
 15588         this.currentTarget = resolve(currentTarget);
       
 15589         this.relatedTarget = resolve(e.relatedTarget);
       
 15590 
       
 15591         if (e.type == "mousewheel" || e.type == "DOMMouseScroll") {
       
 15592             this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
       
 15593         }
       
 15594 
       
 15595         if (this._touch) {
       
 15596             this._touch(e, currentTarget, this._wrapper);
       
 15597         }
       
 15598     },
       
 15599 
       
 15600     stopPropagation: function() {
       
 15601         this._event.stopPropagation();
       
 15602         this._wrapper.stopped = 1;
       
 15603         this.stopped = 1;
       
 15604     },
       
 15605 
       
 15606     stopImmediatePropagation: function() {
       
 15607         var e = this._event;
       
 15608         if (e.stopImmediatePropagation) {
       
 15609             e.stopImmediatePropagation();
       
 15610         } else {
       
 15611             this.stopPropagation();
       
 15612         }
       
 15613         this._wrapper.stopped = 2;
       
 15614         this.stopped = 2;
       
 15615     },
       
 15616 
       
 15617     preventDefault: function(returnValue) {
       
 15618         var e = this._event;
       
 15619         e.preventDefault();
       
 15620         e.returnValue = returnValue || false;
       
 15621         this._wrapper.prevented = 1;
       
 15622         this.prevented = 1;
       
 15623     },
       
 15624 
       
 15625     halt: function(immediate) {
       
 15626         if (immediate) {
       
 15627             this.stopImmediatePropagation();
       
 15628         } else {
       
 15629             this.stopPropagation();
       
 15630         }
       
 15631 
       
 15632         this.preventDefault();
       
 15633     }
       
 15634 
       
 15635 });
       
 15636 
       
 15637 DOMEventFacade.resolve = resolve;
       
 15638 Y.DOM2EventFacade = DOMEventFacade;
       
 15639 Y.DOMEventFacade = DOMEventFacade;
       
 15640 
       
 15641     /**
       
 15642      * The native event
       
 15643      * @property _event
       
 15644      * @type {Native DOM Event}
       
 15645      * @private
       
 15646      */
       
 15647 
       
 15648     /**
       
 15649     The name of the event (e.g. "click")
       
 15650 
       
 15651     @property type
       
 15652     @type {String}
       
 15653     **/
       
 15654 
       
 15655     /**
       
 15656     `true` if the "alt" or "option" key is pressed.
       
 15657 
       
 15658     @property altKey
       
 15659     @type {Boolean}
       
 15660     **/
       
 15661 
       
 15662     /**
       
 15663     `true` if the shift key is pressed.
       
 15664 
       
 15665     @property shiftKey
       
 15666     @type {Boolean}
       
 15667     **/
       
 15668 
       
 15669     /**
       
 15670     `true` if the "Windows" key on a Windows keyboard, "command" key on an
       
 15671     Apple keyboard, or "meta" key on other keyboards is pressed.
       
 15672 
       
 15673     @property metaKey
       
 15674     @type {Boolean}
       
 15675     **/
       
 15676 
       
 15677     /**
       
 15678     `true` if the "Ctrl" or "control" key is pressed.
       
 15679 
       
 15680     @property ctrlKey
       
 15681     @type {Boolean}
       
 15682     **/
       
 15683 
       
 15684     /**
       
 15685      * The X location of the event on the page (including scroll)
       
 15686      * @property pageX
       
 15687      * @type {Number}
       
 15688      */
       
 15689 
       
 15690     /**
       
 15691      * The Y location of the event on the page (including scroll)
       
 15692      * @property pageY
       
 15693      * @type {Number}
       
 15694      */
       
 15695 
       
 15696     /**
       
 15697      * The X location of the event in the viewport
       
 15698      * @property clientX
       
 15699      * @type {Number}
       
 15700      */
       
 15701 
       
 15702     /**
       
 15703      * The Y location of the event in the viewport
       
 15704      * @property clientY
       
 15705      * @type {Number}
       
 15706      */
       
 15707 
       
 15708     /**
       
 15709      * The keyCode for key events.  Uses charCode if keyCode is not available
       
 15710      * @property keyCode
       
 15711      * @type {Number}
       
 15712      */
       
 15713 
       
 15714     /**
       
 15715      * The charCode for key events.  Same as keyCode
       
 15716      * @property charCode
       
 15717      * @type {Number}
       
 15718      */
       
 15719 
       
 15720     /**
       
 15721      * The button that was pushed. 1 for left click, 2 for middle click, 3 for
       
 15722      * right click.  This is only reliably populated on `mouseup` events.
       
 15723      * @property button
       
 15724      * @type {Number}
       
 15725      */
       
 15726 
       
 15727     /**
       
 15728      * The button that was pushed.  Same as button.
       
 15729      * @property which
       
 15730      * @type {Number}
       
 15731      */
       
 15732 
       
 15733     /**
       
 15734      * Node reference for the targeted element
       
 15735      * @property target
       
 15736      * @type {Node}
       
 15737      */
       
 15738 
       
 15739     /**
       
 15740      * Node reference for the element that the listener was attached to.
       
 15741      * @property currentTarget
       
 15742      * @type {Node}
       
 15743      */
       
 15744 
       
 15745     /**
       
 15746      * Node reference to the relatedTarget
       
 15747      * @property relatedTarget
       
 15748      * @type {Node}
       
 15749      */
       
 15750 
       
 15751     /**
       
 15752      * Number representing the direction and velocity of the movement of the mousewheel.
       
 15753      * Negative is down, the higher the number, the faster.  Applies to the mousewheel event.
       
 15754      * @property wheelDelta
       
 15755      * @type {Number}
       
 15756      */
       
 15757 
       
 15758     /**
       
 15759      * Stops the propagation to the next bubble target
       
 15760      * @method stopPropagation
       
 15761      */
       
 15762 
       
 15763     /**
       
 15764      * Stops the propagation to the next bubble target and
       
 15765      * prevents any additional listeners from being exectued
       
 15766      * on the current target.
       
 15767      * @method stopImmediatePropagation
       
 15768      */
       
 15769 
       
 15770     /**
       
 15771      * Prevents the event's default behavior
       
 15772      * @method preventDefault
       
 15773      * @param returnValue {string} sets the returnValue of the event to this value
       
 15774      * (rather than the default false value).  This can be used to add a customized
       
 15775      * confirmation query to the beforeunload event).
       
 15776      */
       
 15777 
       
 15778     /**
       
 15779      * Stops the event propagation and prevents the default
       
 15780      * event behavior.
       
 15781      * @method halt
       
 15782      * @param immediate {boolean} if true additional listeners
       
 15783      * on the current target will not be executed
       
 15784      */
       
 15785 (function() {
       
 15786 
       
 15787 /**
       
 15788  * The event utility provides functions to add and remove event listeners,
       
 15789  * event cleansing.  It also tries to automatically remove listeners it
       
 15790  * registers during the unload event.
       
 15791  * @module event
       
 15792  * @main event
       
 15793  * @submodule event-base
       
 15794  */
       
 15795 
       
 15796 /**
       
 15797  * The event utility provides functions to add and remove event listeners,
       
 15798  * event cleansing.  It also tries to automatically remove listeners it
       
 15799  * registers during the unload event.
       
 15800  *
       
 15801  * @class Event
       
 15802  * @static
       
 15803  */
       
 15804 
       
 15805 Y.Env.evt.dom_wrappers = {};
       
 15806 Y.Env.evt.dom_map = {};
       
 15807 
       
 15808 var _eventenv = Y.Env.evt,
       
 15809     config = Y.config,
       
 15810     win = config.win,
       
 15811     add = YUI.Env.add,
       
 15812     remove = YUI.Env.remove,
       
 15813 
       
 15814     onLoad = function() {
       
 15815         YUI.Env.windowLoaded = true;
       
 15816         Y.Event._load();
       
 15817         remove(win, "load", onLoad);
       
 15818     },
       
 15819 
       
 15820     onUnload = function() {
       
 15821         Y.Event._unload();
       
 15822     },
       
 15823 
       
 15824     EVENT_READY = 'domready',
       
 15825 
       
 15826     COMPAT_ARG = '~yui|2|compat~',
       
 15827 
       
 15828     shouldIterate = function(o) {
       
 15829         try {
       
 15830             // TODO: See if there's a more performant way to return true early on this, for the common case
       
 15831             return (o && typeof o !== "string" && Y.Lang.isNumber(o.length) && !o.tagName && !Y.DOM.isWindow(o));
       
 15832         } catch(ex) {
       
 15833             return false;
       
 15834         }
       
 15835     },
       
 15836 
       
 15837     // aliases to support DOM event subscription clean up when the last
       
 15838     // subscriber is detached. deleteAndClean overrides the DOM event's wrapper
       
 15839     // CustomEvent _delete method.
       
 15840     _ceProtoDelete = Y.CustomEvent.prototype._delete,
       
 15841     _deleteAndClean = function(s) {
       
 15842         var ret = _ceProtoDelete.apply(this, arguments);
       
 15843 
       
 15844         if (!this.hasSubs()) {
       
 15845             Y.Event._clean(this);
       
 15846         }
       
 15847 
       
 15848         return ret;
       
 15849     },
       
 15850 
       
 15851 Event = function() {
       
 15852 
       
 15853     /**
       
 15854      * True after the onload event has fired
       
 15855      * @property _loadComplete
       
 15856      * @type boolean
       
 15857      * @static
       
 15858      * @private
       
 15859      */
       
 15860     var _loadComplete =  false,
       
 15861 
       
 15862     /**
       
 15863      * The number of times to poll after window.onload.  This number is
       
 15864      * increased if additional late-bound handlers are requested after
       
 15865      * the page load.
       
 15866      * @property _retryCount
       
 15867      * @static
       
 15868      * @private
       
 15869      */
       
 15870     _retryCount = 0,
       
 15871 
       
 15872     /**
       
 15873      * onAvailable listeners
       
 15874      * @property _avail
       
 15875      * @static
       
 15876      * @private
       
 15877      */
       
 15878     _avail = [],
       
 15879 
       
 15880     /**
       
 15881      * Custom event wrappers for DOM events.  Key is
       
 15882      * 'event:' + Element uid stamp + event type
       
 15883      * @property _wrappers
       
 15884      * @type Y.Event.Custom
       
 15885      * @static
       
 15886      * @private
       
 15887      */
       
 15888     _wrappers = _eventenv.dom_wrappers,
       
 15889 
       
 15890     _windowLoadKey = null,
       
 15891 
       
 15892     /**
       
 15893      * Custom event wrapper map DOM events.  Key is
       
 15894      * Element uid stamp.  Each item is a hash of custom event
       
 15895      * wrappers as provided in the _wrappers collection.  This
       
 15896      * provides the infrastructure for getListeners.
       
 15897      * @property _el_events
       
 15898      * @static
       
 15899      * @private
       
 15900      */
       
 15901     _el_events = _eventenv.dom_map;
       
 15902 
       
 15903     return {
       
 15904 
       
 15905         /**
       
 15906          * The number of times we should look for elements that are not
       
 15907          * in the DOM at the time the event is requested after the document
       
 15908          * has been loaded.  The default is 1000@amp;40 ms, so it will poll
       
 15909          * for 40 seconds or until all outstanding handlers are bound
       
 15910          * (whichever comes first).
       
 15911          * @property POLL_RETRYS
       
 15912          * @type int
       
 15913          * @static
       
 15914          * @final
       
 15915          */
       
 15916         POLL_RETRYS: 1000,
       
 15917 
       
 15918         /**
       
 15919          * The poll interval in milliseconds
       
 15920          * @property POLL_INTERVAL
       
 15921          * @type int
       
 15922          * @static
       
 15923          * @final
       
 15924          */
       
 15925         POLL_INTERVAL: 40,
       
 15926 
       
 15927         /**
       
 15928          * addListener/removeListener can throw errors in unexpected scenarios.
       
 15929          * These errors are suppressed, the method returns false, and this property
       
 15930          * is set
       
 15931          * @property lastError
       
 15932          * @static
       
 15933          * @type Error
       
 15934          */
       
 15935         lastError: null,
       
 15936 
       
 15937 
       
 15938         /**
       
 15939          * poll handle
       
 15940          * @property _interval
       
 15941          * @static
       
 15942          * @private
       
 15943          */
       
 15944         _interval: null,
       
 15945 
       
 15946         /**
       
 15947          * document readystate poll handle
       
 15948          * @property _dri
       
 15949          * @static
       
 15950          * @private
       
 15951          */
       
 15952          _dri: null,
       
 15953 
       
 15954         /**
       
 15955          * True when the document is initially usable
       
 15956          * @property DOMReady
       
 15957          * @type boolean
       
 15958          * @static
       
 15959          */
       
 15960         DOMReady: false,
       
 15961 
       
 15962         /**
       
 15963          * @method startInterval
       
 15964          * @static
       
 15965          * @private
       
 15966          */
       
 15967         startInterval: function() {
       
 15968             if (!Event._interval) {
       
 15969 Event._interval = setInterval(Event._poll, Event.POLL_INTERVAL);
       
 15970             }
       
 15971         },
       
 15972 
       
 15973         /**
       
 15974          * Executes the supplied callback when the item with the supplied
       
 15975          * id is found.  This is meant to be used to execute behavior as
       
 15976          * soon as possible as the page loads.  If you use this after the
       
 15977          * initial page load it will poll for a fixed time for the element.
       
 15978          * The number of times it will poll and the frequency are
       
 15979          * configurable.  By default it will poll for 10 seconds.
       
 15980          *
       
 15981          * <p>The callback is executed with a single parameter:
       
 15982          * the custom object parameter, if provided.</p>
       
 15983          *
       
 15984          * @method onAvailable
       
 15985          *
       
 15986          * @param {string||string[]}   id the id of the element, or an array
       
 15987          * of ids to look for.
       
 15988          * @param {function} fn what to execute when the element is found.
       
 15989          * @param {object}   p_obj an optional object to be passed back as
       
 15990          *                   a parameter to fn.
       
 15991          * @param {boolean|object}  p_override If set to true, fn will execute
       
 15992          *                   in the context of p_obj, if set to an object it
       
 15993          *                   will execute in the context of that object
       
 15994          * @param checkContent {boolean} check child node readiness (onContentReady)
       
 15995          * @static
       
 15996          * @deprecated Use Y.on("available")
       
 15997          */
       
 15998         // @TODO fix arguments
       
 15999         onAvailable: function(id, fn, p_obj, p_override, checkContent, compat) {
       
 16000 
       
 16001             var a = Y.Array(id), i, availHandle;
       
 16002 
       
 16003 
       
 16004             for (i=0; i<a.length; i=i+1) {
       
 16005                 _avail.push({
       
 16006                     id:         a[i],
       
 16007                     fn:         fn,
       
 16008                     obj:        p_obj,
       
 16009                     override:   p_override,
       
 16010                     checkReady: checkContent,
       
 16011                     compat:     compat
       
 16012                 });
       
 16013             }
       
 16014             _retryCount = this.POLL_RETRYS;
       
 16015 
       
 16016             // We want the first test to be immediate, but async
       
 16017             setTimeout(Event._poll, 0);
       
 16018 
       
 16019             availHandle = new Y.EventHandle({
       
 16020 
       
 16021                 _delete: function() {
       
 16022                     // set by the event system for lazy DOM listeners
       
 16023                     if (availHandle.handle) {
       
 16024                         availHandle.handle.detach();
       
 16025                         return;
       
 16026                     }
       
 16027 
       
 16028                     var i, j;
       
 16029 
       
 16030                     // otherwise try to remove the onAvailable listener(s)
       
 16031                     for (i = 0; i < a.length; i++) {
       
 16032                         for (j = 0; j < _avail.length; j++) {
       
 16033                             if (a[i] === _avail[j].id) {
       
 16034                                 _avail.splice(j, 1);
       
 16035                             }
       
 16036                         }
       
 16037                     }
       
 16038                 }
       
 16039 
       
 16040             });
       
 16041 
       
 16042             return availHandle;
       
 16043         },
       
 16044 
       
 16045         /**
       
 16046          * Works the same way as onAvailable, but additionally checks the
       
 16047          * state of sibling elements to determine if the content of the
       
 16048          * available element is safe to modify.
       
 16049          *
       
 16050          * <p>The callback is executed with a single parameter:
       
 16051          * the custom object parameter, if provided.</p>
       
 16052          *
       
 16053          * @method onContentReady
       
 16054          *
       
 16055          * @param {string}   id the id of the element to look for.
       
 16056          * @param {function} fn what to execute when the element is ready.
       
 16057          * @param {object}   obj an optional object to be passed back as
       
 16058          *                   a parameter to fn.
       
 16059          * @param {boolean|object}  override If set to true, fn will execute
       
 16060          *                   in the context of p_obj.  If an object, fn will
       
 16061          *                   exectute in the context of that object
       
 16062          *
       
 16063          * @static
       
 16064          * @deprecated Use Y.on("contentready")
       
 16065          */
       
 16066         // @TODO fix arguments
       
 16067         onContentReady: function(id, fn, obj, override, compat) {
       
 16068             return Event.onAvailable(id, fn, obj, override, true, compat);
       
 16069         },
       
 16070 
       
 16071         /**
       
 16072          * Adds an event listener
       
 16073          *
       
 16074          * @method attach
       
 16075          *
       
 16076          * @param {String}   type     The type of event to append
       
 16077          * @param {Function} fn        The method the event invokes
       
 16078          * @param {String|HTMLElement|Array|NodeList} el An id, an element
       
 16079          *  reference, or a collection of ids and/or elements to assign the
       
 16080          *  listener to.
       
 16081          * @param {Object}   context optional context object
       
 16082          * @param {Boolean|object}  args 0..n arguments to pass to the callback
       
 16083          * @return {EventHandle} an object to that can be used to detach the listener
       
 16084          *
       
 16085          * @static
       
 16086          */
       
 16087 
       
 16088         attach: function(type, fn, el, context) {
       
 16089             return Event._attach(Y.Array(arguments, 0, true));
       
 16090         },
       
 16091 
       
 16092         _createWrapper: function (el, type, capture, compat, facade) {
       
 16093 
       
 16094             var cewrapper,
       
 16095                 ek  = Y.stamp(el),
       
 16096                 key = 'event:' + ek + type;
       
 16097 
       
 16098             if (false === facade) {
       
 16099                 key += 'native';
       
 16100             }
       
 16101             if (capture) {
       
 16102                 key += 'capture';
       
 16103             }
       
 16104 
       
 16105 
       
 16106             cewrapper = _wrappers[key];
       
 16107 
       
 16108 
       
 16109             if (!cewrapper) {
       
 16110                 // create CE wrapper
       
 16111                 cewrapper = Y.publish(key, {
       
 16112                     silent: true,
       
 16113                     bubbles: false,
       
 16114                     emitFacade:false,
       
 16115                     contextFn: function() {
       
 16116                         if (compat) {
       
 16117                             return cewrapper.el;
       
 16118                         } else {
       
 16119                             cewrapper.nodeRef = cewrapper.nodeRef || Y.one(cewrapper.el);
       
 16120                             return cewrapper.nodeRef;
       
 16121                         }
       
 16122                     }
       
 16123                 });
       
 16124 
       
 16125                 cewrapper.overrides = {};
       
 16126 
       
 16127                 // for later removeListener calls
       
 16128                 cewrapper.el = el;
       
 16129                 cewrapper.key = key;
       
 16130                 cewrapper.domkey = ek;
       
 16131                 cewrapper.type = type;
       
 16132                 cewrapper.fn = function(e) {
       
 16133                     cewrapper.fire(Event.getEvent(e, el, (compat || (false === facade))));
       
 16134                 };
       
 16135                 cewrapper.capture = capture;
       
 16136 
       
 16137                 if (el == win && type == "load") {
       
 16138                     // window load happens once
       
 16139                     cewrapper.fireOnce = true;
       
 16140                     _windowLoadKey = key;
       
 16141                 }
       
 16142                 cewrapper._delete = _deleteAndClean;
       
 16143 
       
 16144                 _wrappers[key] = cewrapper;
       
 16145                 _el_events[ek] = _el_events[ek] || {};
       
 16146                 _el_events[ek][key] = cewrapper;
       
 16147 
       
 16148                 add(el, type, cewrapper.fn, capture);
       
 16149             }
       
 16150 
       
 16151             return cewrapper;
       
 16152 
       
 16153         },
       
 16154 
       
 16155         _attach: function(args, conf) {
       
 16156 
       
 16157             var compat,
       
 16158                 handles, oEl, cewrapper, context,
       
 16159                 fireNow = false, ret,
       
 16160                 type = args[0],
       
 16161                 fn = args[1],
       
 16162                 el = args[2] || win,
       
 16163                 facade = conf && conf.facade,
       
 16164                 capture = conf && conf.capture,
       
 16165                 overrides = conf && conf.overrides;
       
 16166 
       
 16167             if (args[args.length-1] === COMPAT_ARG) {
       
 16168                 compat = true;
       
 16169             }
       
 16170 
       
 16171             if (!fn || !fn.call) {
       
 16172 // throw new TypeError(type + " attach call failed, callback undefined");
       
 16173                 return false;
       
 16174             }
       
 16175 
       
 16176             // The el argument can be an array of elements or element ids.
       
 16177             if (shouldIterate(el)) {
       
 16178 
       
 16179                 handles=[];
       
 16180 
       
 16181                 Y.each(el, function(v, k) {
       
 16182                     args[2] = v;
       
 16183                     handles.push(Event._attach(args.slice(), conf));
       
 16184                 });
       
 16185 
       
 16186                 // return (handles.length === 1) ? handles[0] : handles;
       
 16187                 return new Y.EventHandle(handles);
       
 16188 
       
 16189             // If the el argument is a string, we assume it is
       
 16190             // actually the id of the element.  If the page is loaded
       
 16191             // we convert el to the actual element, otherwise we
       
 16192             // defer attaching the event until the element is
       
 16193             // ready
       
 16194             } else if (Y.Lang.isString(el)) {
       
 16195 
       
 16196                 // oEl = (compat) ? Y.DOM.byId(el) : Y.Selector.query(el);
       
 16197 
       
 16198                 if (compat) {
       
 16199                     oEl = Y.DOM.byId(el);
       
 16200                 } else {
       
 16201 
       
 16202                     oEl = Y.Selector.query(el);
       
 16203 
       
 16204                     switch (oEl.length) {
       
 16205                         case 0:
       
 16206                             oEl = null;
       
 16207                             break;
       
 16208                         case 1:
       
 16209                             oEl = oEl[0];
       
 16210                             break;
       
 16211                         default:
       
 16212                             args[2] = oEl;
       
 16213                             return Event._attach(args, conf);
       
 16214                     }
       
 16215                 }
       
 16216 
       
 16217                 if (oEl) {
       
 16218 
       
 16219                     el = oEl;
       
 16220 
       
 16221                 // Not found = defer adding the event until the element is available
       
 16222                 } else {
       
 16223 
       
 16224                     ret = Event.onAvailable(el, function() {
       
 16225 
       
 16226                         ret.handle = Event._attach(args, conf);
       
 16227 
       
 16228                     }, Event, true, false, compat);
       
 16229 
       
 16230                     return ret;
       
 16231 
       
 16232                 }
       
 16233             }
       
 16234 
       
 16235             // Element should be an html element or node
       
 16236             if (!el) {
       
 16237                 return false;
       
 16238             }
       
 16239 
       
 16240             if (Y.Node && Y.instanceOf(el, Y.Node)) {
       
 16241                 el = Y.Node.getDOMNode(el);
       
 16242             }
       
 16243 
       
 16244             cewrapper = Event._createWrapper(el, type, capture, compat, facade);
       
 16245             if (overrides) {
       
 16246                 Y.mix(cewrapper.overrides, overrides);
       
 16247             }
       
 16248 
       
 16249             if (el == win && type == "load") {
       
 16250 
       
 16251                 // if the load is complete, fire immediately.
       
 16252                 // all subscribers, including the current one
       
 16253                 // will be notified.
       
 16254                 if (YUI.Env.windowLoaded) {
       
 16255                     fireNow = true;
       
 16256                 }
       
 16257             }
       
 16258 
       
 16259             if (compat) {
       
 16260                 args.pop();
       
 16261             }
       
 16262 
       
 16263             context = args[3];
       
 16264 
       
 16265             // set context to the Node if not specified
       
 16266             // ret = cewrapper.on.apply(cewrapper, trimmedArgs);
       
 16267             ret = cewrapper._on(fn, context, (args.length > 4) ? args.slice(4) : null);
       
 16268 
       
 16269             if (fireNow) {
       
 16270                 cewrapper.fire();
       
 16271             }
       
 16272 
       
 16273             return ret;
       
 16274 
       
 16275         },
       
 16276 
       
 16277         /**
       
 16278          * Removes an event listener.  Supports the signature the event was bound
       
 16279          * with, but the preferred way to remove listeners is using the handle
       
 16280          * that is returned when using Y.on
       
 16281          *
       
 16282          * @method detach
       
 16283          *
       
 16284          * @param {String} type the type of event to remove.
       
 16285          * @param {Function} fn the method the event invokes.  If fn is
       
 16286          * undefined, then all event handlers for the type of event are
       
 16287          * removed.
       
 16288          * @param {String|HTMLElement|Array|NodeList|EventHandle} el An
       
 16289          * event handle, an id, an element reference, or a collection
       
 16290          * of ids and/or elements to remove the listener from.
       
 16291          * @return {boolean} true if the unbind was successful, false otherwise.
       
 16292          * @static
       
 16293          */
       
 16294         detach: function(type, fn, el, obj) {
       
 16295 
       
 16296             var args=Y.Array(arguments, 0, true), compat, l, ok, i,
       
 16297                 id, ce;
       
 16298 
       
 16299             if (args[args.length-1] === COMPAT_ARG) {
       
 16300                 compat = true;
       
 16301                 // args.pop();
       
 16302             }
       
 16303 
       
 16304             if (type && type.detach) {
       
 16305                 return type.detach();
       
 16306             }
       
 16307 
       
 16308             // The el argument can be a string
       
 16309             if (typeof el == "string") {
       
 16310 
       
 16311                 // el = (compat) ? Y.DOM.byId(el) : Y.all(el);
       
 16312                 if (compat) {
       
 16313                     el = Y.DOM.byId(el);
       
 16314                 } else {
       
 16315                     el = Y.Selector.query(el);
       
 16316                     l = el.length;
       
 16317                     if (l < 1) {
       
 16318                         el = null;
       
 16319                     } else if (l == 1) {
       
 16320                         el = el[0];
       
 16321                     }
       
 16322                 }
       
 16323                 // return Event.detach.apply(Event, args);
       
 16324             }
       
 16325 
       
 16326             if (!el) {
       
 16327                 return false;
       
 16328             }
       
 16329 
       
 16330             if (el.detach) {
       
 16331                 args.splice(2, 1);
       
 16332                 return el.detach.apply(el, args);
       
 16333             // The el argument can be an array of elements or element ids.
       
 16334             } else if (shouldIterate(el)) {
       
 16335                 ok = true;
       
 16336                 for (i=0, l=el.length; i<l; ++i) {
       
 16337                     args[2] = el[i];
       
 16338                     ok = ( Y.Event.detach.apply(Y.Event, args) && ok );
       
 16339                 }
       
 16340 
       
 16341                 return ok;
       
 16342             }
       
 16343 
       
 16344             if (!type || !fn || !fn.call) {
       
 16345                 return Event.purgeElement(el, false, type);
       
 16346             }
       
 16347 
       
 16348             id = 'event:' + Y.stamp(el) + type;
       
 16349             ce = _wrappers[id];
       
 16350 
       
 16351             if (ce) {
       
 16352                 return ce.detach(fn);
       
 16353             } else {
       
 16354                 return false;
       
 16355             }
       
 16356 
       
 16357         },
       
 16358 
       
 16359         /**
       
 16360          * Finds the event in the window object, the caller's arguments, or
       
 16361          * in the arguments of another method in the callstack.  This is
       
 16362          * executed automatically for events registered through the event
       
 16363          * manager, so the implementer should not normally need to execute
       
 16364          * this function at all.
       
 16365          * @method getEvent
       
 16366          * @param {Event} e the event parameter from the handler
       
 16367          * @param {HTMLElement} el the element the listener was attached to
       
 16368          * @return {Event} the event
       
 16369          * @static
       
 16370          */
       
 16371         getEvent: function(e, el, noFacade) {
       
 16372             var ev = e || win.event;
       
 16373 
       
 16374             return (noFacade) ? ev :
       
 16375                 new Y.DOMEventFacade(ev, el, _wrappers['event:' + Y.stamp(el) + e.type]);
       
 16376         },
       
 16377 
       
 16378         /**
       
 16379          * Generates an unique ID for the element if it does not already
       
 16380          * have one.
       
 16381          * @method generateId
       
 16382          * @param el the element to create the id for
       
 16383          * @return {string} the resulting id of the element
       
 16384          * @static
       
 16385          */
       
 16386         generateId: function(el) {
       
 16387             return Y.DOM.generateID(el);
       
 16388         },
       
 16389 
       
 16390         /**
       
 16391          * We want to be able to use getElementsByTagName as a collection
       
 16392          * to attach a group of events to.  Unfortunately, different
       
 16393          * browsers return different types of collections.  This function
       
 16394          * tests to determine if the object is array-like.  It will also
       
 16395          * fail if the object is an array, but is empty.
       
 16396          * @method _isValidCollection
       
 16397          * @param o the object to test
       
 16398          * @return {boolean} true if the object is array-like and populated
       
 16399          * @deprecated was not meant to be used directly
       
 16400          * @static
       
 16401          * @private
       
 16402          */
       
 16403         _isValidCollection: shouldIterate,
       
 16404 
       
 16405         /**
       
 16406          * hook up any deferred listeners
       
 16407          * @method _load
       
 16408          * @static
       
 16409          * @private
       
 16410          */
       
 16411         _load: function(e) {
       
 16412             if (!_loadComplete) {
       
 16413                 _loadComplete = true;
       
 16414 
       
 16415                 // Just in case DOMReady did not go off for some reason
       
 16416                 // E._ready();
       
 16417                 if (Y.fire) {
       
 16418                     Y.fire(EVENT_READY);
       
 16419                 }
       
 16420 
       
 16421                 // Available elements may not have been detected before the
       
 16422                 // window load event fires. Try to find them now so that the
       
 16423                 // the user is more likely to get the onAvailable notifications
       
 16424                 // before the window load notification
       
 16425                 Event._poll();
       
 16426             }
       
 16427         },
       
 16428 
       
 16429         /**
       
 16430          * Polling function that runs before the onload event fires,
       
 16431          * attempting to attach to DOM Nodes as soon as they are
       
 16432          * available
       
 16433          * @method _poll
       
 16434          * @static
       
 16435          * @private
       
 16436          */
       
 16437         _poll: function() {
       
 16438             if (Event.locked) {
       
 16439                 return;
       
 16440             }
       
 16441 
       
 16442             if (Y.UA.ie && !YUI.Env.DOMReady) {
       
 16443                 // Hold off if DOMReady has not fired and check current
       
 16444                 // readyState to protect against the IE operation aborted
       
 16445                 // issue.
       
 16446                 Event.startInterval();
       
 16447                 return;
       
 16448             }
       
 16449 
       
 16450             Event.locked = true;
       
 16451 
       
 16452             // keep trying until after the page is loaded.  We need to
       
 16453             // check the page load state prior to trying to bind the
       
 16454             // elements so that we can be certain all elements have been
       
 16455             // tested appropriately
       
 16456             var i, len, item, el, notAvail, executeItem,
       
 16457                 tryAgain = !_loadComplete;
       
 16458 
       
 16459             if (!tryAgain) {
       
 16460                 tryAgain = (_retryCount > 0);
       
 16461             }
       
 16462 
       
 16463             // onAvailable
       
 16464             notAvail = [];
       
 16465 
       
 16466             executeItem = function (el, item) {
       
 16467                 var context, ov = item.override;
       
 16468                 try {
       
 16469                     if (item.compat) {
       
 16470                         if (item.override) {
       
 16471                             if (ov === true) {
       
 16472                                 context = item.obj;
       
 16473                             } else {
       
 16474                                 context = ov;
       
 16475                             }
       
 16476                         } else {
       
 16477                             context = el;
       
 16478                         }
       
 16479                         item.fn.call(context, item.obj);
       
 16480                     } else {
       
 16481                         context = item.obj || Y.one(el);
       
 16482                         item.fn.apply(context, (Y.Lang.isArray(ov)) ? ov : []);
       
 16483                     }
       
 16484                 } catch (e) {
       
 16485                 }
       
 16486             };
       
 16487 
       
 16488             // onAvailable
       
 16489             for (i=0,len=_avail.length; i<len; ++i) {
       
 16490                 item = _avail[i];
       
 16491                 if (item && !item.checkReady) {
       
 16492 
       
 16493                     // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
       
 16494                     el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
       
 16495 
       
 16496                     if (el) {
       
 16497                         executeItem(el, item);
       
 16498                         _avail[i] = null;
       
 16499                     } else {
       
 16500                         notAvail.push(item);
       
 16501                     }
       
 16502                 }
       
 16503             }
       
 16504 
       
 16505             // onContentReady
       
 16506             for (i=0,len=_avail.length; i<len; ++i) {
       
 16507                 item = _avail[i];
       
 16508                 if (item && item.checkReady) {
       
 16509 
       
 16510                     // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
       
 16511                     el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
       
 16512 
       
 16513                     if (el) {
       
 16514                         // The element is available, but not necessarily ready
       
 16515                         // @todo should we test parentNode.nextSibling?
       
 16516                         if (_loadComplete || (el.get && el.get('nextSibling')) || el.nextSibling) {
       
 16517                             executeItem(el, item);
       
 16518                             _avail[i] = null;
       
 16519                         }
       
 16520                     } else {
       
 16521                         notAvail.push(item);
       
 16522                     }
       
 16523                 }
       
 16524             }
       
 16525 
       
 16526             _retryCount = (notAvail.length === 0) ? 0 : _retryCount - 1;
       
 16527 
       
 16528             if (tryAgain) {
       
 16529                 // we may need to strip the nulled out items here
       
 16530                 Event.startInterval();
       
 16531             } else {
       
 16532                 clearInterval(Event._interval);
       
 16533                 Event._interval = null;
       
 16534             }
       
 16535 
       
 16536             Event.locked = false;
       
 16537 
       
 16538             return;
       
 16539 
       
 16540         },
       
 16541 
       
 16542         /**
       
 16543          * Removes all listeners attached to the given element via addListener.
       
 16544          * Optionally, the node's children can also be purged.
       
 16545          * Optionally, you can specify a specific type of event to remove.
       
 16546          * @method purgeElement
       
 16547          * @param {HTMLElement} el the element to purge
       
 16548          * @param {boolean} recurse recursively purge this element's children
       
 16549          * as well.  Use with caution.
       
 16550          * @param {string} type optional type of listener to purge. If
       
 16551          * left out, all listeners will be removed
       
 16552          * @static
       
 16553          */
       
 16554         purgeElement: function(el, recurse, type) {
       
 16555             // var oEl = (Y.Lang.isString(el)) ? Y.one(el) : el,
       
 16556             var oEl = (Y.Lang.isString(el)) ?  Y.Selector.query(el, null, true) : el,
       
 16557                 lis = Event.getListeners(oEl, type), i, len, children, child;
       
 16558 
       
 16559             if (recurse && oEl) {
       
 16560                 lis = lis || [];
       
 16561                 children = Y.Selector.query('*', oEl);
       
 16562                 len = children.length;
       
 16563                 for (i = 0; i < len; ++i) {
       
 16564                     child = Event.getListeners(children[i], type);
       
 16565                     if (child) {
       
 16566                         lis = lis.concat(child);
       
 16567                     }
       
 16568                 }
       
 16569             }
       
 16570 
       
 16571             if (lis) {
       
 16572                 for (i = 0, len = lis.length; i < len; ++i) {
       
 16573                     lis[i].detachAll();
       
 16574                 }
       
 16575             }
       
 16576 
       
 16577         },
       
 16578 
       
 16579         /**
       
 16580          * Removes all object references and the DOM proxy subscription for
       
 16581          * a given event for a DOM node.
       
 16582          *
       
 16583          * @method _clean
       
 16584          * @param wrapper {CustomEvent} Custom event proxy for the DOM
       
 16585          *                  subscription
       
 16586          * @private
       
 16587          * @static
       
 16588          * @since 3.4.0
       
 16589          */
       
 16590         _clean: function (wrapper) {
       
 16591             var key    = wrapper.key,
       
 16592                 domkey = wrapper.domkey;
       
 16593 
       
 16594             remove(wrapper.el, wrapper.type, wrapper.fn, wrapper.capture);
       
 16595             delete _wrappers[key];
       
 16596             delete Y._yuievt.events[key];
       
 16597             if (_el_events[domkey]) {
       
 16598                 delete _el_events[domkey][key];
       
 16599                 if (!Y.Object.size(_el_events[domkey])) {
       
 16600                     delete _el_events[domkey];
       
 16601                 }
       
 16602             }
       
 16603         },
       
 16604 
       
 16605         /**
       
 16606          * Returns all listeners attached to the given element via addListener.
       
 16607          * Optionally, you can specify a specific type of event to return.
       
 16608          * @method getListeners
       
 16609          * @param el {HTMLElement|string} the element or element id to inspect
       
 16610          * @param type {string} optional type of listener to return. If
       
 16611          * left out, all listeners will be returned
       
 16612          * @return {CustomEvent} the custom event wrapper for the DOM event(s)
       
 16613          * @static
       
 16614          */
       
 16615         getListeners: function(el, type) {
       
 16616             var ek = Y.stamp(el, true), evts = _el_events[ek],
       
 16617                 results=[] , key = (type) ? 'event:' + ek + type : null,
       
 16618                 adapters = _eventenv.plugins;
       
 16619 
       
 16620             if (!evts) {
       
 16621                 return null;
       
 16622             }
       
 16623 
       
 16624             if (key) {
       
 16625                 // look for synthetic events
       
 16626                 if (adapters[type] && adapters[type].eventDef) {
       
 16627                     key += '_synth';
       
 16628                 }
       
 16629 
       
 16630                 if (evts[key]) {
       
 16631                     results.push(evts[key]);
       
 16632                 }
       
 16633 
       
 16634                 // get native events as well
       
 16635                 key += 'native';
       
 16636                 if (evts[key]) {
       
 16637                     results.push(evts[key]);
       
 16638                 }
       
 16639 
       
 16640             } else {
       
 16641                 Y.each(evts, function(v, k) {
       
 16642                     results.push(v);
       
 16643                 });
       
 16644             }
       
 16645 
       
 16646             return (results.length) ? results : null;
       
 16647         },
       
 16648 
       
 16649         /**
       
 16650          * Removes all listeners registered by pe.event.  Called
       
 16651          * automatically during the unload event.
       
 16652          * @method _unload
       
 16653          * @static
       
 16654          * @private
       
 16655          */
       
 16656         _unload: function(e) {
       
 16657             Y.each(_wrappers, function(v, k) {
       
 16658                 if (v.type == 'unload') {
       
 16659                     v.fire(e);
       
 16660                 }
       
 16661                 v.detachAll();
       
 16662             });
       
 16663             remove(win, "unload", onUnload);
       
 16664         },
       
 16665 
       
 16666         /**
       
 16667          * Adds a DOM event directly without the caching, cleanup, context adj, etc
       
 16668          *
       
 16669          * @method nativeAdd
       
 16670          * @param {HTMLElement} el      the element to bind the handler to
       
 16671          * @param {string}      type   the type of event handler
       
 16672          * @param {function}    fn      the callback to invoke
       
 16673          * @param {boolen}      capture capture or bubble phase
       
 16674          * @static
       
 16675          * @private
       
 16676          */
       
 16677         nativeAdd: add,
       
 16678 
       
 16679         /**
       
 16680          * Basic remove listener
       
 16681          *
       
 16682          * @method nativeRemove
       
 16683          * @param {HTMLElement} el      the element to bind the handler to
       
 16684          * @param {string}      type   the type of event handler
       
 16685          * @param {function}    fn      the callback to invoke
       
 16686          * @param {boolen}      capture capture or bubble phase
       
 16687          * @static
       
 16688          * @private
       
 16689          */
       
 16690         nativeRemove: remove
       
 16691     };
       
 16692 
       
 16693 }();
       
 16694 
       
 16695 Y.Event = Event;
       
 16696 
       
 16697 if (config.injected || YUI.Env.windowLoaded) {
       
 16698     onLoad();
       
 16699 } else {
       
 16700     add(win, "load", onLoad);
       
 16701 }
       
 16702 
       
 16703 // Process onAvailable/onContentReady items when when the DOM is ready in IE
       
 16704 if (Y.UA.ie) {
       
 16705     Y.on(EVENT_READY, Event._poll);
       
 16706 }
       
 16707 
       
 16708 try {
       
 16709     add(win, "unload", onUnload);
       
 16710 } catch(e) {
       
 16711     /*jshint maxlen:300*/
       
 16712 }
       
 16713 
       
 16714 Event.Custom = Y.CustomEvent;
       
 16715 Event.Subscriber = Y.Subscriber;
       
 16716 Event.Target = Y.EventTarget;
       
 16717 Event.Handle = Y.EventHandle;
       
 16718 Event.Facade = Y.EventFacade;
       
 16719 
       
 16720 Event._poll();
       
 16721 
       
 16722 }());
       
 16723 
       
 16724 /**
       
 16725  * DOM event listener abstraction layer
       
 16726  * @module event
       
 16727  * @submodule event-base
       
 16728  */
       
 16729 
       
 16730 /**
       
 16731  * Executes the callback as soon as the specified element
       
 16732  * is detected in the DOM.  This function expects a selector
       
 16733  * string for the element(s) to detect.  If you already have
       
 16734  * an element reference, you don't need this event.
       
 16735  * @event available
       
 16736  * @param type {string} 'available'
       
 16737  * @param fn {function} the callback function to execute.
       
 16738  * @param el {string} an selector for the element(s) to attach
       
 16739  * @param context optional argument that specifies what 'this' refers to.
       
 16740  * @param args* 0..n additional arguments to pass on to the callback function.
       
 16741  * These arguments will be added after the event object.
       
 16742  * @return {EventHandle} the detach handle
       
 16743  * @for YUI
       
 16744  */
       
 16745 Y.Env.evt.plugins.available = {
       
 16746     on: function(type, fn, id, o) {
       
 16747         var a = arguments.length > 4 ?  Y.Array(arguments, 4, true) : null;
       
 16748         return Y.Event.onAvailable.call(Y.Event, id, fn, o, a);
       
 16749     }
       
 16750 };
       
 16751 
       
 16752 /**
       
 16753  * Executes the callback as soon as the specified element
       
 16754  * is detected in the DOM with a nextSibling property
       
 16755  * (indicating that the element's children are available).
       
 16756  * This function expects a selector
       
 16757  * string for the element(s) to detect.  If you already have
       
 16758  * an element reference, you don't need this event.
       
 16759  * @event contentready
       
 16760  * @param type {string} 'contentready'
       
 16761  * @param fn {function} the callback function to execute.
       
 16762  * @param el {string} an selector for the element(s) to attach.
       
 16763  * @param context optional argument that specifies what 'this' refers to.
       
 16764  * @param args* 0..n additional arguments to pass on to the callback function.
       
 16765  * These arguments will be added after the event object.
       
 16766  * @return {EventHandle} the detach handle
       
 16767  * @for YUI
       
 16768  */
       
 16769 Y.Env.evt.plugins.contentready = {
       
 16770     on: function(type, fn, id, o) {
       
 16771         var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
       
 16772         return Y.Event.onContentReady.call(Y.Event, id, fn, o, a);
       
 16773     }
       
 16774 };
       
 16775 
       
 16776 
       
 16777 }, '@VERSION@', {"requires": ["event-custom-base"]});
       
 16778 (function() {
       
 16779 
       
 16780 var stateChangeListener,
       
 16781     GLOBAL_ENV   = YUI.Env,
       
 16782     config       = YUI.config,
       
 16783     doc          = config.doc,
       
 16784     docElement   = doc && doc.documentElement,
       
 16785     EVENT_NAME   = 'onreadystatechange',
       
 16786     pollInterval = config.pollInterval || 40;
       
 16787 
       
 16788 if (docElement.doScroll && !GLOBAL_ENV._ieready) {
       
 16789     GLOBAL_ENV._ieready = function() {
       
 16790         GLOBAL_ENV._ready();
       
 16791     };
       
 16792 
       
 16793 /*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
       
 16794 // Internet Explorer: use the doScroll() method on the root element.
       
 16795 // This isolates what appears to be a safe moment to manipulate the
       
 16796 // DOM prior to when the document's readyState suggests it is safe to do so.
       
 16797     if (self !== self.top) {
       
 16798         stateChangeListener = function() {
       
 16799             if (doc.readyState == 'complete') {
       
 16800                 GLOBAL_ENV.remove(doc, EVENT_NAME, stateChangeListener);
       
 16801                 GLOBAL_ENV.ieready();
       
 16802             }
       
 16803         };
       
 16804         GLOBAL_ENV.add(doc, EVENT_NAME, stateChangeListener);
       
 16805     } else {
       
 16806         GLOBAL_ENV._dri = setInterval(function() {
       
 16807             try {
       
 16808                 docElement.doScroll('left');
       
 16809                 clearInterval(GLOBAL_ENV._dri);
       
 16810                 GLOBAL_ENV._dri = null;
       
 16811                 GLOBAL_ENV._ieready();
       
 16812             } catch (domNotReady) { }
       
 16813         }, pollInterval);
       
 16814     }
       
 16815 }
       
 16816 
       
 16817 })();
       
 16818 YUI.add('event-base-ie', function (Y, NAME) {
       
 16819 
       
 16820 /*
       
 16821  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 16822  * events.
       
 16823  * @module event
       
 16824  * @submodule event-base
       
 16825  */
       
 16826 
       
 16827 function IEEventFacade() {
       
 16828     // IEEventFacade.superclass.constructor.apply(this, arguments);
       
 16829     Y.DOM2EventFacade.apply(this, arguments);
       
 16830 }
       
 16831 
       
 16832 /*
       
 16833  * (intentially left out of API docs)
       
 16834  * Alternate Facade implementation that is based on Object.defineProperty, which
       
 16835  * is partially supported in IE8.  Properties that involve setup work are
       
 16836  * deferred to temporary getters using the static _define method.
       
 16837  */
       
 16838 function IELazyFacade(e) {
       
 16839     var proxy = Y.config.doc.createEventObject(e),
       
 16840         proto = IELazyFacade.prototype;
       
 16841 
       
 16842     // TODO: necessary?
       
 16843     proxy.hasOwnProperty = function () { return true; };
       
 16844 
       
 16845     proxy.init = proto.init;
       
 16846     proxy.halt = proto.halt;
       
 16847     proxy.preventDefault           = proto.preventDefault;
       
 16848     proxy.stopPropagation          = proto.stopPropagation;
       
 16849     proxy.stopImmediatePropagation = proto.stopImmediatePropagation;
       
 16850 
       
 16851     Y.DOM2EventFacade.apply(proxy, arguments);
       
 16852 
       
 16853     return proxy;
       
 16854 }
       
 16855 
       
 16856 
       
 16857 var imp = Y.config.doc && Y.config.doc.implementation,
       
 16858     useLazyFacade = Y.config.lazyEventFacade,
       
 16859 
       
 16860     buttonMap = {
       
 16861         0: 1, // left click
       
 16862         4: 2, // middle click
       
 16863         2: 3  // right click
       
 16864     },
       
 16865     relatedTargetMap = {
       
 16866         mouseout: 'toElement',
       
 16867         mouseover: 'fromElement'
       
 16868     },
       
 16869 
       
 16870     resolve = Y.DOM2EventFacade.resolve,
       
 16871 
       
 16872     proto = {
       
 16873         init: function() {
       
 16874 
       
 16875             IEEventFacade.superclass.init.apply(this, arguments);
       
 16876 
       
 16877             var e = this._event,
       
 16878                 x, y, d, b, de, t;
       
 16879 
       
 16880             this.target = resolve(e.srcElement);
       
 16881 
       
 16882             if (('clientX' in e) && (!x) && (0 !== x)) {
       
 16883                 x = e.clientX;
       
 16884                 y = e.clientY;
       
 16885 
       
 16886                 d = Y.config.doc;
       
 16887                 b = d.body;
       
 16888                 de = d.documentElement;
       
 16889 
       
 16890                 x += (de.scrollLeft || (b && b.scrollLeft) || 0);
       
 16891                 y += (de.scrollTop  || (b && b.scrollTop)  || 0);
       
 16892 
       
 16893                 this.pageX = x;
       
 16894                 this.pageY = y;
       
 16895             }
       
 16896 
       
 16897             if (e.type == "mouseout") {
       
 16898                 t = e.toElement;
       
 16899             } else if (e.type == "mouseover") {
       
 16900                 t = e.fromElement;
       
 16901             }
       
 16902 
       
 16903             // fallback to t.relatedTarget to support simulated events.
       
 16904             // IE doesn't support setting toElement or fromElement on generic
       
 16905             // events, so Y.Event.simulate sets relatedTarget instead.
       
 16906             this.relatedTarget = resolve(t || e.relatedTarget);
       
 16907 
       
 16908             // which should contain the unicode key code if this is a key event.
       
 16909             // For click events, which is normalized for which mouse button was
       
 16910             // clicked.
       
 16911             this.which = // chained assignment
       
 16912             this.button = e.keyCode || buttonMap[e.button] || e.button;
       
 16913         },
       
 16914 
       
 16915         stopPropagation: function() {
       
 16916             this._event.cancelBubble = true;
       
 16917             this._wrapper.stopped = 1;
       
 16918             this.stopped = 1;
       
 16919         },
       
 16920 
       
 16921         stopImmediatePropagation: function() {
       
 16922             this.stopPropagation();
       
 16923             this._wrapper.stopped = 2;
       
 16924             this.stopped = 2;
       
 16925         },
       
 16926 
       
 16927         preventDefault: function(returnValue) {
       
 16928             this._event.returnValue = returnValue || false;
       
 16929             this._wrapper.prevented = 1;
       
 16930             this.prevented = 1;
       
 16931         }
       
 16932     };
       
 16933 
       
 16934 Y.extend(IEEventFacade, Y.DOM2EventFacade, proto);
       
 16935 
       
 16936 Y.extend(IELazyFacade, Y.DOM2EventFacade, proto);
       
 16937 IELazyFacade.prototype.init = function () {
       
 16938     var e         = this._event,
       
 16939         overrides = this._wrapper.overrides,
       
 16940         define    = IELazyFacade._define,
       
 16941         lazyProperties = IELazyFacade._lazyProperties,
       
 16942         prop;
       
 16943 
       
 16944     this.altKey   = e.altKey;
       
 16945     this.ctrlKey  = e.ctrlKey;
       
 16946     this.metaKey  = e.metaKey;
       
 16947     this.shiftKey = e.shiftKey;
       
 16948     this.type     = (overrides && overrides.type) || e.type;
       
 16949     this.clientX  = e.clientX;
       
 16950     this.clientY  = e.clientY;
       
 16951     this.keyCode  = // chained assignment
       
 16952     this.charCode = e.keyCode;
       
 16953     this.which    = // chained assignment
       
 16954     this.button   = e.keyCode || buttonMap[e.button] || e.button;
       
 16955 
       
 16956     for (prop in lazyProperties) {
       
 16957         if (lazyProperties.hasOwnProperty(prop)) {
       
 16958             define(this, prop, lazyProperties[prop]);
       
 16959         }
       
 16960     }
       
 16961 
       
 16962     if (this._touch) {
       
 16963         this._touch(e, this._currentTarget, this._wrapper);
       
 16964     }
       
 16965 };
       
 16966 
       
 16967 IELazyFacade._lazyProperties = {
       
 16968     target: function () {
       
 16969         return resolve(this._event.srcElement);
       
 16970     },
       
 16971     relatedTarget: function () {
       
 16972         var e = this._event,
       
 16973             targetProp = relatedTargetMap[e.type] || 'relatedTarget';
       
 16974 
       
 16975         // fallback to t.relatedTarget to support simulated events.
       
 16976         // IE doesn't support setting toElement or fromElement on generic
       
 16977         // events, so Y.Event.simulate sets relatedTarget instead.
       
 16978         return resolve(e[targetProp] || e.relatedTarget);
       
 16979     },
       
 16980     currentTarget: function () {
       
 16981         return resolve(this._currentTarget);
       
 16982     },
       
 16983 
       
 16984     wheelDelta: function () {
       
 16985         var e = this._event;
       
 16986 
       
 16987         if (e.type === "mousewheel" || e.type === "DOMMouseScroll") {
       
 16988             return (e.detail) ?
       
 16989                 (e.detail * -1) :
       
 16990                 // wheelDelta between -80 and 80 result in -1 or 1
       
 16991                 Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
       
 16992         }
       
 16993     },
       
 16994 
       
 16995     pageX: function () {
       
 16996         var e = this._event,
       
 16997             val = e.pageX,
       
 16998             doc, bodyScroll, docScroll;
       
 16999 
       
 17000         if (val === undefined) {
       
 17001             doc = Y.config.doc;
       
 17002             bodyScroll = doc.body && doc.body.scrollLeft;
       
 17003             docScroll = doc.documentElement.scrollLeft;
       
 17004 
       
 17005             val = e.clientX + (docScroll || bodyScroll || 0);
       
 17006         }
       
 17007 
       
 17008         return val;
       
 17009     },
       
 17010     pageY: function () {
       
 17011         var e = this._event,
       
 17012             val = e.pageY,
       
 17013             doc, bodyScroll, docScroll;
       
 17014 
       
 17015         if (val === undefined) {
       
 17016             doc = Y.config.doc;
       
 17017             bodyScroll = doc.body && doc.body.scrollTop;
       
 17018             docScroll = doc.documentElement.scrollTop;
       
 17019 
       
 17020             val = e.clientY + (docScroll || bodyScroll || 0);
       
 17021         }
       
 17022 
       
 17023         return val;
       
 17024     }
       
 17025 };
       
 17026 
       
 17027 
       
 17028 /**
       
 17029  * Wrapper function for Object.defineProperty that creates a property whose
       
 17030  * value will be calulated only when asked for.  After calculating the value,
       
 17031  * the getter wll be removed, so it will behave as a normal property beyond that
       
 17032  * point.  A setter is also assigned so assigning to the property will clear
       
 17033  * the getter, so foo.prop = 'a'; foo.prop; won't trigger the getter,
       
 17034  * overwriting value 'a'.
       
 17035  *
       
 17036  * Used only by the DOMEventFacades used by IE8 when the YUI configuration
       
 17037  * <code>lazyEventFacade</code> is set to true.
       
 17038  *
       
 17039  * @method _define
       
 17040  * @param o {DOMObject} A DOM object to add the property to
       
 17041  * @param prop {String} The name of the new property
       
 17042  * @param valueFn {Function} The function that will return the initial, default
       
 17043  *                  value for the property.
       
 17044  * @static
       
 17045  * @private
       
 17046  */
       
 17047 IELazyFacade._define = function (o, prop, valueFn) {
       
 17048     function val(v) {
       
 17049         var ret = (arguments.length) ? v : valueFn.call(this);
       
 17050 
       
 17051         delete o[prop];
       
 17052         Object.defineProperty(o, prop, {
       
 17053             value: ret,
       
 17054             configurable: true,
       
 17055             writable: true
       
 17056         });
       
 17057         return ret;
       
 17058     }
       
 17059     Object.defineProperty(o, prop, {
       
 17060         get: val,
       
 17061         set: val,
       
 17062         configurable: true
       
 17063     });
       
 17064 };
       
 17065 
       
 17066 if (imp && (!imp.hasFeature('Events', '2.0'))) {
       
 17067     if (useLazyFacade) {
       
 17068         // Make sure we can use the lazy facade logic
       
 17069         try {
       
 17070             Object.defineProperty(Y.config.doc.createEventObject(), 'z', {});
       
 17071         } catch (e) {
       
 17072             useLazyFacade = false;
       
 17073         }
       
 17074     }
       
 17075 
       
 17076     Y.DOMEventFacade = (useLazyFacade) ? IELazyFacade : IEEventFacade;
       
 17077 }
       
 17078 
       
 17079 
       
 17080 }, '@VERSION@', {"requires": ["node-base"]});
       
 17081 YUI.add('pluginhost-base', function (Y, NAME) {
       
 17082 
       
 17083     /**
       
 17084      * Provides the augmentable PluginHost interface, which can be added to any class.
       
 17085      * @module pluginhost
       
 17086      */
       
 17087 
       
 17088     /**
       
 17089      * Provides the augmentable PluginHost interface, which can be added to any class.
       
 17090      * @module pluginhost-base
       
 17091      */
       
 17092 
       
 17093     /**
       
 17094      * <p>
       
 17095      * An augmentable class, which provides the augmented class with the ability to host plugins.
       
 17096      * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can 
       
 17097      * be used to add or remove plugins from instances of the class.
       
 17098      * </p>
       
 17099      *
       
 17100      * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using
       
 17101      * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method. 
       
 17102      * 
       
 17103      * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
       
 17104      * <xmp>
       
 17105      * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
       
 17106      * </xmp>
       
 17107      * </p>
       
 17108      * <p>
       
 17109      * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a> 
       
 17110      * methods should be invoked by the host class at the appropriate point in the host's lifecyle.  
       
 17111      * </p>
       
 17112      *
       
 17113      * @class Plugin.Host
       
 17114      */
       
 17115 
       
 17116     var L = Y.Lang;
       
 17117 
       
 17118     function PluginHost() {
       
 17119         this._plugins = {};
       
 17120     }
       
 17121 
       
 17122     PluginHost.prototype = {
       
 17123 
       
 17124         /**
       
 17125          * Adds a plugin to the host object. This will instantiate the 
       
 17126          * plugin and attach it to the configured namespace on the host object.
       
 17127          *
       
 17128          * @method plug
       
 17129          * @chainable
       
 17130          * @param P {Function | Object |Array} Accepts the plugin class, or an 
       
 17131          * object with a "fn" property specifying the plugin class and 
       
 17132          * a "cfg" property specifying the configuration for the Plugin.
       
 17133          * <p>
       
 17134          * Additionally an Array can also be passed in, with the above function or 
       
 17135          * object values, allowing the user to add multiple plugins in a single call.
       
 17136          * </p>
       
 17137          * @param config (Optional) If the first argument is the plugin class, the second argument
       
 17138          * can be the configuration for the plugin.
       
 17139          * @return {Base} A reference to the host object
       
 17140          */
       
 17141         plug: function(Plugin, config) {
       
 17142             var i, ln, ns;
       
 17143 
       
 17144             if (L.isArray(Plugin)) {
       
 17145                 for (i = 0, ln = Plugin.length; i < ln; i++) {
       
 17146                     this.plug(Plugin[i]);
       
 17147                 }
       
 17148             } else {
       
 17149                 if (Plugin && !L.isFunction(Plugin)) {
       
 17150                     config = Plugin.cfg;
       
 17151                     Plugin = Plugin.fn;
       
 17152                 }
       
 17153 
       
 17154                 // Plugin should be fn by now
       
 17155                 if (Plugin && Plugin.NS) {
       
 17156                     ns = Plugin.NS;
       
 17157         
       
 17158                     config = config || {};
       
 17159                     config.host = this;
       
 17160         
       
 17161                     if (this.hasPlugin(ns)) {
       
 17162                         // Update config
       
 17163                         if (this[ns].setAttrs) {
       
 17164                             this[ns].setAttrs(config);
       
 17165                         }
       
 17166                     } else {
       
 17167                         // Create new instance
       
 17168                         this[ns] = new Plugin(config);
       
 17169                         this._plugins[ns] = Plugin;
       
 17170                     }
       
 17171                 }
       
 17172             }
       
 17173             return this;
       
 17174         },
       
 17175 
       
 17176         /**
       
 17177          * Removes a plugin from the host object. This will destroy the 
       
 17178          * plugin instance and delete the namespace from the host object. 
       
 17179          *
       
 17180          * @method unplug
       
 17181          * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
       
 17182          * all registered plugins are unplugged.
       
 17183          * @return {Base} A reference to the host object
       
 17184          * @chainable
       
 17185          */
       
 17186         unplug: function(plugin) {
       
 17187             var ns = plugin, 
       
 17188                 plugins = this._plugins;
       
 17189             
       
 17190             if (plugin) {
       
 17191                 if (L.isFunction(plugin)) {
       
 17192                     ns = plugin.NS;
       
 17193                     if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
       
 17194                         ns = null;
       
 17195                     }
       
 17196                 }
       
 17197         
       
 17198                 if (ns) {
       
 17199                     if (this[ns]) {
       
 17200                         if (this[ns].destroy) {
       
 17201                             this[ns].destroy();
       
 17202                         }
       
 17203                         delete this[ns];
       
 17204                     }
       
 17205                     if (plugins[ns]) {
       
 17206                         delete plugins[ns];
       
 17207                     }
       
 17208                 }
       
 17209             } else {
       
 17210                 for (ns in this._plugins) {
       
 17211                     if (this._plugins.hasOwnProperty(ns)) {
       
 17212                         this.unplug(ns);
       
 17213                     }
       
 17214                 }
       
 17215             }
       
 17216             return this;
       
 17217         },
       
 17218 
       
 17219         /**
       
 17220          * Determines if a plugin has plugged into this host.
       
 17221          *
       
 17222          * @method hasPlugin
       
 17223          * @param {String} ns The plugin's namespace
       
 17224          * @return {Plugin} Returns a truthy value (the plugin instance) if present, or undefined if not.
       
 17225          */
       
 17226         hasPlugin : function(ns) {
       
 17227             return (this._plugins[ns] && this[ns]);
       
 17228         },
       
 17229 
       
 17230         /**
       
 17231          * Initializes static plugins registered on the host (using the
       
 17232          * Base.plug static method) and any plugins passed to the 
       
 17233          * instance through the "plugins" configuration property.
       
 17234          *
       
 17235          * @method _initPlugins
       
 17236          * @param {Config} config The configuration object with property name/value pairs.
       
 17237          * @private
       
 17238          */
       
 17239         
       
 17240         _initPlugins: function(config) {
       
 17241             this._plugins = this._plugins || {};
       
 17242 
       
 17243             if (this._initConfigPlugins) {
       
 17244                 this._initConfigPlugins(config);
       
 17245             }
       
 17246         },
       
 17247 
       
 17248         /**
       
 17249          * Unplugs and destroys all plugins on the host
       
 17250          * @method _destroyPlugins
       
 17251          * @private
       
 17252          */
       
 17253         _destroyPlugins: function() {
       
 17254             this.unplug();
       
 17255         }
       
 17256     };
       
 17257 
       
 17258     Y.namespace("Plugin").Host = PluginHost;
       
 17259 
       
 17260 
       
 17261 }, '@VERSION@', {"requires": ["yui-base"]});
       
 17262 YUI.add('pluginhost-config', function (Y, NAME) {
       
 17263 
       
 17264     /**
       
 17265      * Adds pluginhost constructor configuration and static configuration support
       
 17266      * @submodule pluginhost-config
       
 17267      */
       
 17268 
       
 17269     var PluginHost = Y.Plugin.Host,
       
 17270         L = Y.Lang;
       
 17271 
       
 17272     /**
       
 17273      * A protected initialization method, used by the host class to initialize
       
 17274      * plugin configurations passed the constructor, through the config object.
       
 17275      * 
       
 17276      * Host objects should invoke this method at the appropriate time in their
       
 17277      * construction lifecycle.
       
 17278      * 
       
 17279      * @method _initConfigPlugins
       
 17280      * @param {Object} config The configuration object passed to the constructor
       
 17281      * @protected
       
 17282      * @for Plugin.Host
       
 17283      */
       
 17284     PluginHost.prototype._initConfigPlugins = function(config) {
       
 17285 
       
 17286         // Class Configuration
       
 17287         var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
       
 17288             plug = [],
       
 17289             unplug = {},
       
 17290             constructor, i, classPlug, classUnplug, pluginClassName;
       
 17291 
       
 17292         // TODO: Room for optimization. Can we apply statically/unplug in same pass?
       
 17293         for (i = classes.length - 1; i >= 0; i--) {
       
 17294             constructor = classes[i];
       
 17295 
       
 17296             classUnplug = constructor._UNPLUG;
       
 17297             if (classUnplug) {
       
 17298                 // subclasses over-write
       
 17299                 Y.mix(unplug, classUnplug, true);
       
 17300             }
       
 17301 
       
 17302             classPlug = constructor._PLUG;
       
 17303             if (classPlug) {
       
 17304                 // subclasses over-write
       
 17305                 Y.mix(plug, classPlug, true);
       
 17306             }
       
 17307         }
       
 17308 
       
 17309         for (pluginClassName in plug) {
       
 17310             if (plug.hasOwnProperty(pluginClassName)) {
       
 17311                 if (!unplug[pluginClassName]) {
       
 17312                     this.plug(plug[pluginClassName]);
       
 17313                 }
       
 17314             }
       
 17315         }
       
 17316 
       
 17317         // User Configuration
       
 17318         if (config && config.plugins) {
       
 17319             this.plug(config.plugins);
       
 17320         }
       
 17321     };
       
 17322     
       
 17323     /**
       
 17324      * Registers plugins to be instantiated at the class level (plugins 
       
 17325      * which should be plugged into every instance of the class by default).
       
 17326      *
       
 17327      * @method plug
       
 17328      * @static
       
 17329      *
       
 17330      * @param {Function} hostClass The host class on which to register the plugins
       
 17331      * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
       
 17332      * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
       
 17333      * @for Plugin.Host
       
 17334      */
       
 17335     PluginHost.plug = function(hostClass, plugin, config) {
       
 17336         // Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
       
 17337         var p, i, l, name;
       
 17338     
       
 17339         if (hostClass !== Y.Base) {
       
 17340             hostClass._PLUG = hostClass._PLUG || {};
       
 17341     
       
 17342             if (!L.isArray(plugin)) {
       
 17343                 if (config) {
       
 17344                     plugin = {fn:plugin, cfg:config};
       
 17345                 }
       
 17346                 plugin = [plugin];
       
 17347             }
       
 17348     
       
 17349             for (i = 0, l = plugin.length; i < l;i++) {
       
 17350                 p = plugin[i];
       
 17351                 name = p.NAME || p.fn.NAME;
       
 17352                 hostClass._PLUG[name] = p;
       
 17353             }
       
 17354         }
       
 17355     };
       
 17356 
       
 17357     /**
       
 17358      * Unregisters any class level plugins which have been registered by the host class, or any
       
 17359      * other class in the hierarchy.
       
 17360      *
       
 17361      * @method unplug
       
 17362      * @static
       
 17363      *
       
 17364      * @param {Function} hostClass The host class from which to unregister the plugins
       
 17365      * @param {Function | Array} plugin The plugin class, or an array of plugin classes
       
 17366      * @for Plugin.Host
       
 17367      */
       
 17368     PluginHost.unplug = function(hostClass, plugin) {
       
 17369         var p, i, l, name;
       
 17370     
       
 17371         if (hostClass !== Y.Base) {
       
 17372             hostClass._UNPLUG = hostClass._UNPLUG || {};
       
 17373     
       
 17374             if (!L.isArray(plugin)) {
       
 17375                 plugin = [plugin];
       
 17376             }
       
 17377     
       
 17378             for (i = 0, l = plugin.length; i < l; i++) {
       
 17379                 p = plugin[i];
       
 17380                 name = p.NAME;
       
 17381                 if (!hostClass._PLUG[name]) {
       
 17382                     hostClass._UNPLUG[name] = p;
       
 17383                 } else {
       
 17384                     delete hostClass._PLUG[name];
       
 17385                 }
       
 17386             }
       
 17387         }
       
 17388     };
       
 17389 
       
 17390 
       
 17391 }, '@VERSION@', {"requires": ["pluginhost-base"]});
       
 17392 YUI.add('event-delegate', function (Y, NAME) {
       
 17393 
       
 17394 /**
       
 17395  * Adds event delegation support to the library.
       
 17396  *
       
 17397  * @module event
       
 17398  * @submodule event-delegate
       
 17399  */
       
 17400 
       
 17401 var toArray          = Y.Array,
       
 17402     YLang            = Y.Lang,
       
 17403     isString         = YLang.isString,
       
 17404     isObject         = YLang.isObject,
       
 17405     isArray          = YLang.isArray,
       
 17406     selectorTest     = Y.Selector.test,
       
 17407     detachCategories = Y.Env.evt.handles;
       
 17408 
       
 17409 /**
       
 17410  * <p>Sets up event delegation on a container element.  The delegated event
       
 17411  * will use a supplied selector or filtering function to test if the event
       
 17412  * references at least one node that should trigger the subscription
       
 17413  * callback.</p>
       
 17414  *
       
 17415  * <p>Selector string filters will trigger the callback if the event originated
       
 17416  * from a node that matches it or is contained in a node that matches it.
       
 17417  * Function filters are called for each Node up the parent axis to the
       
 17418  * subscribing container node, and receive at each level the Node and the event
       
 17419  * object.  The function should return true (or a truthy value) if that Node
       
 17420  * should trigger the subscription callback.  Note, it is possible for filters
       
 17421  * to match multiple Nodes for a single event.  In this case, the delegate
       
 17422  * callback will be executed for each matching Node.</p>
       
 17423  *
       
 17424  * <p>For each matching Node, the callback will be executed with its 'this'
       
 17425  * object set to the Node matched by the filter (unless a specific context was
       
 17426  * provided during subscription), and the provided event's
       
 17427  * <code>currentTarget</code> will also be set to the matching Node.  The
       
 17428  * containing Node from which the subscription was originally made can be
       
 17429  * referenced as <code>e.container</code>.
       
 17430  *
       
 17431  * @method delegate
       
 17432  * @param type {String} the event type to delegate
       
 17433  * @param fn {Function} the callback function to execute.  This function
       
 17434  *              will be provided the event object for the delegated event.
       
 17435  * @param el {String|node} the element that is the delegation container
       
 17436  * @param filter {string|Function} a selector that must match the target of the
       
 17437  *              event or a function to test target and its parents for a match
       
 17438  * @param context optional argument that specifies what 'this' refers to.
       
 17439  * @param args* 0..n additional arguments to pass on to the callback function.
       
 17440  *              These arguments will be added after the event object.
       
 17441  * @return {EventHandle} the detach handle
       
 17442  * @static
       
 17443  * @for Event
       
 17444  */
       
 17445 function delegate(type, fn, el, filter) {
       
 17446     var args     = toArray(arguments, 0, true),
       
 17447         query    = isString(el) ? el : null,
       
 17448         typeBits, synth, container, categories, cat, i, len, handles, handle;
       
 17449 
       
 17450     // Support Y.delegate({ click: fnA, key: fnB }, el, filter, ...);
       
 17451     // and Y.delegate(['click', 'key'], fn, el, filter, ...);
       
 17452     if (isObject(type)) {
       
 17453         handles = [];
       
 17454 
       
 17455         if (isArray(type)) {
       
 17456             for (i = 0, len = type.length; i < len; ++i) {
       
 17457                 args[0] = type[i];
       
 17458                 handles.push(Y.delegate.apply(Y, args));
       
 17459             }
       
 17460         } else {
       
 17461             // Y.delegate({'click', fn}, el, filter) =>
       
 17462             // Y.delegate('click', fn, el, filter)
       
 17463             args.unshift(null); // one arg becomes two; need to make space
       
 17464 
       
 17465             for (i in type) {
       
 17466                 if (type.hasOwnProperty(i)) {
       
 17467                     args[0] = i;
       
 17468                     args[1] = type[i];
       
 17469                     handles.push(Y.delegate.apply(Y, args));
       
 17470                 }
       
 17471             }
       
 17472         }
       
 17473 
       
 17474         return new Y.EventHandle(handles);
       
 17475     }
       
 17476 
       
 17477     typeBits = type.split(/\|/);
       
 17478 
       
 17479     if (typeBits.length > 1) {
       
 17480         cat  = typeBits.shift();
       
 17481         args[0] = type = typeBits.shift();
       
 17482     }
       
 17483 
       
 17484     synth = Y.Node.DOM_EVENTS[type];
       
 17485 
       
 17486     if (isObject(synth) && synth.delegate) {
       
 17487         handle = synth.delegate.apply(synth, arguments);
       
 17488     }
       
 17489 
       
 17490     if (!handle) {
       
 17491         if (!type || !fn || !el || !filter) {
       
 17492             return;
       
 17493         }
       
 17494 
       
 17495         container = (query) ? Y.Selector.query(query, null, true) : el;
       
 17496 
       
 17497         if (!container && isString(el)) {
       
 17498             handle = Y.on('available', function () {
       
 17499                 Y.mix(handle, Y.delegate.apply(Y, args), true);
       
 17500             }, el);
       
 17501         }
       
 17502 
       
 17503         if (!handle && container) {
       
 17504             args.splice(2, 2, container); // remove the filter
       
 17505 
       
 17506             handle = Y.Event._attach(args, { facade: false });
       
 17507             handle.sub.filter  = filter;
       
 17508             handle.sub._notify = delegate.notifySub;
       
 17509         }
       
 17510     }
       
 17511 
       
 17512     if (handle && cat) {
       
 17513         categories = detachCategories[cat]  || (detachCategories[cat] = {});
       
 17514         categories = categories[type] || (categories[type] = []);
       
 17515         categories.push(handle);
       
 17516     }
       
 17517 
       
 17518     return handle;
       
 17519 }
       
 17520 
       
 17521 /**
       
 17522 Overrides the <code>_notify</code> method on the normal DOM subscription to
       
 17523 inject the filtering logic and only proceed in the case of a match.
       
 17524 
       
 17525 This method is hosted as a private property of the `delegate` method
       
 17526 (e.g. `Y.delegate.notifySub`)
       
 17527 
       
 17528 @method notifySub
       
 17529 @param thisObj {Object} default 'this' object for the callback
       
 17530 @param args {Array} arguments passed to the event's <code>fire()</code>
       
 17531 @param ce {CustomEvent} the custom event managing the DOM subscriptions for
       
 17532              the subscribed event on the subscribing node.
       
 17533 @return {Boolean} false if the event was stopped
       
 17534 @private
       
 17535 @static
       
 17536 @since 3.2.0
       
 17537 **/
       
 17538 delegate.notifySub = function (thisObj, args, ce) {
       
 17539     // Preserve args for other subscribers
       
 17540     args = args.slice();
       
 17541     if (this.args) {
       
 17542         args.push.apply(args, this.args);
       
 17543     }
       
 17544 
       
 17545     // Only notify subs if the event occurred on a targeted element
       
 17546     var currentTarget = delegate._applyFilter(this.filter, args, ce),
       
 17547         //container     = e.currentTarget,
       
 17548         e, i, len, ret;
       
 17549 
       
 17550     if (currentTarget) {
       
 17551         // Support multiple matches up the the container subtree
       
 17552         currentTarget = toArray(currentTarget);
       
 17553 
       
 17554         // The second arg is the currentTarget, but we'll be reusing this
       
 17555         // facade, replacing the currentTarget for each use, so it doesn't
       
 17556         // matter what element we seed it with.
       
 17557         e = args[0] = new Y.DOMEventFacade(args[0], ce.el, ce);
       
 17558 
       
 17559         e.container = Y.one(ce.el);
       
 17560 
       
 17561         for (i = 0, len = currentTarget.length; i < len && !e.stopped; ++i) {
       
 17562             e.currentTarget = Y.one(currentTarget[i]);
       
 17563 
       
 17564             ret = this.fn.apply(this.context || e.currentTarget, args);
       
 17565 
       
 17566             if (ret === false) { // stop further notifications
       
 17567                 break;
       
 17568             }
       
 17569         }
       
 17570 
       
 17571         return ret;
       
 17572     }
       
 17573 };
       
 17574 
       
 17575 /**
       
 17576 Compiles a selector string into a filter function to identify whether
       
 17577 Nodes along the parent axis of an event's target should trigger event
       
 17578 notification.
       
 17579 
       
 17580 This function is memoized, so previously compiled filter functions are
       
 17581 returned if the same selector string is provided.
       
 17582 
       
 17583 This function may be useful when defining synthetic events for delegate
       
 17584 handling.
       
 17585 
       
 17586 Hosted as a property of the `delegate` method (e.g. `Y.delegate.compileFilter`).
       
 17587 
       
 17588 @method compileFilter
       
 17589 @param selector {String} the selector string to base the filtration on
       
 17590 @return {Function}
       
 17591 @since 3.2.0
       
 17592 @static
       
 17593 **/
       
 17594 delegate.compileFilter = Y.cached(function (selector) {
       
 17595     return function (target, e) {
       
 17596         return selectorTest(target._node, selector,
       
 17597             (e.currentTarget === e.target) ? null : e.currentTarget._node);
       
 17598     };
       
 17599 });
       
 17600 
       
 17601 /**
       
 17602 Regex to test for disabled elements during filtering. This is only relevant to
       
 17603 IE to normalize behavior with other browsers, which swallow events that occur
       
 17604 to disabled elements. IE fires the event from the parent element instead of the
       
 17605 original target, though it does preserve `event.srcElement` as the disabled
       
 17606 element. IE also supports disabled on `<a>`, but the event still bubbles, so it
       
 17607 acts more like `e.preventDefault()` plus styling. That issue is not handled here
       
 17608 because other browsers fire the event on the `<a>`, so delegate is supported in
       
 17609 both cases.
       
 17610 
       
 17611 @property _disabledRE
       
 17612 @type {RegExp}
       
 17613 @protected
       
 17614 @since 3.8.1
       
 17615 **/
       
 17616 delegate._disabledRE = /^(?:button|input|select|textarea)$/i;
       
 17617 
       
 17618 /**
       
 17619 Walks up the parent axis of an event's target, and tests each element
       
 17620 against a supplied filter function.  If any Nodes, including the container,
       
 17621 satisfy the filter, the delegated callback will be triggered for each.
       
 17622 
       
 17623 Hosted as a protected property of the `delegate` method (e.g.
       
 17624 `Y.delegate._applyFilter`).
       
 17625 
       
 17626 @method _applyFilter
       
 17627 @param filter {Function} boolean function to test for inclusion in event
       
 17628                  notification
       
 17629 @param args {Array} the arguments that would be passed to subscribers
       
 17630 @param ce   {CustomEvent} the DOM event wrapper
       
 17631 @return {Node|Node[]|undefined} The Node or Nodes that satisfy the filter
       
 17632 @protected
       
 17633 **/
       
 17634 delegate._applyFilter = function (filter, args, ce) {
       
 17635     var e         = args[0],
       
 17636         container = ce.el, // facadeless events in IE, have no e.currentTarget
       
 17637         target    = e.target || e.srcElement,
       
 17638         match     = [],
       
 17639         isContainer = false;
       
 17640 
       
 17641     // Resolve text nodes to their containing element
       
 17642     if (target.nodeType === 3) {
       
 17643         target = target.parentNode;
       
 17644     }
       
 17645 
       
 17646     // For IE. IE propagates events from the parent element of disabled
       
 17647     // elements, where other browsers swallow the event entirely. To normalize
       
 17648     // this in IE, filtering for matching elements should abort if the target
       
 17649     // is a disabled form control.
       
 17650     if (target.disabled && delegate._disabledRE.test(target.nodeName)) {
       
 17651         return match;
       
 17652     }
       
 17653 
       
 17654     // passing target as the first arg rather than leaving well enough alone
       
 17655     // making 'this' in the filter function refer to the target.  This is to
       
 17656     // support bound filter functions.
       
 17657     args.unshift(target);
       
 17658 
       
 17659     if (isString(filter)) {
       
 17660         while (target) {
       
 17661             isContainer = (target === container);
       
 17662             if (selectorTest(target, filter, (isContainer ? null: container))) {
       
 17663                 match.push(target);
       
 17664             }
       
 17665 
       
 17666             if (isContainer) {
       
 17667                 break;
       
 17668             }
       
 17669 
       
 17670             target = target.parentNode;
       
 17671         }
       
 17672     } else {
       
 17673         // filter functions are implementer code and should receive wrappers
       
 17674         args[0] = Y.one(target);
       
 17675         args[1] = new Y.DOMEventFacade(e, container, ce);
       
 17676 
       
 17677         while (target) {
       
 17678             // filter(target, e, extra args...) - this === target
       
 17679             if (filter.apply(args[0], args)) {
       
 17680                 match.push(target);
       
 17681             }
       
 17682 
       
 17683             if (target === container) {
       
 17684                 break;
       
 17685             }
       
 17686 
       
 17687             target = target.parentNode;
       
 17688             args[0] = Y.one(target);
       
 17689         }
       
 17690         args[1] = e; // restore the raw DOM event
       
 17691     }
       
 17692 
       
 17693     if (match.length <= 1) {
       
 17694         match = match[0]; // single match or undefined
       
 17695     }
       
 17696 
       
 17697     // remove the target
       
 17698     args.shift();
       
 17699 
       
 17700     return match;
       
 17701 };
       
 17702 
       
 17703 /**
       
 17704  * Sets up event delegation on a container element.  The delegated event
       
 17705  * will use a supplied filter to test if the callback should be executed.
       
 17706  * This filter can be either a selector string or a function that returns
       
 17707  * a Node to use as the currentTarget for the event.
       
 17708  *
       
 17709  * The event object for the delegated event is supplied to the callback
       
 17710  * function.  It is modified slightly in order to support all properties
       
 17711  * that may be needed for event delegation.  'currentTarget' is set to
       
 17712  * the element that matched the selector string filter or the Node returned
       
 17713  * from the filter function.  'container' is set to the element that the
       
 17714  * listener is delegated from (this normally would be the 'currentTarget').
       
 17715  *
       
 17716  * Filter functions will be called with the arguments that would be passed to
       
 17717  * the callback function, including the event object as the first parameter.
       
 17718  * The function should return false (or a falsey value) if the success criteria
       
 17719  * aren't met, and the Node to use as the event's currentTarget and 'this'
       
 17720  * object if they are.
       
 17721  *
       
 17722  * @method delegate
       
 17723  * @param type {string} the event type to delegate
       
 17724  * @param fn {function} the callback function to execute.  This function
       
 17725  * will be provided the event object for the delegated event.
       
 17726  * @param el {string|node} the element that is the delegation container
       
 17727  * @param filter {string|function} a selector that must match the target of the
       
 17728  * event or a function that returns a Node or false.
       
 17729  * @param context optional argument that specifies what 'this' refers to.
       
 17730  * @param args* 0..n additional arguments to pass on to the callback function.
       
 17731  * These arguments will be added after the event object.
       
 17732  * @return {EventHandle} the detach handle
       
 17733  * @for YUI
       
 17734  */
       
 17735 Y.delegate = Y.Event.delegate = delegate;
       
 17736 
       
 17737 
       
 17738 }, '@VERSION@', {"requires": ["node-base"]});
       
 17739 YUI.add('node-event-delegate', function (Y, NAME) {
       
 17740 
       
 17741 /**
       
 17742  * Functionality to make the node a delegated event container
       
 17743  * @module node
       
 17744  * @submodule node-event-delegate
       
 17745  */
       
 17746 
       
 17747 /**
       
 17748  * <p>Sets up a delegation listener for an event occurring inside the Node.
       
 17749  * The delegated event will be verified against a supplied selector or
       
 17750  * filtering function to test if the event references at least one node that
       
 17751  * should trigger the subscription callback.</p>
       
 17752  *
       
 17753  * <p>Selector string filters will trigger the callback if the event originated
       
 17754  * from a node that matches it or is contained in a node that matches it.
       
 17755  * Function filters are called for each Node up the parent axis to the
       
 17756  * subscribing container node, and receive at each level the Node and the event
       
 17757  * object.  The function should return true (or a truthy value) if that Node
       
 17758  * should trigger the subscription callback.  Note, it is possible for filters
       
 17759  * to match multiple Nodes for a single event.  In this case, the delegate
       
 17760  * callback will be executed for each matching Node.</p>
       
 17761  *
       
 17762  * <p>For each matching Node, the callback will be executed with its 'this'
       
 17763  * object set to the Node matched by the filter (unless a specific context was
       
 17764  * provided during subscription), and the provided event's
       
 17765  * <code>currentTarget</code> will also be set to the matching Node.  The
       
 17766  * containing Node from which the subscription was originally made can be
       
 17767  * referenced as <code>e.container</code>.
       
 17768  *
       
 17769  * @method delegate
       
 17770  * @param type {String} the event type to delegate
       
 17771  * @param fn {Function} the callback function to execute.  This function
       
 17772  *              will be provided the event object for the delegated event.
       
 17773  * @param spec {String|Function} a selector that must match the target of the
       
 17774  *              event or a function to test target and its parents for a match
       
 17775  * @param context {Object} optional argument that specifies what 'this' refers to.
       
 17776  * @param args* {any} 0..n additional arguments to pass on to the callback function.
       
 17777  *              These arguments will be added after the event object.
       
 17778  * @return {EventHandle} the detach handle
       
 17779  * @for Node
       
 17780  */
       
 17781 Y.Node.prototype.delegate = function(type) {
       
 17782 
       
 17783     var args = Y.Array(arguments, 0, true),
       
 17784         index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2;
       
 17785 
       
 17786     args.splice(index, 0, this._node);
       
 17787 
       
 17788     return Y.delegate.apply(Y, args);
       
 17789 };
       
 17790 
       
 17791 
       
 17792 }, '@VERSION@', {"requires": ["node-base", "event-delegate"]});
       
 17793 YUI.add('node-pluginhost', function (Y, NAME) {
       
 17794 
       
 17795 /**
       
 17796  * @module node
       
 17797  * @submodule node-pluginhost
       
 17798  */
       
 17799 
       
 17800 /**
       
 17801  * Registers plugins to be instantiated at the class level (plugins
       
 17802  * which should be plugged into every instance of Node by default).
       
 17803  *
       
 17804  * @method plug
       
 17805  * @static
       
 17806  * @for Node
       
 17807  * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
       
 17808  * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
       
 17809  */
       
 17810 Y.Node.plug = function() {
       
 17811     var args = Y.Array(arguments);
       
 17812     args.unshift(Y.Node);
       
 17813     Y.Plugin.Host.plug.apply(Y.Base, args);
       
 17814     return Y.Node;
       
 17815 };
       
 17816 
       
 17817 /**
       
 17818  * Unregisters any class level plugins which have been registered by the Node
       
 17819  *
       
 17820  * @method unplug
       
 17821  * @static
       
 17822  *
       
 17823  * @param {Function | Array} plugin The plugin class, or an array of plugin classes
       
 17824  */
       
 17825 Y.Node.unplug = function() {
       
 17826     var args = Y.Array(arguments);
       
 17827     args.unshift(Y.Node);
       
 17828     Y.Plugin.Host.unplug.apply(Y.Base, args);
       
 17829     return Y.Node;
       
 17830 };
       
 17831 
       
 17832 Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
       
 17833 
       
 17834 // allow batching of plug/unplug via NodeList
       
 17835 // doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
       
 17836 /**
       
 17837  * Adds a plugin to each node in the NodeList.
       
 17838  * This will instantiate the plugin and attach it to the configured namespace on each node
       
 17839  * @method plug
       
 17840  * @for NodeList
       
 17841  * @param P {Function | Object |Array} Accepts the plugin class, or an 
       
 17842  * object with a "fn" property specifying the plugin class and 
       
 17843  * a "cfg" property specifying the configuration for the Plugin.
       
 17844  * <p>
       
 17845  * Additionally an Array can also be passed in, with the above function or 
       
 17846  * object values, allowing the user to add multiple plugins in a single call.
       
 17847  * </p>
       
 17848  * @param config (Optional) If the first argument is the plugin class, the second argument
       
 17849  * can be the configuration for the plugin.
       
 17850  * @chainable
       
 17851  */
       
 17852 Y.NodeList.prototype.plug = function() {
       
 17853     var args = arguments;
       
 17854     Y.NodeList.each(this, function(node) {
       
 17855         Y.Node.prototype.plug.apply(Y.one(node), args);
       
 17856     });
       
 17857     return this;
       
 17858 };
       
 17859 
       
 17860 /**
       
 17861  * Removes a plugin from all nodes in the NodeList. This will destroy the 
       
 17862  * plugin instance and delete the namespace each node. 
       
 17863  * @method unplug
       
 17864  * @for NodeList
       
 17865  * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
       
 17866  * all registered plugins are unplugged.
       
 17867  * @chainable
       
 17868  */
       
 17869 Y.NodeList.prototype.unplug = function() {
       
 17870     var args = arguments;
       
 17871     Y.NodeList.each(this, function(node) {
       
 17872         Y.Node.prototype.unplug.apply(Y.one(node), args);
       
 17873     });
       
 17874     return this;
       
 17875 };
       
 17876 
       
 17877 
       
 17878 }, '@VERSION@', {"requires": ["node-base", "pluginhost"]});
       
 17879 YUI.add('node-screen', function (Y, NAME) {
       
 17880 
       
 17881 /**
       
 17882  * Extended Node interface for managing regions and screen positioning.
       
 17883  * Adds support for positioning elements and normalizes window size and scroll detection. 
       
 17884  * @module node
       
 17885  * @submodule node-screen
       
 17886  */
       
 17887 
       
 17888 // these are all "safe" returns, no wrapping required
       
 17889 Y.each([
       
 17890     /**
       
 17891      * Returns the inner width of the viewport (exludes scrollbar). 
       
 17892      * @config winWidth
       
 17893      * @for Node
       
 17894      * @type {Int}
       
 17895      */
       
 17896     'winWidth',
       
 17897 
       
 17898     /**
       
 17899      * Returns the inner height of the viewport (exludes scrollbar). 
       
 17900      * @config winHeight
       
 17901      * @type {Int}
       
 17902      */
       
 17903     'winHeight',
       
 17904 
       
 17905     /**
       
 17906      * Document width 
       
 17907      * @config docWidth
       
 17908      * @type {Int}
       
 17909      */
       
 17910     'docWidth',
       
 17911 
       
 17912     /**
       
 17913      * Document height 
       
 17914      * @config docHeight
       
 17915      * @type {Int}
       
 17916      */
       
 17917     'docHeight',
       
 17918 
       
 17919     /**
       
 17920      * Pixel distance the page has been scrolled horizontally 
       
 17921      * @config docScrollX
       
 17922      * @type {Int}
       
 17923      */
       
 17924     'docScrollX',
       
 17925 
       
 17926     /**
       
 17927      * Pixel distance the page has been scrolled vertically 
       
 17928      * @config docScrollY
       
 17929      * @type {Int}
       
 17930      */
       
 17931     'docScrollY'
       
 17932     ],
       
 17933     function(name) {
       
 17934         Y.Node.ATTRS[name] = {
       
 17935             getter: function() {
       
 17936                 var args = Array.prototype.slice.call(arguments);
       
 17937                 args.unshift(Y.Node.getDOMNode(this));
       
 17938 
       
 17939                 return Y.DOM[name].apply(this, args);
       
 17940             }
       
 17941         };
       
 17942     }
       
 17943 );
       
 17944 
       
 17945 Y.Node.ATTRS.scrollLeft = {
       
 17946     getter: function() {
       
 17947         var node = Y.Node.getDOMNode(this);
       
 17948         return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
       
 17949     },
       
 17950 
       
 17951     setter: function(val) {
       
 17952         var node = Y.Node.getDOMNode(this);
       
 17953         if (node) {
       
 17954             if ('scrollLeft' in node) {
       
 17955                 node.scrollLeft = val;
       
 17956             } else if (node.document || node.nodeType === 9) {
       
 17957                 Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
       
 17958             }
       
 17959         } else {
       
 17960         }
       
 17961     }
       
 17962 };
       
 17963 
       
 17964 Y.Node.ATTRS.scrollTop = {
       
 17965     getter: function() {
       
 17966         var node = Y.Node.getDOMNode(this);
       
 17967         return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
       
 17968     },
       
 17969 
       
 17970     setter: function(val) {
       
 17971         var node = Y.Node.getDOMNode(this);
       
 17972         if (node) {
       
 17973             if ('scrollTop' in node) {
       
 17974                 node.scrollTop = val;
       
 17975             } else if (node.document || node.nodeType === 9) {
       
 17976                 Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
       
 17977             }
       
 17978         } else {
       
 17979         }
       
 17980     }
       
 17981 };
       
 17982 
       
 17983 Y.Node.importMethod(Y.DOM, [
       
 17984 /**
       
 17985  * Gets the current position of the node in page coordinates. 
       
 17986  * @method getXY
       
 17987  * @for Node
       
 17988  * @return {Array} The XY position of the node
       
 17989 */
       
 17990     'getXY',
       
 17991 
       
 17992 /**
       
 17993  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
 17994  * @method setXY
       
 17995  * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
       
 17996  * @chainable
       
 17997  */
       
 17998     'setXY',
       
 17999 
       
 18000 /**
       
 18001  * Gets the current position of the node in page coordinates. 
       
 18002  * @method getX
       
 18003  * @return {Int} The X position of the node
       
 18004 */
       
 18005     'getX',
       
 18006 
       
 18007 /**
       
 18008  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
 18009  * @method setX
       
 18010  * @param {Int} x X value for new position (coordinates are page-based)
       
 18011  * @chainable
       
 18012  */
       
 18013     'setX',
       
 18014 
       
 18015 /**
       
 18016  * Gets the current position of the node in page coordinates. 
       
 18017  * @method getY
       
 18018  * @return {Int} The Y position of the node
       
 18019 */
       
 18020     'getY',
       
 18021 
       
 18022 /**
       
 18023  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
 18024  * @method setY
       
 18025  * @param {Int} y Y value for new position (coordinates are page-based)
       
 18026  * @chainable
       
 18027  */
       
 18028     'setY',
       
 18029 
       
 18030 /**
       
 18031  * Swaps the XY position of this node with another node. 
       
 18032  * @method swapXY
       
 18033  * @param {Node | HTMLElement} otherNode The node to swap with.
       
 18034  * @chainable
       
 18035  */
       
 18036     'swapXY'
       
 18037 ]);
       
 18038 
       
 18039 /**
       
 18040  * @module node
       
 18041  * @submodule node-screen
       
 18042  */
       
 18043 
       
 18044 /**
       
 18045  * Returns a region object for the node
       
 18046  * @config region
       
 18047  * @for Node
       
 18048  * @type Node
       
 18049  */
       
 18050 Y.Node.ATTRS.region = {
       
 18051     getter: function() {
       
 18052         var node = this.getDOMNode(),
       
 18053             region;
       
 18054 
       
 18055         if (node && !node.tagName) {
       
 18056             if (node.nodeType === 9) { // document
       
 18057                 node = node.documentElement;
       
 18058             }
       
 18059         }
       
 18060         if (Y.DOM.isWindow(node)) {
       
 18061             region = Y.DOM.viewportRegion(node);
       
 18062         } else {
       
 18063             region = Y.DOM.region(node);
       
 18064         }
       
 18065         return region;
       
 18066     }
       
 18067 };
       
 18068 
       
 18069 /**
       
 18070  * Returns a region object for the node's viewport
       
 18071  * @config viewportRegion
       
 18072  * @type Node
       
 18073  */
       
 18074 Y.Node.ATTRS.viewportRegion = {
       
 18075     getter: function() {
       
 18076         return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
       
 18077     }
       
 18078 };
       
 18079 
       
 18080 Y.Node.importMethod(Y.DOM, 'inViewportRegion');
       
 18081 
       
 18082 // these need special treatment to extract 2nd node arg
       
 18083 /**
       
 18084  * Compares the intersection of the node with another node or region
       
 18085  * @method intersect
       
 18086  * @for Node
       
 18087  * @param {Node|Object} node2 The node or region to compare with.
       
 18088  * @param {Object} altRegion An alternate region to use (rather than this node's).
       
 18089  * @return {Object} An object representing the intersection of the regions.
       
 18090  */
       
 18091 Y.Node.prototype.intersect = function(node2, altRegion) {
       
 18092     var node1 = Y.Node.getDOMNode(this);
       
 18093     if (Y.instanceOf(node2, Y.Node)) { // might be a region object
       
 18094         node2 = Y.Node.getDOMNode(node2);
       
 18095     }
       
 18096     return Y.DOM.intersect(node1, node2, altRegion);
       
 18097 };
       
 18098 
       
 18099 /**
       
 18100  * Determines whether or not the node is within the giving region.
       
 18101  * @method inRegion
       
 18102  * @param {Node|Object} node2 The node or region to compare with.
       
 18103  * @param {Boolean} all Whether or not all of the node must be in the region.
       
 18104  * @param {Object} altRegion An alternate region to use (rather than this node's).
       
 18105  * @return {Boolean} True if in region, false if not.
       
 18106  */
       
 18107 Y.Node.prototype.inRegion = function(node2, all, altRegion) {
       
 18108     var node1 = Y.Node.getDOMNode(this);
       
 18109     if (Y.instanceOf(node2, Y.Node)) { // might be a region object
       
 18110         node2 = Y.Node.getDOMNode(node2);
       
 18111     }
       
 18112     return Y.DOM.inRegion(node1, node2, all, altRegion);
       
 18113 };
       
 18114 
       
 18115 
       
 18116 }, '@VERSION@', {"requires": ["dom-screen", "node-base"]});
       
 18117 YUI.add('node-style', function (Y, NAME) {
       
 18118 
       
 18119 (function(Y) {
       
 18120 /**
       
 18121  * Extended Node interface for managing node styles.
       
 18122  * @module node
       
 18123  * @submodule node-style
       
 18124  */
       
 18125 
       
 18126 Y.mix(Y.Node.prototype, {
       
 18127     /**
       
 18128      * Sets a style property of the node.
       
 18129      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18130      * @method setStyle
       
 18131      * @param {String} attr The style attribute to set. 
       
 18132      * @param {String|Number} val The value. 
       
 18133      * @chainable
       
 18134      */
       
 18135     setStyle: function(attr, val) {
       
 18136         Y.DOM.setStyle(this._node, attr, val);
       
 18137         return this;
       
 18138     },
       
 18139 
       
 18140     /**
       
 18141      * Sets multiple style properties on the node.
       
 18142      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18143      * @method setStyles
       
 18144      * @param {Object} hash An object literal of property:value pairs. 
       
 18145      * @chainable
       
 18146      */
       
 18147     setStyles: function(hash) {
       
 18148         Y.DOM.setStyles(this._node, hash);
       
 18149         return this;
       
 18150     },
       
 18151 
       
 18152     /**
       
 18153      * Returns the style's current value.
       
 18154      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18155      * @method getStyle
       
 18156      * @for Node
       
 18157      * @param {String} attr The style attribute to retrieve. 
       
 18158      * @return {String} The current value of the style property for the element.
       
 18159      */
       
 18160 
       
 18161      getStyle: function(attr) {
       
 18162         return Y.DOM.getStyle(this._node, attr);
       
 18163      },
       
 18164 
       
 18165     /**
       
 18166      * Returns the computed value for the given style property.
       
 18167      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18168      * @method getComputedStyle
       
 18169      * @param {String} attr The style attribute to retrieve. 
       
 18170      * @return {String} The computed value of the style property for the element.
       
 18171      */
       
 18172      getComputedStyle: function(attr) {
       
 18173         return Y.DOM.getComputedStyle(this._node, attr);
       
 18174      }
       
 18175 });
       
 18176 
       
 18177 /**
       
 18178  * Returns an array of values for each node.
       
 18179  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18180  * @method getStyle
       
 18181  * @for NodeList
       
 18182  * @see Node.getStyle
       
 18183  * @param {String} attr The style attribute to retrieve. 
       
 18184  * @return {Array} The current values of the style property for the element.
       
 18185  */
       
 18186 
       
 18187 /**
       
 18188  * Returns an array of the computed value for each node.
       
 18189  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18190  * @method getComputedStyle
       
 18191  * @see Node.getComputedStyle
       
 18192  * @param {String} attr The style attribute to retrieve. 
       
 18193  * @return {Array} The computed values for each node.
       
 18194  */
       
 18195 
       
 18196 /**
       
 18197  * Sets a style property on each node.
       
 18198  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18199  * @method setStyle
       
 18200  * @see Node.setStyle
       
 18201  * @param {String} attr The style attribute to set. 
       
 18202  * @param {String|Number} val The value. 
       
 18203  * @chainable
       
 18204  */
       
 18205 
       
 18206 /**
       
 18207  * Sets multiple style properties on each node.
       
 18208  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18209  * @method setStyles
       
 18210  * @see Node.setStyles
       
 18211  * @param {Object} hash An object literal of property:value pairs. 
       
 18212  * @chainable
       
 18213  */
       
 18214 
       
 18215 // These are broken out to handle undefined return (avoid false positive for
       
 18216 // chainable)
       
 18217 
       
 18218 Y.NodeList.importMethod(Y.Node.prototype, ['getStyle', 'getComputedStyle', 'setStyle', 'setStyles']);
       
 18219 })(Y);
       
 18220 
       
 18221 
       
 18222 }, '@VERSION@', {"requires": ["dom-style", "node-base"]});
       
 18223 YUI.add('querystring-stringify-simple', function (Y, NAME) {
       
 18224 
       
 18225 /*global Y */
       
 18226 /**
       
 18227  * <p>Provides Y.QueryString.stringify method for converting objects to Query Strings.
       
 18228  * This is a subset implementation of the full querystring-stringify.</p>
       
 18229  * <p>This module provides the bare minimum functionality (encoding a hash of simple values),
       
 18230  * without the additional support for nested data structures.  Every key-value pair is
       
 18231  * encoded by encodeURIComponent.</p>
       
 18232  * <p>This module provides a minimalistic way for io to handle  single-level objects
       
 18233  * as transaction data.</p>
       
 18234  *
       
 18235  * @module querystring
       
 18236  * @submodule querystring-stringify-simple
       
 18237  */
       
 18238 
       
 18239 var QueryString = Y.namespace("QueryString"),
       
 18240     EUC = encodeURIComponent;
       
 18241 
       
 18242 
       
 18243 QueryString.stringify = function (obj, c) {
       
 18244     var qs = [],
       
 18245         // Default behavior is false; standard key notation.
       
 18246         s = c && c.arrayKey ? true : false,
       
 18247         key, i, l;
       
 18248 
       
 18249     for (key in obj) {
       
 18250         if (obj.hasOwnProperty(key)) {
       
 18251             if (Y.Lang.isArray(obj[key])) {
       
 18252                 for (i = 0, l = obj[key].length; i < l; i++) {
       
 18253                     qs.push(EUC(s ? key + '[]' : key) + '=' + EUC(obj[key][i]));
       
 18254                 }
       
 18255             }
       
 18256             else {
       
 18257                 qs.push(EUC(key) + '=' + EUC(obj[key]));
       
 18258             }
       
 18259         }
       
 18260     }
       
 18261 
       
 18262     return qs.join('&');
       
 18263 };
       
 18264 
       
 18265 
       
 18266 }, '@VERSION@', {"requires": ["yui-base"]});
       
 18267 YUI.add('io-base', function (Y, NAME) {
       
 18268 
       
 18269 /**
       
 18270 Base IO functionality. Provides basic XHR transport support.
       
 18271 
       
 18272 @module io
       
 18273 @submodule io-base
       
 18274 @for IO
       
 18275 **/
       
 18276 
       
 18277 var // List of events that comprise the IO event lifecycle.
       
 18278     EVENTS = ['start', 'complete', 'end', 'success', 'failure', 'progress'],
       
 18279 
       
 18280     // Whitelist of used XHR response object properties.
       
 18281     XHR_PROPS = ['status', 'statusText', 'responseText', 'responseXML'],
       
 18282 
       
 18283     win = Y.config.win,
       
 18284     uid = 0;
       
 18285 
       
 18286 /**
       
 18287 The IO class is a utility that brokers HTTP requests through a simplified
       
 18288 interface.  Specifically, it allows JavaScript to make HTTP requests to
       
 18289 a resource without a page reload.  The underlying transport for making
       
 18290 same-domain requests is the XMLHttpRequest object.  IO can also use
       
 18291 Flash, if specified as a transport, for cross-domain requests.
       
 18292 
       
 18293 @class IO
       
 18294 @constructor
       
 18295 @param {Object} config Object of EventTarget's publish method configurations
       
 18296                     used to configure IO's events.
       
 18297 **/
       
 18298 function IO (config) {
       
 18299     var io = this;
       
 18300 
       
 18301     io._uid = 'io:' + uid++;
       
 18302     io._init(config);
       
 18303     Y.io._map[io._uid] = io;
       
 18304 }
       
 18305 
       
 18306 IO.prototype = {
       
 18307     //--------------------------------------
       
 18308     //  Properties
       
 18309     //--------------------------------------
       
 18310 
       
 18311    /**
       
 18312     * A counter that increments for each transaction.
       
 18313     *
       
 18314     * @property _id
       
 18315     * @private
       
 18316     * @type {Number}
       
 18317     */
       
 18318     _id: 0,
       
 18319 
       
 18320    /**
       
 18321     * Object of IO HTTP headers sent with each transaction.
       
 18322     *
       
 18323     * @property _headers
       
 18324     * @private
       
 18325     * @type {Object}
       
 18326     */
       
 18327     _headers: {
       
 18328         'X-Requested-With' : 'XMLHttpRequest'
       
 18329     },
       
 18330 
       
 18331    /**
       
 18332     * Object that stores timeout values for any transaction with a defined
       
 18333     * "timeout" configuration property.
       
 18334     *
       
 18335     * @property _timeout
       
 18336     * @private
       
 18337     * @type {Object}
       
 18338     */
       
 18339     _timeout: {},
       
 18340 
       
 18341     //--------------------------------------
       
 18342     //  Methods
       
 18343     //--------------------------------------
       
 18344 
       
 18345     _init: function(config) {
       
 18346         var io = this, i, len;
       
 18347 
       
 18348         io.cfg = config || {};
       
 18349 
       
 18350         Y.augment(io, Y.EventTarget);
       
 18351         for (i = 0, len = EVENTS.length; i < len; ++i) {
       
 18352             // Publish IO global events with configurations, if any.
       
 18353             // IO global events are set to broadcast by default.
       
 18354             // These events use the "io:" namespace.
       
 18355             io.publish('io:' + EVENTS[i], Y.merge({ broadcast: 1 }, config));
       
 18356             // Publish IO transaction events with configurations, if
       
 18357             // any.  These events use the "io-trn:" namespace.
       
 18358             io.publish('io-trn:' + EVENTS[i], config);
       
 18359         }
       
 18360     },
       
 18361 
       
 18362    /**
       
 18363     * Method that creates a unique transaction object for each request.
       
 18364     *
       
 18365     * @method _create
       
 18366     * @private
       
 18367     * @param {Object} cfg Configuration object subset to determine if
       
 18368     *                 the transaction is an XDR or file upload,
       
 18369     *                 requiring an alternate transport.
       
 18370     * @param {Number} id Transaction id
       
 18371     * @return {Object} The transaction object
       
 18372     */
       
 18373     _create: function(config, id) {
       
 18374         var io = this,
       
 18375             transaction = {
       
 18376                 id : Y.Lang.isNumber(id) ? id : io._id++,
       
 18377                 uid: io._uid
       
 18378             },
       
 18379             alt = config.xdr ? config.xdr.use : null,
       
 18380             form = config.form && config.form.upload ? 'iframe' : null,
       
 18381             use;
       
 18382 
       
 18383         if (alt === 'native') {
       
 18384             // Non-IE and IE >= 10  can use XHR level 2 and not rely on an
       
 18385             // external transport.
       
 18386             alt = Y.UA.ie && !SUPPORTS_CORS ? 'xdr' : null;
       
 18387 
       
 18388             // Prevent "pre-flight" OPTIONS request by removing the
       
 18389             // `X-Requested-With` HTTP header from CORS requests. This header
       
 18390             // can be added back on a per-request basis, if desired.
       
 18391             io.setHeader('X-Requested-With');
       
 18392         }
       
 18393 
       
 18394         use = alt || form;
       
 18395         transaction = use ? Y.merge(Y.IO.customTransport(use), transaction) :
       
 18396                             Y.merge(Y.IO.defaultTransport(), transaction);
       
 18397 
       
 18398         if (transaction.notify) {
       
 18399             config.notify = function (e, t, c) { io.notify(e, t, c); };
       
 18400         }
       
 18401 
       
 18402         if (!use) {
       
 18403             if (win && win.FormData && config.data instanceof win.FormData) {
       
 18404                 transaction.c.upload.onprogress = function (e) {
       
 18405                     io.progress(transaction, e, config);
       
 18406                 };
       
 18407                 transaction.c.onload = function (e) {
       
 18408                     io.load(transaction, e, config);
       
 18409                 };
       
 18410                 transaction.c.onerror = function (e) {
       
 18411                     io.error(transaction, e, config);
       
 18412                 };
       
 18413                 transaction.upload = true;
       
 18414             }
       
 18415         }
       
 18416 
       
 18417         return transaction;
       
 18418     },
       
 18419 
       
 18420     _destroy: function(transaction) {
       
 18421         if (win && !transaction.notify && !transaction.xdr) {
       
 18422             if (XHR && !transaction.upload) {
       
 18423                 transaction.c.onreadystatechange = null;
       
 18424             } else if (transaction.upload) {
       
 18425                 transaction.c.upload.onprogress = null;
       
 18426                 transaction.c.onload = null;
       
 18427                 transaction.c.onerror = null;
       
 18428             } else if (Y.UA.ie && !transaction.e) {
       
 18429                 // IE, when using XMLHttpRequest as an ActiveX Object, will throw
       
 18430                 // a "Type Mismatch" error if the event handler is set to "null".
       
 18431                 transaction.c.abort();
       
 18432             }
       
 18433         }
       
 18434 
       
 18435         transaction = transaction.c = null;
       
 18436     },
       
 18437 
       
 18438    /**
       
 18439     * Method for creating and firing events.
       
 18440     *
       
 18441     * @method _evt
       
 18442     * @private
       
 18443     * @param {String} eventName Event to be published.
       
 18444     * @param {Object} transaction Transaction object.
       
 18445     * @param {Object} config Configuration data subset for event subscription.
       
 18446     */
       
 18447     _evt: function(eventName, transaction, config) {
       
 18448         var io          = this, params,
       
 18449             args        = config['arguments'],
       
 18450             emitFacade  = io.cfg.emitFacade,
       
 18451             globalEvent = "io:" + eventName,
       
 18452             trnEvent    = "io-trn:" + eventName;
       
 18453 
       
 18454         // Workaround for #2532107
       
 18455         this.detach(trnEvent);
       
 18456 
       
 18457         if (transaction.e) {
       
 18458             transaction.c = { status: 0, statusText: transaction.e };
       
 18459         }
       
 18460 
       
 18461         // Fire event with parameters or an Event Facade.
       
 18462         params = [ emitFacade ?
       
 18463             {
       
 18464                 id: transaction.id,
       
 18465                 data: transaction.c,
       
 18466                 cfg: config,
       
 18467                 'arguments': args
       
 18468             } :
       
 18469             transaction.id
       
 18470         ];
       
 18471 
       
 18472         if (!emitFacade) {
       
 18473             if (eventName === EVENTS[0] || eventName === EVENTS[2]) {
       
 18474                 if (args) {
       
 18475                     params.push(args);
       
 18476                 }
       
 18477             } else {
       
 18478                 if (transaction.evt) {
       
 18479                     params.push(transaction.evt);
       
 18480                 } else {
       
 18481                     params.push(transaction.c);
       
 18482                 }
       
 18483                 if (args) {
       
 18484                     params.push(args);
       
 18485                 }
       
 18486             }
       
 18487         }
       
 18488 
       
 18489         params.unshift(globalEvent);
       
 18490         // Fire global events.
       
 18491         io.fire.apply(io, params);
       
 18492         // Fire transaction events, if receivers are defined.
       
 18493         if (config.on) {
       
 18494             params[0] = trnEvent;
       
 18495             io.once(trnEvent, config.on[eventName], config.context || Y);
       
 18496             io.fire.apply(io, params);
       
 18497         }
       
 18498     },
       
 18499 
       
 18500    /**
       
 18501     * Fires event "io:start" and creates, fires a transaction-specific
       
 18502     * start event, if `config.on.start` is defined.
       
 18503     *
       
 18504     * @method start
       
 18505     * @param {Object} transaction Transaction object.
       
 18506     * @param {Object} config Configuration object for the transaction.
       
 18507     */
       
 18508     start: function(transaction, config) {
       
 18509        /**
       
 18510         * Signals the start of an IO request.
       
 18511         * @event io:start
       
 18512         */
       
 18513         this._evt(EVENTS[0], transaction, config);
       
 18514     },
       
 18515 
       
 18516    /**
       
 18517     * Fires event "io:complete" and creates, fires a
       
 18518     * transaction-specific "complete" event, if config.on.complete is
       
 18519     * defined.
       
 18520     *
       
 18521     * @method complete
       
 18522     * @param {Object} transaction Transaction object.
       
 18523     * @param {Object} config Configuration object for the transaction.
       
 18524     */
       
 18525     complete: function(transaction, config) {
       
 18526        /**
       
 18527         * Signals the completion of the request-response phase of a
       
 18528         * transaction. Response status and data are accessible, if
       
 18529         * available, in this event.
       
 18530         * @event io:complete
       
 18531         */
       
 18532         this._evt(EVENTS[1], transaction, config);
       
 18533     },
       
 18534 
       
 18535    /**
       
 18536     * Fires event "io:end" and creates, fires a transaction-specific "end"
       
 18537     * event, if config.on.end is defined.
       
 18538     *
       
 18539     * @method end
       
 18540     * @param {Object} transaction Transaction object.
       
 18541     * @param {Object} config Configuration object for the transaction.
       
 18542     */
       
 18543     end: function(transaction, config) {
       
 18544        /**
       
 18545         * Signals the end of the transaction lifecycle.
       
 18546         * @event io:end
       
 18547         */
       
 18548         this._evt(EVENTS[2], transaction, config);
       
 18549         this._destroy(transaction);
       
 18550     },
       
 18551 
       
 18552    /**
       
 18553     * Fires event "io:success" and creates, fires a transaction-specific
       
 18554     * "success" event, if config.on.success is defined.
       
 18555     *
       
 18556     * @method success
       
 18557     * @param {Object} transaction Transaction object.
       
 18558     * @param {Object} config Configuration object for the transaction.
       
 18559     */
       
 18560     success: function(transaction, config) {
       
 18561        /**
       
 18562         * Signals an HTTP response with status in the 2xx range.
       
 18563         * Fires after io:complete.
       
 18564         * @event io:success
       
 18565         */
       
 18566         this._evt(EVENTS[3], transaction, config);
       
 18567         this.end(transaction, config);
       
 18568     },
       
 18569 
       
 18570    /**
       
 18571     * Fires event "io:failure" and creates, fires a transaction-specific
       
 18572     * "failure" event, if config.on.failure is defined.
       
 18573     *
       
 18574     * @method failure
       
 18575     * @param {Object} transaction Transaction object.
       
 18576     * @param {Object} config Configuration object for the transaction.
       
 18577     */
       
 18578     failure: function(transaction, config) {
       
 18579        /**
       
 18580         * Signals an HTTP response with status outside of the 2xx range.
       
 18581         * Fires after io:complete.
       
 18582         * @event io:failure
       
 18583         */
       
 18584         this._evt(EVENTS[4], transaction, config);
       
 18585         this.end(transaction, config);
       
 18586     },
       
 18587 
       
 18588    /**
       
 18589     * Fires event "io:progress" and creates, fires a transaction-specific
       
 18590     * "progress" event -- for XMLHttpRequest file upload -- if
       
 18591     * config.on.progress is defined.
       
 18592     *
       
 18593     * @method progress
       
 18594     * @param {Object} transaction Transaction object.
       
 18595     * @param {Object} progress event.
       
 18596     * @param {Object} config Configuration object for the transaction.
       
 18597     */
       
 18598     progress: function(transaction, e, config) {
       
 18599        /**
       
 18600         * Signals the interactive state during a file upload transaction.
       
 18601         * This event fires after io:start and before io:complete.
       
 18602         * @event io:progress
       
 18603         */
       
 18604         transaction.evt = e;
       
 18605         this._evt(EVENTS[5], transaction, config);
       
 18606     },
       
 18607 
       
 18608    /**
       
 18609     * Fires event "io:complete" and creates, fires a transaction-specific
       
 18610     * "complete" event -- for XMLHttpRequest file upload -- if
       
 18611     * config.on.complete is defined.
       
 18612     *
       
 18613     * @method load
       
 18614     * @param {Object} transaction Transaction object.
       
 18615     * @param {Object} load event.
       
 18616     * @param {Object} config Configuration object for the transaction.
       
 18617     */
       
 18618     load: function (transaction, e, config) {
       
 18619         transaction.evt = e.target;
       
 18620         this._evt(EVENTS[1], transaction, config);
       
 18621     },
       
 18622 
       
 18623    /**
       
 18624     * Fires event "io:failure" and creates, fires a transaction-specific
       
 18625     * "failure" event -- for XMLHttpRequest file upload -- if
       
 18626     * config.on.failure is defined.
       
 18627     *
       
 18628     * @method error
       
 18629     * @param {Object} transaction Transaction object.
       
 18630     * @param {Object} error event.
       
 18631     * @param {Object} config Configuration object for the transaction.
       
 18632     */
       
 18633     error: function (transaction, e, config) {
       
 18634         transaction.evt = e;
       
 18635         this._evt(EVENTS[4], transaction, config);
       
 18636     },
       
 18637 
       
 18638    /**
       
 18639     * Retry an XDR transaction, using the Flash tranport, if the native
       
 18640     * transport fails.
       
 18641     *
       
 18642     * @method _retry
       
 18643     * @private
       
 18644     * @param {Object} transaction Transaction object.
       
 18645     * @param {String} uri Qualified path to transaction resource.
       
 18646     * @param {Object} config Configuration object for the transaction.
       
 18647     */
       
 18648     _retry: function(transaction, uri, config) {
       
 18649         this._destroy(transaction);
       
 18650         config.xdr.use = 'flash';
       
 18651         return this.send(uri, config, transaction.id);
       
 18652     },
       
 18653 
       
 18654    /**
       
 18655     * Method that concatenates string data for HTTP GET transactions.
       
 18656     *
       
 18657     * @method _concat
       
 18658     * @private
       
 18659     * @param {String} uri URI or root data.
       
 18660     * @param {String} data Data to be concatenated onto URI.
       
 18661     * @return {String}
       
 18662     */
       
 18663     _concat: function(uri, data) {
       
 18664         uri += (uri.indexOf('?') === -1 ? '?' : '&') + data;
       
 18665         return uri;
       
 18666     },
       
 18667 
       
 18668    /**
       
 18669     * Stores default client headers for all transactions. If a label is
       
 18670     * passed with no value argument, the header will be deleted.
       
 18671     *
       
 18672     * @method setHeader
       
 18673     * @param {String} name HTTP header
       
 18674     * @param {String} value HTTP header value
       
 18675     */
       
 18676     setHeader: function(name, value) {
       
 18677         if (value) {
       
 18678             this._headers[name] = value;
       
 18679         } else {
       
 18680             delete this._headers[name];
       
 18681         }
       
 18682     },
       
 18683 
       
 18684    /**
       
 18685     * Method that sets all HTTP headers to be sent in a transaction.
       
 18686     *
       
 18687     * @method _setHeaders
       
 18688     * @private
       
 18689     * @param {Object} transaction - XHR instance for the specific transaction.
       
 18690     * @param {Object} headers - HTTP headers for the specific transaction, as
       
 18691     *                    defined in the configuration object passed to YUI.io().
       
 18692     */
       
 18693     _setHeaders: function(transaction, headers) {
       
 18694         headers = Y.merge(this._headers, headers);
       
 18695         Y.Object.each(headers, function(value, name) {
       
 18696             if (value !== 'disable') {
       
 18697                 transaction.setRequestHeader(name, headers[name]);
       
 18698             }
       
 18699         });
       
 18700     },
       
 18701 
       
 18702    /**
       
 18703     * Starts timeout count if the configuration object has a defined
       
 18704     * timeout property.
       
 18705     *
       
 18706     * @method _startTimeout
       
 18707     * @private
       
 18708     * @param {Object} transaction Transaction object generated by _create().
       
 18709     * @param {Object} timeout Timeout in milliseconds.
       
 18710     */
       
 18711     _startTimeout: function(transaction, timeout) {
       
 18712         var io = this;
       
 18713 
       
 18714         io._timeout[transaction.id] = setTimeout(function() {
       
 18715             io._abort(transaction, 'timeout');
       
 18716         }, timeout);
       
 18717     },
       
 18718 
       
 18719    /**
       
 18720     * Clears the timeout interval started by _startTimeout().
       
 18721     *
       
 18722     * @method _clearTimeout
       
 18723     * @private
       
 18724     * @param {Number} id - Transaction id.
       
 18725     */
       
 18726     _clearTimeout: function(id) {
       
 18727         clearTimeout(this._timeout[id]);
       
 18728         delete this._timeout[id];
       
 18729     },
       
 18730 
       
 18731    /**
       
 18732     * Method that determines if a transaction response qualifies as success
       
 18733     * or failure, based on the response HTTP status code, and fires the
       
 18734     * appropriate success or failure events.
       
 18735     *
       
 18736     * @method _result
       
 18737     * @private
       
 18738     * @static
       
 18739     * @param {Object} transaction Transaction object generated by _create().
       
 18740     * @param {Object} config Configuration object passed to io().
       
 18741     */
       
 18742     _result: function(transaction, config) {
       
 18743         var status;
       
 18744         // Firefox will throw an exception if attempting to access
       
 18745         // an XHR object's status property, after a request is aborted.
       
 18746         try {
       
 18747             status = transaction.c.status;
       
 18748         } catch(e) {
       
 18749             status = 0;
       
 18750         }
       
 18751 
       
 18752         // IE reports HTTP 204 as HTTP 1223.
       
 18753         if (status >= 200 && status < 300 || status === 304 || status === 1223) {
       
 18754             this.success(transaction, config);
       
 18755         } else {
       
 18756             this.failure(transaction, config);
       
 18757         }
       
 18758     },
       
 18759 
       
 18760    /**
       
 18761     * Event handler bound to onreadystatechange.
       
 18762     *
       
 18763     * @method _rS
       
 18764     * @private
       
 18765     * @param {Object} transaction Transaction object generated by _create().
       
 18766     * @param {Object} config Configuration object passed to YUI.io().
       
 18767     */
       
 18768     _rS: function(transaction, config) {
       
 18769         var io = this;
       
 18770 
       
 18771         if (transaction.c.readyState === 4) {
       
 18772             if (config.timeout) {
       
 18773                 io._clearTimeout(transaction.id);
       
 18774             }
       
 18775 
       
 18776             // Yield in the event of request timeout or abort.
       
 18777             setTimeout(function() {
       
 18778                 io.complete(transaction, config);
       
 18779                 io._result(transaction, config);
       
 18780             }, 0);
       
 18781         }
       
 18782     },
       
 18783 
       
 18784    /**
       
 18785     * Terminates a transaction due to an explicit abort or timeout.
       
 18786     *
       
 18787     * @method _abort
       
 18788     * @private
       
 18789     * @param {Object} transaction Transaction object generated by _create().
       
 18790     * @param {String} type Identifies timed out or aborted transaction.
       
 18791     */
       
 18792     _abort: function(transaction, type) {
       
 18793         if (transaction && transaction.c) {
       
 18794             transaction.e = type;
       
 18795             transaction.c.abort();
       
 18796         }
       
 18797     },
       
 18798 
       
 18799    /**
       
 18800     * Requests a transaction. `send()` is implemented as `Y.io()`.  Each
       
 18801     * transaction may include a configuration object.  Its properties are:
       
 18802     *
       
 18803     * <dl>
       
 18804     *   <dt>method</dt>
       
 18805     *     <dd>HTTP method verb (e.g., GET or POST). If this property is not
       
 18806     *         not defined, the default value will be GET.</dd>
       
 18807     *
       
 18808     *   <dt>data</dt>
       
 18809     *     <dd>This is the name-value string that will be sent as the
       
 18810     *     transaction data. If the request is HTTP GET, the data become
       
 18811     *     part of querystring. If HTTP POST, the data are sent in the
       
 18812     *     message body.</dd>
       
 18813     *
       
 18814     *   <dt>xdr</dt>
       
 18815     *     <dd>Defines the transport to be used for cross-domain requests.
       
 18816     *     By setting this property, the transaction will use the specified
       
 18817     *     transport instead of XMLHttpRequest. The properties of the
       
 18818     *     transport object are:
       
 18819     *     <dl>
       
 18820     *       <dt>use</dt>
       
 18821     *         <dd>The transport to be used: 'flash' or 'native'</dd>
       
 18822     *       <dt>dataType</dt>
       
 18823     *         <dd>Set the value to 'XML' if that is the expected response
       
 18824     *         content type.</dd>
       
 18825     *       <dt>credentials</dt>
       
 18826     *         <dd>Set the value to 'true' to set XHR.withCredentials property to true.</dd>
       
 18827     *     </dl></dd>
       
 18828     *
       
 18829     *   <dt>form</dt>
       
 18830     *     <dd>Form serialization configuration object.  Its properties are:
       
 18831     *     <dl>
       
 18832     *       <dt>id</dt>
       
 18833     *         <dd>Node object or id of HTML form</dd>
       
 18834     *       <dt>useDisabled</dt>
       
 18835     *         <dd>`true` to also serialize disabled form field values
       
 18836     *         (defaults to `false`)</dd>
       
 18837     *     </dl></dd>
       
 18838     *
       
 18839     *   <dt>on</dt>
       
 18840     *     <dd>Assigns transaction event subscriptions. Available events are:
       
 18841     *     <dl>
       
 18842     *       <dt>start</dt>
       
 18843     *         <dd>Fires when a request is sent to a resource.</dd>
       
 18844     *       <dt>complete</dt>
       
 18845     *         <dd>Fires when the transaction is complete.</dd>
       
 18846     *       <dt>success</dt>
       
 18847     *         <dd>Fires when the HTTP response status is within the 2xx
       
 18848     *         range.</dd>
       
 18849     *       <dt>failure</dt>
       
 18850     *         <dd>Fires when the HTTP response status is outside the 2xx
       
 18851     *         range, if an exception occurs, if the transation is aborted,
       
 18852     *         or if the transaction exceeds a configured `timeout`.</dd>
       
 18853     *       <dt>end</dt>
       
 18854     *         <dd>Fires at the conclusion of the transaction
       
 18855     *            lifecycle, after `success` or `failure`.</dd>
       
 18856     *     </dl>
       
 18857     *
       
 18858     *     <p>Callback functions for `start` and `end` receive the id of the
       
 18859     *     transaction as a first argument. For `complete`, `success`, and
       
 18860     *     `failure`, callbacks receive the id and the response object
       
 18861     *     (usually the XMLHttpRequest instance).  If the `arguments`
       
 18862     *     property was included in the configuration object passed to
       
 18863     *     `Y.io()`, the configured data will be passed to all callbacks as
       
 18864     *     the last argument.</p>
       
 18865     *     </dd>
       
 18866     *
       
 18867     *   <dt>sync</dt>
       
 18868     *     <dd>Pass `true` to make a same-domain transaction synchronous.
       
 18869     *     <strong>CAVEAT</strong>: This will negatively impact the user
       
 18870     *     experience. Have a <em>very</em> good reason if you intend to use
       
 18871     *     this.</dd>
       
 18872     *
       
 18873     *   <dt>context</dt>
       
 18874     *     <dd>The "`this'" object for all configured event handlers. If a
       
 18875     *     specific context is needed for individual callbacks, bind the
       
 18876     *     callback to a context using `Y.bind()`.</dd>
       
 18877     *
       
 18878     *   <dt>headers</dt>
       
 18879     *     <dd>Object map of transaction headers to send to the server. The
       
 18880     *     object keys are the header names and the values are the header
       
 18881     *     values.</dd>
       
 18882     *
       
 18883     *   <dt>timeout</dt>
       
 18884     *     <dd>Millisecond threshold for the transaction before being
       
 18885     *     automatically aborted.</dd>
       
 18886     *
       
 18887     *   <dt>arguments</dt>
       
 18888     *     <dd>User-defined data passed to all registered event handlers.
       
 18889     *     This value is available as the second argument in the "start" and
       
 18890     *     "end" event handlers. It is the third argument in the "complete",
       
 18891     *     "success", and "failure" event handlers. <strong>Be sure to quote
       
 18892     *     this property name in the transaction configuration as
       
 18893     *     "arguments" is a reserved word in JavaScript</strong> (e.g.
       
 18894     *     `Y.io({ ..., "arguments": stuff })`).</dd>
       
 18895     * </dl>
       
 18896     *
       
 18897     * @method send
       
 18898     * @public
       
 18899     * @param {String} uri Qualified path to transaction resource.
       
 18900     * @param {Object} config Configuration object for the transaction.
       
 18901     * @param {Number} id Transaction id, if already set.
       
 18902     * @return {Object}
       
 18903     */
       
 18904     send: function(uri, config, id) {
       
 18905         var transaction, method, i, len, sync, data,
       
 18906             io = this,
       
 18907             u = uri,
       
 18908             response = {};
       
 18909 
       
 18910         config = config ? Y.Object(config) : {};
       
 18911         transaction = io._create(config, id);
       
 18912         method = config.method ? config.method.toUpperCase() : 'GET';
       
 18913         sync = config.sync;
       
 18914         data = config.data;
       
 18915 
       
 18916         // Serialize a map object into a key-value string using
       
 18917         // querystring-stringify-simple.
       
 18918         if ((Y.Lang.isObject(data) && !data.nodeType) && !transaction.upload) {
       
 18919             if (Y.QueryString && Y.QueryString.stringify) {
       
 18920                 config.data = data = Y.QueryString.stringify(data);
       
 18921             } else {
       
 18922             }
       
 18923         }
       
 18924 
       
 18925         if (config.form) {
       
 18926             if (config.form.upload) {
       
 18927                 // This is a file upload transaction, calling
       
 18928                 // upload() in io-upload-iframe.
       
 18929                 return io.upload(transaction, uri, config);
       
 18930             } else {
       
 18931                 // Serialize HTML form data into a key-value string.
       
 18932                 data = io._serialize(config.form, data);
       
 18933             }
       
 18934         }
       
 18935 
       
 18936         // Convert falsy values to an empty string. This way IE can't be
       
 18937         // rediculous and translate `undefined` to "undefined".
       
 18938         data || (data = '');
       
 18939 
       
 18940         if (data) {
       
 18941             switch (method) {
       
 18942                 case 'GET':
       
 18943                 case 'HEAD':
       
 18944                 case 'DELETE':
       
 18945                     u = io._concat(u, data);
       
 18946                     data = '';
       
 18947                     break;
       
 18948                 case 'POST':
       
 18949                 case 'PUT':
       
 18950                     // If Content-Type is defined in the configuration object, or
       
 18951                     // or as a default header, it will be used instead of
       
 18952                     // 'application/x-www-form-urlencoded; charset=UTF-8'
       
 18953                     config.headers = Y.merge({
       
 18954                         'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
       
 18955                     }, config.headers);
       
 18956                     break;
       
 18957             }
       
 18958         }
       
 18959 
       
 18960         if (transaction.xdr) {
       
 18961             // Route data to io-xdr module for flash and XDomainRequest.
       
 18962             return io.xdr(u, transaction, config);
       
 18963         }
       
 18964         else if (transaction.notify) {
       
 18965             // Route data to custom transport
       
 18966             return transaction.c.send(transaction, uri, config);
       
 18967         }
       
 18968 
       
 18969         if (!sync && !transaction.upload) {
       
 18970             transaction.c.onreadystatechange = function() {
       
 18971                 io._rS(transaction, config);
       
 18972             };
       
 18973         }
       
 18974 
       
 18975         try {
       
 18976             // Determine if request is to be set as
       
 18977             // synchronous or asynchronous.
       
 18978             transaction.c.open(method, u, !sync, config.username || null, config.password || null);
       
 18979             io._setHeaders(transaction.c, config.headers || {});
       
 18980             io.start(transaction, config);
       
 18981 
       
 18982             // Will work only in browsers that implement the
       
 18983             // Cross-Origin Resource Sharing draft.
       
 18984             if (config.xdr && config.xdr.credentials && SUPPORTS_CORS) {
       
 18985                 transaction.c.withCredentials = true;
       
 18986             }
       
 18987 
       
 18988             // Using "null" with HTTP POST will result in a request
       
 18989             // with no Content-Length header defined.
       
 18990             transaction.c.send(data);
       
 18991 
       
 18992             if (sync) {
       
 18993                 // Create a response object for synchronous transactions,
       
 18994                 // mixing id and arguments properties with the xhr
       
 18995                 // properties whitelist.
       
 18996                 for (i = 0, len = XHR_PROPS.length; i < len; ++i) {
       
 18997                     response[XHR_PROPS[i]] = transaction.c[XHR_PROPS[i]];
       
 18998                 }
       
 18999 
       
 19000                 response.getAllResponseHeaders = function() {
       
 19001                     return transaction.c.getAllResponseHeaders();
       
 19002                 };
       
 19003 
       
 19004                 response.getResponseHeader = function(name) {
       
 19005                     return transaction.c.getResponseHeader(name);
       
 19006                 };
       
 19007 
       
 19008                 io.complete(transaction, config);
       
 19009                 io._result(transaction, config);
       
 19010 
       
 19011                 return response;
       
 19012             }
       
 19013         } catch(e) {
       
 19014             if (transaction.xdr) {
       
 19015                 // This exception is usually thrown by browsers
       
 19016                 // that do not support XMLHttpRequest Level 2.
       
 19017                 // Retry the request with the XDR transport set
       
 19018                 // to 'flash'.  If the Flash transport is not
       
 19019                 // initialized or available, the transaction
       
 19020                 // will resolve to a transport error.
       
 19021                 return io._retry(transaction, uri, config);
       
 19022             } else {
       
 19023                 io.complete(transaction, config);
       
 19024                 io._result(transaction, config);
       
 19025             }
       
 19026         }
       
 19027 
       
 19028         // If config.timeout is defined, and the request is standard XHR,
       
 19029         // initialize timeout polling.
       
 19030         if (config.timeout) {
       
 19031             io._startTimeout(transaction, config.timeout);
       
 19032         }
       
 19033 
       
 19034         return {
       
 19035             id: transaction.id,
       
 19036             abort: function() {
       
 19037                 return transaction.c ? io._abort(transaction, 'abort') : false;
       
 19038             },
       
 19039             isInProgress: function() {
       
 19040                 return transaction.c ? (transaction.c.readyState % 4) : false;
       
 19041             },
       
 19042             io: io
       
 19043         };
       
 19044     }
       
 19045 };
       
 19046 
       
 19047 /**
       
 19048 Method for initiating an ajax call.  The first argument is the url end
       
 19049 point for the call.  The second argument is an object to configure the
       
 19050 transaction and attach event subscriptions.  The configuration object
       
 19051 supports the following properties:
       
 19052 
       
 19053 <dl>
       
 19054   <dt>method</dt>
       
 19055     <dd>HTTP method verb (e.g., GET or POST). If this property is not
       
 19056         not defined, the default value will be GET.</dd>
       
 19057 
       
 19058   <dt>data</dt>
       
 19059     <dd>This is the name-value string that will be sent as the
       
 19060     transaction data. If the request is HTTP GET, the data become
       
 19061     part of querystring. If HTTP POST, the data are sent in the
       
 19062     message body.</dd>
       
 19063 
       
 19064   <dt>xdr</dt>
       
 19065     <dd>Defines the transport to be used for cross-domain requests.
       
 19066     By setting this property, the transaction will use the specified
       
 19067     transport instead of XMLHttpRequest. The properties of the
       
 19068     transport object are:
       
 19069     <dl>
       
 19070       <dt>use</dt>
       
 19071         <dd>The transport to be used: 'flash' or 'native'</dd>
       
 19072       <dt>dataType</dt>
       
 19073         <dd>Set the value to 'XML' if that is the expected response
       
 19074         content type.</dd>
       
 19075     </dl></dd>
       
 19076 
       
 19077   <dt>form</dt>
       
 19078     <dd>Form serialization configuration object.  Its properties are:
       
 19079     <dl>
       
 19080       <dt>id</dt>
       
 19081         <dd>Node object or id of HTML form</dd>
       
 19082       <dt>useDisabled</dt>
       
 19083         <dd>`true` to also serialize disabled form field values
       
 19084         (defaults to `false`)</dd>
       
 19085     </dl></dd>
       
 19086 
       
 19087   <dt>on</dt>
       
 19088     <dd>Assigns transaction event subscriptions. Available events are:
       
 19089     <dl>
       
 19090       <dt>start</dt>
       
 19091         <dd>Fires when a request is sent to a resource.</dd>
       
 19092       <dt>complete</dt>
       
 19093         <dd>Fires when the transaction is complete.</dd>
       
 19094       <dt>success</dt>
       
 19095         <dd>Fires when the HTTP response status is within the 2xx
       
 19096         range.</dd>
       
 19097       <dt>failure</dt>
       
 19098         <dd>Fires when the HTTP response status is outside the 2xx
       
 19099         range, if an exception occurs, if the transation is aborted,
       
 19100         or if the transaction exceeds a configured `timeout`.</dd>
       
 19101       <dt>end</dt>
       
 19102         <dd>Fires at the conclusion of the transaction
       
 19103            lifecycle, after `success` or `failure`.</dd>
       
 19104     </dl>
       
 19105 
       
 19106     <p>Callback functions for `start` and `end` receive the id of the
       
 19107     transaction as a first argument. For `complete`, `success`, and
       
 19108     `failure`, callbacks receive the id and the response object
       
 19109     (usually the XMLHttpRequest instance).  If the `arguments`
       
 19110     property was included in the configuration object passed to
       
 19111     `Y.io()`, the configured data will be passed to all callbacks as
       
 19112     the last argument.</p>
       
 19113     </dd>
       
 19114 
       
 19115   <dt>sync</dt>
       
 19116     <dd>Pass `true` to make a same-domain transaction synchronous.
       
 19117     <strong>CAVEAT</strong>: This will negatively impact the user
       
 19118     experience. Have a <em>very</em> good reason if you intend to use
       
 19119     this.</dd>
       
 19120 
       
 19121   <dt>context</dt>
       
 19122     <dd>The "`this'" object for all configured event handlers. If a
       
 19123     specific context is needed for individual callbacks, bind the
       
 19124     callback to a context using `Y.bind()`.</dd>
       
 19125 
       
 19126   <dt>headers</dt>
       
 19127     <dd>Object map of transaction headers to send to the server. The
       
 19128     object keys are the header names and the values are the header
       
 19129     values.</dd>
       
 19130 
       
 19131   <dt>timeout</dt>
       
 19132     <dd>Millisecond threshold for the transaction before being
       
 19133     automatically aborted.</dd>
       
 19134 
       
 19135   <dt>arguments</dt>
       
 19136     <dd>User-defined data passed to all registered event handlers.
       
 19137     This value is available as the second argument in the "start" and
       
 19138     "end" event handlers. It is the third argument in the "complete",
       
 19139     "success", and "failure" event handlers. <strong>Be sure to quote
       
 19140     this property name in the transaction configuration as
       
 19141     "arguments" is a reserved word in JavaScript</strong> (e.g.
       
 19142     `Y.io({ ..., "arguments": stuff })`).</dd>
       
 19143 </dl>
       
 19144 
       
 19145 @method io
       
 19146 @static
       
 19147 @param {String} url qualified path to transaction resource.
       
 19148 @param {Object} config configuration object for the transaction.
       
 19149 @return {Object}
       
 19150 @for YUI
       
 19151 **/
       
 19152 Y.io = function(url, config) {
       
 19153     // Calling IO through the static interface will use and reuse
       
 19154     // an instance of IO.
       
 19155     var transaction = Y.io._map['io:0'] || new IO();
       
 19156     return transaction.send.apply(transaction, [url, config]);
       
 19157 };
       
 19158 
       
 19159 /**
       
 19160 Method for setting and deleting IO HTTP headers to be sent with every
       
 19161 request.
       
 19162 
       
 19163 Hosted as a property on the `io` function (e.g. `Y.io.header`).
       
 19164 
       
 19165 @method header
       
 19166 @param {String} name HTTP header
       
 19167 @param {String} value HTTP header value
       
 19168 @static
       
 19169 **/
       
 19170 Y.io.header = function(name, value) {
       
 19171     // Calling IO through the static interface will use and reuse
       
 19172     // an instance of IO.
       
 19173     var transaction = Y.io._map['io:0'] || new IO();
       
 19174     transaction.setHeader(name, value);
       
 19175 };
       
 19176 
       
 19177 Y.IO = IO;
       
 19178 // Map of all IO instances created.
       
 19179 Y.io._map = {};
       
 19180 var XHR = win && win.XMLHttpRequest,
       
 19181     XDR = win && win.XDomainRequest,
       
 19182     AX = win && win.ActiveXObject,
       
 19183 
       
 19184     // Checks for the presence of the `withCredentials` in an XHR instance
       
 19185     // object, which will be present if the environment supports CORS.
       
 19186     SUPPORTS_CORS = XHR && 'withCredentials' in (new XMLHttpRequest());
       
 19187 
       
 19188 
       
 19189 Y.mix(Y.IO, {
       
 19190     /**
       
 19191     * The ID of the default IO transport, defaults to `xhr`
       
 19192     * @property _default
       
 19193     * @type {String}
       
 19194     * @static
       
 19195     */
       
 19196     _default: 'xhr',
       
 19197     /**
       
 19198     *
       
 19199     * @method defaultTransport
       
 19200     * @static
       
 19201     * @param {String} [id] The transport to set as the default, if empty a new transport is created.
       
 19202     * @return {Object} The transport object with a `send` method
       
 19203     */
       
 19204     defaultTransport: function(id) {
       
 19205         if (id) {
       
 19206             Y.IO._default = id;
       
 19207         } else {
       
 19208             var o = {
       
 19209                 c: Y.IO.transports[Y.IO._default](),
       
 19210                 notify: Y.IO._default === 'xhr' ? false : true
       
 19211             };
       
 19212             return o;
       
 19213         }
       
 19214     },
       
 19215     /**
       
 19216     * An object hash of custom transports available to IO
       
 19217     * @property transports
       
 19218     * @type {Object}
       
 19219     * @static
       
 19220     */
       
 19221     transports: {
       
 19222         xhr: function () {
       
 19223             return XHR ? new XMLHttpRequest() :
       
 19224                 AX ? new ActiveXObject('Microsoft.XMLHTTP') : null;
       
 19225         },
       
 19226         xdr: function () {
       
 19227             return XDR ? new XDomainRequest() : null;
       
 19228         },
       
 19229         iframe: function () { return {}; },
       
 19230         flash: null,
       
 19231         nodejs: null
       
 19232     },
       
 19233     /**
       
 19234     * Create a custom transport of type and return it's object
       
 19235     * @method customTransport
       
 19236     * @param {String} id The id of the transport to create.
       
 19237     * @static
       
 19238     */
       
 19239     customTransport: function(id) {
       
 19240         var o = { c: Y.IO.transports[id]() };
       
 19241 
       
 19242         o[(id === 'xdr' || id === 'flash') ? 'xdr' : 'notify'] = true;
       
 19243         return o;
       
 19244     }
       
 19245 });
       
 19246 
       
 19247 Y.mix(Y.IO.prototype, {
       
 19248     /**
       
 19249     * Fired from the notify method of the transport which in turn fires
       
 19250     * the event on the IO object.
       
 19251     * @method notify
       
 19252     * @param {String} event The name of the event
       
 19253     * @param {Object} transaction The transaction object
       
 19254     * @param {Object} config The configuration object for this transaction
       
 19255     */
       
 19256     notify: function(event, transaction, config) {
       
 19257         var io = this;
       
 19258 
       
 19259         switch (event) {
       
 19260             case 'timeout':
       
 19261             case 'abort':
       
 19262             case 'transport error':
       
 19263                 transaction.c = { status: 0, statusText: event };
       
 19264                 event = 'failure';
       
 19265             default:
       
 19266                 io[event].apply(io, [transaction, config]);
       
 19267         }
       
 19268     }
       
 19269 });
       
 19270 
       
 19271 
       
 19272 
       
 19273 
       
 19274 }, '@VERSION@', {"requires": ["event-custom-base", "querystring-stringify-simple"]});
       
 19275 YUI.add('json-parse', function (Y, NAME) {
       
 19276 
       
 19277 var _JSON = Y.config.global.JSON;
       
 19278 
       
 19279 Y.namespace('JSON').parse = function (obj, reviver, space) {
       
 19280     return _JSON.parse((typeof obj === 'string' ? obj : obj + ''), reviver, space);
       
 19281 };
       
 19282 
       
 19283 
       
 19284 }, '@VERSION@', {"requires": ["yui-base"]});
       
 19285 YUI.add('transition', function (Y, NAME) {
       
 19286 
       
 19287 /**
       
 19288 * Provides the transition method for Node.
       
 19289 * Transition has no API of its own, but adds the transition method to Node.
       
 19290 *
       
 19291 * @module transition
       
 19292 * @requires node-style
       
 19293 */
       
 19294 
       
 19295 var CAMEL_VENDOR_PREFIX = '',
       
 19296     VENDOR_PREFIX = '',
       
 19297     DOCUMENT = Y.config.doc,
       
 19298     DOCUMENT_ELEMENT = 'documentElement',
       
 19299     DOCUMENT_STYLE = DOCUMENT[DOCUMENT_ELEMENT].style,
       
 19300     TRANSITION_CAMEL = 'transition',
       
 19301     TRANSITION_PROPERTY_CAMEL = 'transitionProperty',
       
 19302     TRANSITION_PROPERTY,
       
 19303     TRANSITION_DURATION,
       
 19304     TRANSITION_TIMING_FUNCTION,
       
 19305     TRANSITION_DELAY,
       
 19306     TRANSITION_END,
       
 19307     ON_TRANSITION_END,
       
 19308 
       
 19309     EMPTY_OBJ = {},
       
 19310 
       
 19311     VENDORS = [
       
 19312         'Webkit',
       
 19313         'Moz'
       
 19314     ],
       
 19315 
       
 19316     VENDOR_TRANSITION_END = {
       
 19317         Webkit: 'webkitTransitionEnd'
       
 19318     },
       
 19319 
       
 19320 /**
       
 19321  * A class for constructing transition instances.
       
 19322  * Adds the "transition" method to Node.
       
 19323  * @class Transition
       
 19324  * @constructor
       
 19325  */
       
 19326 
       
 19327 Transition = function() {
       
 19328     this.init.apply(this, arguments);
       
 19329 };
       
 19330 
       
 19331 // One off handling of transform-prefixing.
       
 19332 Transition._TRANSFORM = 'transform';
       
 19333 
       
 19334 Transition._toCamel = function(property) {
       
 19335     property = property.replace(/-([a-z])/gi, function(m0, m1) {
       
 19336         return m1.toUpperCase();
       
 19337     });
       
 19338 
       
 19339     return property;
       
 19340 };
       
 19341 
       
 19342 Transition._toHyphen = function(property) {
       
 19343     property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
       
 19344         var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2;
       
 19345 
       
 19346         if (m3) {
       
 19347             str += '-' + m3.toLowerCase();
       
 19348         }
       
 19349 
       
 19350         return str;
       
 19351     });
       
 19352 
       
 19353     return property;
       
 19354 };
       
 19355 
       
 19356 Transition.SHOW_TRANSITION = 'fadeIn';
       
 19357 Transition.HIDE_TRANSITION = 'fadeOut';
       
 19358 
       
 19359 Transition.useNative = false;
       
 19360 
       
 19361 // Map transition properties to vendor-specific versions.
       
 19362 if ('transition' in DOCUMENT_STYLE 
       
 19363     && 'transitionProperty' in DOCUMENT_STYLE 
       
 19364     && 'transitionDuration' in DOCUMENT_STYLE
       
 19365     && 'transitionTimingFunction' in DOCUMENT_STYLE
       
 19366     && 'transitionDelay' in DOCUMENT_STYLE) {
       
 19367     Transition.useNative = true;
       
 19368     Transition.supported = true; // TODO: remove
       
 19369 } else {
       
 19370     Y.Array.each(VENDORS, function(val) { // then vendor specific
       
 19371         var property = val + 'Transition';
       
 19372         if (property in DOCUMENT[DOCUMENT_ELEMENT].style) {
       
 19373             CAMEL_VENDOR_PREFIX = val;
       
 19374             VENDOR_PREFIX       = Transition._toHyphen(val) + '-';
       
 19375 
       
 19376             Transition.useNative = true;
       
 19377             Transition.supported = true; // TODO: remove
       
 19378             Transition._VENDOR_PREFIX = val;
       
 19379         }
       
 19380     });
       
 19381 }
       
 19382 
       
 19383 // Map transform property to vendor-specific versions.
       
 19384 // One-off required for cssText injection.
       
 19385 if (typeof DOCUMENT_STYLE.transform === 'undefined') {
       
 19386     Y.Array.each(VENDORS, function(val) { // then vendor specific
       
 19387         var property = val + 'Transform';
       
 19388         if (typeof DOCUMENT_STYLE[property] !== 'undefined') {
       
 19389             Transition._TRANSFORM = property;
       
 19390         }
       
 19391     });
       
 19392 }
       
 19393 
       
 19394 if (CAMEL_VENDOR_PREFIX) {
       
 19395     TRANSITION_CAMEL          = CAMEL_VENDOR_PREFIX + 'Transition';
       
 19396     TRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty';
       
 19397 }
       
 19398 
       
 19399 TRANSITION_PROPERTY        = VENDOR_PREFIX + 'transition-property';
       
 19400 TRANSITION_DURATION        = VENDOR_PREFIX + 'transition-duration';
       
 19401 TRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function';
       
 19402 TRANSITION_DELAY           = VENDOR_PREFIX + 'transition-delay';
       
 19403 
       
 19404 TRANSITION_END    = 'transitionend';
       
 19405 ON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend';
       
 19406 TRANSITION_END    = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END;
       
 19407 
       
 19408 Transition.fx = {};
       
 19409 Transition.toggles = {};
       
 19410 
       
 19411 Transition._hasEnd = {};
       
 19412 
       
 19413 Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
       
 19414 
       
 19415 Y.Node.DOM_EVENTS[TRANSITION_END] = 1;
       
 19416 
       
 19417 Transition.NAME = 'transition';
       
 19418 
       
 19419 Transition.DEFAULT_EASING = 'ease';
       
 19420 Transition.DEFAULT_DURATION = 0.5;
       
 19421 Transition.DEFAULT_DELAY = 0;
       
 19422 
       
 19423 Transition._nodeAttrs = {};
       
 19424 
       
 19425 Transition.prototype = {
       
 19426     constructor: Transition,
       
 19427     init: function(node, config) {
       
 19428         var anim = this;
       
 19429         anim._node = node;
       
 19430         if (!anim._running && config) {
       
 19431             anim._config = config;
       
 19432             node._transition = anim; // cache for reuse
       
 19433 
       
 19434             anim._duration = ('duration' in config) ?
       
 19435                 config.duration: anim.constructor.DEFAULT_DURATION;
       
 19436 
       
 19437             anim._delay = ('delay' in config) ?
       
 19438                 config.delay: anim.constructor.DEFAULT_DELAY;
       
 19439 
       
 19440             anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
       
 19441             anim._count = 0; // track number of animated properties
       
 19442             anim._running = false;
       
 19443 
       
 19444         }
       
 19445 
       
 19446         return anim;
       
 19447     },
       
 19448 
       
 19449     addProperty: function(prop, config) {
       
 19450         var anim = this,
       
 19451             node = this._node,
       
 19452             uid = Y.stamp(node),
       
 19453             nodeInstance = Y.one(node),
       
 19454             attrs = Transition._nodeAttrs[uid],
       
 19455             computed,
       
 19456             compareVal,
       
 19457             dur,
       
 19458             attr,
       
 19459             val;
       
 19460 
       
 19461         if (!attrs) {
       
 19462             attrs = Transition._nodeAttrs[uid] = {};
       
 19463         }
       
 19464 
       
 19465         attr = attrs[prop];
       
 19466 
       
 19467         // might just be a value
       
 19468         if (config && config.value !== undefined) {
       
 19469             val = config.value;
       
 19470         } else if (config !== undefined) {
       
 19471             val = config;
       
 19472             config = EMPTY_OBJ;
       
 19473         }
       
 19474 
       
 19475         if (typeof val === 'function') {
       
 19476             val = val.call(nodeInstance, nodeInstance);
       
 19477         }
       
 19478 
       
 19479         if (attr && attr.transition) {
       
 19480             // take control if another transition owns this property
       
 19481             if (attr.transition !== anim) {
       
 19482                 attr.transition._count--; // remapping attr to this transition
       
 19483             }
       
 19484         }
       
 19485 
       
 19486         anim._count++; // properties per transition
       
 19487 
       
 19488         // make 0 async and fire events
       
 19489         dur = ((typeof config.duration !== 'undefined') ? config.duration :
       
 19490                     anim._duration) || 0.0001;
       
 19491 
       
 19492         attrs[prop] = {
       
 19493             value: val,
       
 19494             duration: dur,
       
 19495             delay: (typeof config.delay !== 'undefined') ? config.delay :
       
 19496                     anim._delay,
       
 19497 
       
 19498             easing: config.easing || anim._easing,
       
 19499 
       
 19500             transition: anim
       
 19501         };
       
 19502 
       
 19503         // native end event doesnt fire when setting to same value
       
 19504         // supplementing with timer
       
 19505         // val may be a string or number (height: 0, etc), but computedStyle is always string
       
 19506         computed = Y.DOM.getComputedStyle(node, prop);
       
 19507         compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
       
 19508 
       
 19509         if (Transition.useNative && compareVal === val) {
       
 19510             setTimeout(function() {
       
 19511                 anim._onNativeEnd.call(node, {
       
 19512                     propertyName: prop,
       
 19513                     elapsedTime: dur
       
 19514                 });
       
 19515             }, dur * 1000);
       
 19516         }
       
 19517     },
       
 19518 
       
 19519     removeProperty: function(prop) {
       
 19520         var anim = this,
       
 19521             attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
       
 19522 
       
 19523         if (attrs && attrs[prop]) {
       
 19524             delete attrs[prop];
       
 19525             anim._count--;
       
 19526         }
       
 19527 
       
 19528     },
       
 19529 
       
 19530     initAttrs: function(config) {
       
 19531         var attr,
       
 19532             node = this._node;
       
 19533 
       
 19534         if (config.transform && !config[Transition._TRANSFORM]) {
       
 19535             config[Transition._TRANSFORM] = config.transform;
       
 19536             delete config.transform; // TODO: copy
       
 19537         }
       
 19538 
       
 19539         for (attr in config) {
       
 19540             if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
       
 19541                 this.addProperty(attr, config[attr]);
       
 19542 
       
 19543                 // when size is auto or % webkit starts from zero instead of computed
       
 19544                 // (https://bugs.webkit.org/show_bug.cgi?id=16020)
       
 19545                 // TODO: selective set
       
 19546                 if (node.style[attr] === '') {
       
 19547                     Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
       
 19548                 }
       
 19549             }
       
 19550         }
       
 19551     },
       
 19552 
       
 19553     /**
       
 19554      * Starts or an animation.
       
 19555      * @method run
       
 19556      * @chainable
       
 19557      * @private
       
 19558      */
       
 19559     run: function(callback) {
       
 19560         var anim = this,
       
 19561             node = anim._node,
       
 19562             config = anim._config,
       
 19563             data = {
       
 19564                 type: 'transition:start',
       
 19565                 config: config
       
 19566             };
       
 19567 
       
 19568 
       
 19569         if (!anim._running) {
       
 19570             anim._running = true;
       
 19571 
       
 19572             if (config.on && config.on.start) {
       
 19573                 config.on.start.call(Y.one(node), data);
       
 19574             }
       
 19575 
       
 19576             anim.initAttrs(anim._config);
       
 19577 
       
 19578             anim._callback = callback;
       
 19579             anim._start();
       
 19580         }
       
 19581 
       
 19582 
       
 19583         return anim;
       
 19584     },
       
 19585 
       
 19586     _start: function() {
       
 19587         this._runNative();
       
 19588     },
       
 19589 
       
 19590     _prepDur: function(dur) {
       
 19591         dur = parseFloat(dur) * 1000;
       
 19592 
       
 19593         return dur + 'ms';
       
 19594     },
       
 19595 
       
 19596     _runNative: function() {
       
 19597         var anim = this,
       
 19598             node = anim._node,
       
 19599             uid = Y.stamp(node),
       
 19600             style = node.style,
       
 19601             computed = node.ownerDocument.defaultView.getComputedStyle(node),
       
 19602             attrs = Transition._nodeAttrs[uid],
       
 19603             cssText = '',
       
 19604             cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)],
       
 19605 
       
 19606             transitionText = TRANSITION_PROPERTY + ': ',
       
 19607             duration = TRANSITION_DURATION + ': ',
       
 19608             easing = TRANSITION_TIMING_FUNCTION + ': ',
       
 19609             delay = TRANSITION_DELAY + ': ',
       
 19610             hyphy,
       
 19611             attr,
       
 19612             name;
       
 19613 
       
 19614         // preserve existing transitions
       
 19615         if (cssTransition !== 'all') {
       
 19616             transitionText += cssTransition + ',';
       
 19617             duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ',';
       
 19618             easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ',';
       
 19619             delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ',';
       
 19620 
       
 19621         }
       
 19622 
       
 19623         // run transitions mapped to this instance
       
 19624         for (name in attrs) {
       
 19625             hyphy = Transition._toHyphen(name);
       
 19626             attr = attrs[name];
       
 19627             if ((attr = attrs[name]) && attr.transition === anim) {
       
 19628                 if (name in node.style) { // only native styles allowed
       
 19629                     duration += anim._prepDur(attr.duration) + ',';
       
 19630                     delay += anim._prepDur(attr.delay) + ',';
       
 19631                     easing += (attr.easing) + ',';
       
 19632 
       
 19633                     transitionText += hyphy + ',';
       
 19634                     cssText += hyphy + ': ' + attr.value + '; ';
       
 19635                 } else {
       
 19636                     this.removeProperty(name);
       
 19637                 }
       
 19638             }
       
 19639         }
       
 19640 
       
 19641         transitionText = transitionText.replace(/,$/, ';');
       
 19642         duration = duration.replace(/,$/, ';');
       
 19643         easing = easing.replace(/,$/, ';');
       
 19644         delay = delay.replace(/,$/, ';');
       
 19645 
       
 19646         // only one native end event per node
       
 19647         if (!Transition._hasEnd[uid]) {
       
 19648             node.addEventListener(TRANSITION_END, anim._onNativeEnd, '');
       
 19649             Transition._hasEnd[uid] = true;
       
 19650 
       
 19651         }
       
 19652 
       
 19653         style.cssText += transitionText + duration + easing + delay + cssText;
       
 19654 
       
 19655     },
       
 19656 
       
 19657     _end: function(elapsed) {
       
 19658         var anim = this,
       
 19659             node = anim._node,
       
 19660             callback = anim._callback,
       
 19661             config = anim._config,
       
 19662             data = {
       
 19663                 type: 'transition:end',
       
 19664                 config: config,
       
 19665                 elapsedTime: elapsed
       
 19666             },
       
 19667 
       
 19668             nodeInstance = Y.one(node);
       
 19669 
       
 19670         anim._running = false;
       
 19671         anim._callback = null;
       
 19672 
       
 19673         if (node) {
       
 19674             if (config.on && config.on.end) {
       
 19675                 setTimeout(function() { // IE: allow previous update to finish
       
 19676                     config.on.end.call(nodeInstance, data);
       
 19677 
       
 19678                     // nested to ensure proper fire order
       
 19679                     if (callback) {
       
 19680                         callback.call(nodeInstance, data);
       
 19681                     }
       
 19682 
       
 19683                 }, 1);
       
 19684             } else if (callback) {
       
 19685                 setTimeout(function() { // IE: allow previous update to finish
       
 19686                     callback.call(nodeInstance, data);
       
 19687                 }, 1);
       
 19688             }
       
 19689         }
       
 19690 
       
 19691     },
       
 19692 
       
 19693     _endNative: function(name) {
       
 19694         var node = this._node,
       
 19695             value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)];
       
 19696 
       
 19697         name = Transition._toHyphen(name);
       
 19698         if (typeof value === 'string') {
       
 19699             value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
       
 19700             value = value.replace(/^,|,$/, '');
       
 19701             node.style[TRANSITION_CAMEL] = value;
       
 19702         }
       
 19703     },
       
 19704 
       
 19705     _onNativeEnd: function(e) {
       
 19706         var node = this,
       
 19707             uid = Y.stamp(node),
       
 19708             event = e,//e._event,
       
 19709             name = Transition._toCamel(event.propertyName),
       
 19710             elapsed = event.elapsedTime,
       
 19711             attrs = Transition._nodeAttrs[uid],
       
 19712             attr = attrs[name],
       
 19713             anim = (attr) ? attr.transition : null,
       
 19714             data,
       
 19715             config;
       
 19716 
       
 19717         if (anim) {
       
 19718             anim.removeProperty(name);
       
 19719             anim._endNative(name);
       
 19720             config = anim._config[name];
       
 19721 
       
 19722             data = {
       
 19723                 type: 'propertyEnd',
       
 19724                 propertyName: name,
       
 19725                 elapsedTime: elapsed,
       
 19726                 config: config
       
 19727             };
       
 19728 
       
 19729             if (config && config.on && config.on.end) {
       
 19730                 config.on.end.call(Y.one(node), data);
       
 19731             }
       
 19732 
       
 19733             if (anim._count <= 0)  { // after propertyEnd fires
       
 19734                 anim._end(elapsed);
       
 19735                 node.style[TRANSITION_PROPERTY_CAMEL] = ''; // clean up style
       
 19736             }
       
 19737         }
       
 19738     },
       
 19739 
       
 19740     destroy: function() {
       
 19741         var anim = this,
       
 19742             node = anim._node;
       
 19743 
       
 19744         if (node) {
       
 19745             node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
       
 19746             anim._node = null;
       
 19747         }
       
 19748     }
       
 19749 };
       
 19750 
       
 19751 Y.Transition = Transition;
       
 19752 Y.TransitionNative = Transition; // TODO: remove
       
 19753 
       
 19754 /**
       
 19755  *   Animate one or more css properties to a given value. Requires the "transition" module.
       
 19756  *   <pre>example usage:
       
 19757  *       Y.one('#demo').transition({
       
 19758  *           duration: 1, // in seconds, default is 0.5
       
 19759  *           easing: 'ease-out', // default is 'ease'
       
 19760  *           delay: '1', // delay start for 1 second, default is 0
       
 19761  *
       
 19762  *           height: '10px',
       
 19763  *           width: '10px',
       
 19764  *
       
 19765  *           opacity: { // per property
       
 19766  *               value: 0,
       
 19767  *               duration: 2,
       
 19768  *               delay: 2,
       
 19769  *               easing: 'ease-in'
       
 19770  *           }
       
 19771  *       });
       
 19772  *   </pre>
       
 19773  *   @for Node
       
 19774  *   @method transition
       
 19775  *   @param {Object} config An object containing one or more style properties, a duration and an easing.
       
 19776  *   @param {Function} callback A function to run after the transition has completed.
       
 19777  *   @chainable
       
 19778 */
       
 19779 Y.Node.prototype.transition = function(name, config, callback) {
       
 19780     var
       
 19781         transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
       
 19782         anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
       
 19783         fxConfig,
       
 19784         prop;
       
 19785 
       
 19786     if (typeof name === 'string') { // named effect, pull config from registry
       
 19787         if (typeof config === 'function') {
       
 19788             callback = config;
       
 19789             config = null;
       
 19790         }
       
 19791 
       
 19792         fxConfig = Transition.fx[name];
       
 19793 
       
 19794         if (config && typeof config !== 'boolean') {
       
 19795             config = Y.clone(config);
       
 19796 
       
 19797             for (prop in fxConfig) {
       
 19798                 if (fxConfig.hasOwnProperty(prop)) {
       
 19799                     if (! (prop in config)) {
       
 19800                         config[prop] = fxConfig[prop];
       
 19801                     }
       
 19802                 }
       
 19803             }
       
 19804         } else {
       
 19805             config = fxConfig;
       
 19806         }
       
 19807 
       
 19808     } else { // name is a config, config is a callback or undefined
       
 19809         callback = config;
       
 19810         config = name;
       
 19811     }
       
 19812 
       
 19813     if (anim && !anim._running) {
       
 19814         anim.init(this, config);
       
 19815     } else {
       
 19816         anim = new Transition(this._node, config);
       
 19817     }
       
 19818 
       
 19819     anim.run(callback);
       
 19820     return this;
       
 19821 };
       
 19822 
       
 19823 Y.Node.prototype.show = function(name, config, callback) {
       
 19824     this._show(); // show prior to transition
       
 19825     if (name && Y.Transition) {
       
 19826         if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
       
 19827             if (typeof config === 'function') {
       
 19828                 callback = config;
       
 19829                 config = name;
       
 19830             }
       
 19831             name = Transition.SHOW_TRANSITION;
       
 19832         }
       
 19833         this.transition(name, config, callback);
       
 19834     }
       
 19835     return this;
       
 19836 };
       
 19837 
       
 19838 Y.NodeList.prototype.show = function(name, config, callback) {
       
 19839     var nodes = this._nodes,
       
 19840         i = 0,
       
 19841         node;
       
 19842 
       
 19843     while ((node = nodes[i++])) {
       
 19844         Y.one(node).show(name, config, callback);
       
 19845     }
       
 19846 
       
 19847     return this;
       
 19848 };
       
 19849 
       
 19850 
       
 19851 
       
 19852 var _wrapCallBack = function(anim, fn, callback) {
       
 19853     return function() {
       
 19854         if (fn) {
       
 19855             fn.call(anim);
       
 19856         }
       
 19857         if (callback && typeof callback === 'function') {
       
 19858             callback.apply(anim._node, arguments);
       
 19859         }
       
 19860     };
       
 19861 };
       
 19862 
       
 19863 Y.Node.prototype.hide = function(name, config, callback) {
       
 19864     if (name && Y.Transition) {
       
 19865         if (typeof config === 'function') {
       
 19866             callback = config;
       
 19867             config = null;
       
 19868         }
       
 19869 
       
 19870         callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
       
 19871         if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
       
 19872             if (typeof config === 'function') {
       
 19873                 callback = config;
       
 19874                 config = name;
       
 19875             }
       
 19876             name = Transition.HIDE_TRANSITION;
       
 19877         }
       
 19878         this.transition(name, config, callback);
       
 19879     } else {
       
 19880         this._hide();
       
 19881     }
       
 19882     return this;
       
 19883 };
       
 19884 
       
 19885 Y.NodeList.prototype.hide = function(name, config, callback) {
       
 19886     var nodes = this._nodes,
       
 19887         i = 0,
       
 19888         node;
       
 19889 
       
 19890     while ((node = nodes[i++])) {
       
 19891         Y.one(node).hide(name, config, callback);
       
 19892     }
       
 19893 
       
 19894     return this;
       
 19895 };
       
 19896 
       
 19897 /**
       
 19898  *   Animate one or more css properties to a given value. Requires the "transition" module.
       
 19899  *   <pre>example usage:
       
 19900  *       Y.all('.demo').transition({
       
 19901  *           duration: 1, // in seconds, default is 0.5
       
 19902  *           easing: 'ease-out', // default is 'ease'
       
 19903  *           delay: '1', // delay start for 1 second, default is 0
       
 19904  *
       
 19905  *           height: '10px',
       
 19906  *           width: '10px',
       
 19907  *
       
 19908  *           opacity: { // per property
       
 19909  *               value: 0,
       
 19910  *               duration: 2,
       
 19911  *               delay: 2,
       
 19912  *               easing: 'ease-in'
       
 19913  *           }
       
 19914  *       });
       
 19915  *   </pre>
       
 19916  *   @for NodeList
       
 19917  *   @method transition
       
 19918  *   @param {Object} config An object containing one or more style properties, a duration and an easing.
       
 19919  *   @param {Function} callback A function to run after the transition has completed. The callback fires
       
 19920  *       once per item in the NodeList.
       
 19921  *   @chainable
       
 19922 */
       
 19923 Y.NodeList.prototype.transition = function(config, callback) {
       
 19924     var nodes = this._nodes,
       
 19925         i = 0,
       
 19926         node;
       
 19927 
       
 19928     while ((node = nodes[i++])) {
       
 19929         Y.one(node).transition(config, callback);
       
 19930     }
       
 19931 
       
 19932     return this;
       
 19933 };
       
 19934 
       
 19935 Y.Node.prototype.toggleView = function(name, on, callback) {
       
 19936     this._toggles = this._toggles || [];
       
 19937     callback = arguments[arguments.length - 1];
       
 19938 
       
 19939     if (typeof name !== 'string') { // no transition, just toggle
       
 19940         on = name;
       
 19941         this._toggleView(on, callback); // call original _toggleView in Y.Node
       
 19942         return;
       
 19943     }
       
 19944 
       
 19945     if (typeof on === 'function') { // Ignore "on" if used for callback argument.
       
 19946         on = undefined;
       
 19947     }
       
 19948 
       
 19949     if (typeof on === 'undefined' && name in this._toggles) { // reverse current toggle
       
 19950         on = ! this._toggles[name];
       
 19951     }
       
 19952 
       
 19953     on = (on) ? 1 : 0;
       
 19954     if (on) {
       
 19955         this._show();
       
 19956     }  else {
       
 19957         callback = _wrapCallBack(this, this._hide, callback);
       
 19958     }
       
 19959 
       
 19960     this._toggles[name] = on;
       
 19961     this.transition(Y.Transition.toggles[name][on], callback);
       
 19962 
       
 19963     return this;
       
 19964 };
       
 19965 
       
 19966 Y.NodeList.prototype.toggleView = function(name, on, callback) {
       
 19967     var nodes = this._nodes,
       
 19968         i = 0,
       
 19969         node;
       
 19970 
       
 19971     while ((node = nodes[i++])) {
       
 19972         node = Y.one(node);
       
 19973         node.toggleView.apply(node, arguments);
       
 19974     }
       
 19975 
       
 19976     return this;
       
 19977 };
       
 19978 
       
 19979 Y.mix(Transition.fx, {
       
 19980     fadeOut: {
       
 19981         opacity: 0,
       
 19982         duration: 0.5,
       
 19983         easing: 'ease-out'
       
 19984     },
       
 19985 
       
 19986     fadeIn: {
       
 19987         opacity: 1,
       
 19988         duration: 0.5,
       
 19989         easing: 'ease-in'
       
 19990     },
       
 19991 
       
 19992     sizeOut: {
       
 19993         height: 0,
       
 19994         width: 0,
       
 19995         duration: 0.75,
       
 19996         easing: 'ease-out'
       
 19997     },
       
 19998 
       
 19999     sizeIn: {
       
 20000         height: function(node) {
       
 20001             return node.get('scrollHeight') + 'px';
       
 20002         },
       
 20003         width: function(node) {
       
 20004             return node.get('scrollWidth') + 'px';
       
 20005         },
       
 20006         duration: 0.5,
       
 20007         easing: 'ease-in',
       
 20008 
       
 20009         on: {
       
 20010             start: function() {
       
 20011                 var overflow = this.getStyle('overflow');
       
 20012                 if (overflow !== 'hidden') { // enable scrollHeight/Width
       
 20013                     this.setStyle('overflow', 'hidden');
       
 20014                     this._transitionOverflow = overflow;
       
 20015                 }
       
 20016             },
       
 20017 
       
 20018             end: function() {
       
 20019                 if (this._transitionOverflow) { // revert overridden value
       
 20020                     this.setStyle('overflow', this._transitionOverflow);
       
 20021                     delete this._transitionOverflow;
       
 20022                 }
       
 20023             }
       
 20024         }
       
 20025     }
       
 20026 });
       
 20027 
       
 20028 Y.mix(Transition.toggles, {
       
 20029     size: ['sizeOut', 'sizeIn'],
       
 20030     fade: ['fadeOut', 'fadeIn']
       
 20031 });
       
 20032 
       
 20033 
       
 20034 }, '@VERSION@', {"requires": ["node-style"]});
       
 20035 YUI.add('selector-css2', function (Y, NAME) {
       
 20036 
       
 20037 /**
       
 20038  * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
       
 20039  * @module dom
       
 20040  * @submodule selector-css2
       
 20041  * @for Selector
       
 20042  */
       
 20043 
       
 20044 /*
       
 20045  * Provides helper methods for collecting and filtering DOM elements.
       
 20046  */
       
 20047 
       
 20048 var PARENT_NODE = 'parentNode',
       
 20049     TAG_NAME = 'tagName',
       
 20050     ATTRIBUTES = 'attributes',
       
 20051     COMBINATOR = 'combinator',
       
 20052     PSEUDOS = 'pseudos',
       
 20053 
       
 20054     Selector = Y.Selector,
       
 20055 
       
 20056     SelectorCSS2 = {
       
 20057         _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,
       
 20058         SORT_RESULTS: true,
       
 20059 
       
 20060         // TODO: better detection, document specific
       
 20061         _isXML: (function() {
       
 20062             var isXML = (Y.config.doc.createElement('div').tagName !== 'DIV');
       
 20063             return isXML;
       
 20064         }()),
       
 20065 
       
 20066         /**
       
 20067          * Mapping of shorthand tokens to corresponding attribute selector 
       
 20068          * @property shorthand
       
 20069          * @type object
       
 20070          */
       
 20071         shorthand: {
       
 20072             '\\#(-?[_a-z0-9]+[-\\w\\uE000]*)': '[id=$1]',
       
 20073             '\\.(-?[_a-z]+[-\\w\\uE000]*)': '[className~=$1]'
       
 20074         },
       
 20075 
       
 20076         /**
       
 20077          * List of operators and corresponding boolean functions. 
       
 20078          * These functions are passed the attribute and the current node's value of the attribute.
       
 20079          * @property operators
       
 20080          * @type object
       
 20081          */
       
 20082         operators: {
       
 20083             '': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute
       
 20084             '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
       
 20085             '|=': '^{val}-?' // optional hyphen-delimited
       
 20086         },
       
 20087 
       
 20088         pseudos: {
       
 20089            'first-child': function(node) { 
       
 20090                 return Y.DOM._children(node[PARENT_NODE])[0] === node; 
       
 20091             } 
       
 20092         },
       
 20093 
       
 20094         _bruteQuery: function(selector, root, firstOnly) {
       
 20095             var ret = [],
       
 20096                 nodes = [],
       
 20097                 tokens = Selector._tokenize(selector),
       
 20098                 token = tokens[tokens.length - 1],
       
 20099                 rootDoc = Y.DOM._getDoc(root),
       
 20100                 child,
       
 20101                 id,
       
 20102                 className,
       
 20103                 tagName;
       
 20104 
       
 20105             if (token) {
       
 20106                 // prefilter nodes
       
 20107                 id = token.id;
       
 20108                 className = token.className;
       
 20109                 tagName = token.tagName || '*';
       
 20110 
       
 20111                 if (root.getElementsByTagName) { // non-IE lacks DOM api on doc frags
       
 20112                     // try ID first, unless no root.all && root not in document
       
 20113                     // (root.all works off document, but not getElementById)
       
 20114                     if (id && (root.all || (root.nodeType === 9 || Y.DOM.inDoc(root)))) {
       
 20115                         nodes = Y.DOM.allById(id, root);
       
 20116                     // try className
       
 20117                     } else if (className) {
       
 20118                         nodes = root.getElementsByClassName(className);
       
 20119                     } else { // default to tagName
       
 20120                         nodes = root.getElementsByTagName(tagName);
       
 20121                     }
       
 20122 
       
 20123                 } else { // brute getElementsByTagName()
       
 20124                     child = root.firstChild;
       
 20125                     while (child) {
       
 20126                         // only collect HTMLElements
       
 20127                         // match tag to supplement missing getElementsByTagName
       
 20128                         if (child.tagName && (tagName === '*' || child.tagName === tagName)) {
       
 20129                             nodes.push(child);
       
 20130                         }
       
 20131                         child = child.nextSibling || child.firstChild;
       
 20132                     }
       
 20133                 }
       
 20134                 if (nodes.length) {
       
 20135                     ret = Selector._filterNodes(nodes, tokens, firstOnly);
       
 20136                 }
       
 20137             }
       
 20138 
       
 20139             return ret;
       
 20140         },
       
 20141         
       
 20142         _filterNodes: function(nodes, tokens, firstOnly) {
       
 20143             var i = 0,
       
 20144                 j,
       
 20145                 len = tokens.length,
       
 20146                 n = len - 1,
       
 20147                 result = [],
       
 20148                 node = nodes[0],
       
 20149                 tmpNode = node,
       
 20150                 getters = Y.Selector.getters,
       
 20151                 operator,
       
 20152                 combinator,
       
 20153                 token,
       
 20154                 path,
       
 20155                 pass,
       
 20156                 value,
       
 20157                 tests,
       
 20158                 test;
       
 20159 
       
 20160             for (i = 0; (tmpNode = node = nodes[i++]);) {
       
 20161                 n = len - 1;
       
 20162                 path = null;
       
 20163                 
       
 20164                 testLoop:
       
 20165                 while (tmpNode && tmpNode.tagName) {
       
 20166                     token = tokens[n];
       
 20167                     tests = token.tests;
       
 20168                     j = tests.length;
       
 20169                     if (j && !pass) {
       
 20170                         while ((test = tests[--j])) {
       
 20171                             operator = test[1];
       
 20172                             if (getters[test[0]]) {
       
 20173                                 value = getters[test[0]](tmpNode, test[0]);
       
 20174                             } else {
       
 20175                                 value = tmpNode[test[0]];
       
 20176                                 if (test[0] === 'tagName' && !Selector._isXML) {
       
 20177                                     value = value.toUpperCase();    
       
 20178                                 }
       
 20179                                 if (typeof value != 'string' && value !== undefined && value.toString) {
       
 20180                                     value = value.toString(); // coerce for comparison
       
 20181                                 } else if (value === undefined && tmpNode.getAttribute) {
       
 20182                                     // use getAttribute for non-standard attributes
       
 20183                                     value = tmpNode.getAttribute(test[0], 2); // 2 === force string for IE
       
 20184                                 }
       
 20185                             }
       
 20186 
       
 20187                             if ((operator === '=' && value !== test[2]) ||  // fast path for equality
       
 20188                                 (typeof operator !== 'string' && // protect against String.test monkey-patch (Moo)
       
 20189                                 operator.test && !operator.test(value)) ||  // regex test
       
 20190                                 (!operator.test && // protect against RegExp as function (webkit)
       
 20191                                         typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // function test
       
 20192 
       
 20193                                 // skip non element nodes or non-matching tags
       
 20194                                 if ((tmpNode = tmpNode[path])) {
       
 20195                                     while (tmpNode &&
       
 20196                                         (!tmpNode.tagName ||
       
 20197                                             (token.tagName && token.tagName !== tmpNode.tagName))
       
 20198                                     ) {
       
 20199                                         tmpNode = tmpNode[path]; 
       
 20200                                     }
       
 20201                                 }
       
 20202                                 continue testLoop;
       
 20203                             }
       
 20204                         }
       
 20205                     }
       
 20206 
       
 20207                     n--; // move to next token
       
 20208                     // now that we've passed the test, move up the tree by combinator
       
 20209                     if (!pass && (combinator = token.combinator)) {
       
 20210                         path = combinator.axis;
       
 20211                         tmpNode = tmpNode[path];
       
 20212 
       
 20213                         // skip non element nodes
       
 20214                         while (tmpNode && !tmpNode.tagName) {
       
 20215                             tmpNode = tmpNode[path]; 
       
 20216                         }
       
 20217 
       
 20218                         if (combinator.direct) { // one pass only
       
 20219                             path = null; 
       
 20220                         }
       
 20221 
       
 20222                     } else { // success if we made it this far
       
 20223                         result.push(node);
       
 20224                         if (firstOnly) {
       
 20225                             return result;
       
 20226                         }
       
 20227                         break;
       
 20228                     }
       
 20229                 }
       
 20230             }
       
 20231             node = tmpNode = null;
       
 20232             return result;
       
 20233         },
       
 20234 
       
 20235         combinators: {
       
 20236             ' ': {
       
 20237                 axis: 'parentNode'
       
 20238             },
       
 20239 
       
 20240             '>': {
       
 20241                 axis: 'parentNode',
       
 20242                 direct: true
       
 20243             },
       
 20244 
       
 20245 
       
 20246             '+': {
       
 20247                 axis: 'previousSibling',
       
 20248                 direct: true
       
 20249             }
       
 20250         },
       
 20251 
       
 20252         _parsers: [
       
 20253             {
       
 20254                 name: ATTRIBUTES,
       
 20255                 re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,
       
 20256                 fn: function(match, token) {
       
 20257                     var operator = match[2] || '',
       
 20258                         operators = Selector.operators,
       
 20259                         escVal = (match[3]) ? match[3].replace(/\\/g, '') : '',
       
 20260                         test;
       
 20261 
       
 20262                     // add prefiltering for ID and CLASS
       
 20263                     if ((match[1] === 'id' && operator === '=') ||
       
 20264                             (match[1] === 'className' &&
       
 20265                             Y.config.doc.documentElement.getElementsByClassName &&
       
 20266                             (operator === '~=' || operator === '='))) {
       
 20267                         token.prefilter = match[1];
       
 20268 
       
 20269 
       
 20270                         match[3] = escVal; 
       
 20271 
       
 20272                         // escape all but ID for prefilter, which may run through QSA (via Dom.allById)
       
 20273                         token[match[1]] = (match[1] === 'id') ? match[3] : escVal;
       
 20274 
       
 20275                     }
       
 20276 
       
 20277                     // add tests
       
 20278                     if (operator in operators) {
       
 20279                         test = operators[operator];
       
 20280                         if (typeof test === 'string') {
       
 20281                             match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1');
       
 20282                             test = new RegExp(test.replace('{val}', match[3]));
       
 20283                         }
       
 20284                         match[2] = test;
       
 20285                     }
       
 20286                     if (!token.last || token.prefilter !== match[1]) {
       
 20287                         return match.slice(1);
       
 20288                     }
       
 20289                 }
       
 20290             },
       
 20291             {
       
 20292                 name: TAG_NAME,
       
 20293                 re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
       
 20294                 fn: function(match, token) {
       
 20295                     var tag = match[1];
       
 20296 
       
 20297                     if (!Selector._isXML) {
       
 20298                         tag = tag.toUpperCase();
       
 20299                     }
       
 20300 
       
 20301                     token.tagName = tag;
       
 20302 
       
 20303                     if (tag !== '*' && (!token.last || token.prefilter)) {
       
 20304                         return [TAG_NAME, '=', tag];
       
 20305                     }
       
 20306                     if (!token.prefilter) {
       
 20307                         token.prefilter = 'tagName';
       
 20308                     }
       
 20309                 }
       
 20310             },
       
 20311             {
       
 20312                 name: COMBINATOR,
       
 20313                 re: /^\s*([>+~]|\s)\s*/,
       
 20314                 fn: function(match, token) {
       
 20315                 }
       
 20316             },
       
 20317             {
       
 20318                 name: PSEUDOS,
       
 20319                 re: /^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,
       
 20320                 fn: function(match, token) {
       
 20321                     var test = Selector[PSEUDOS][match[1]];
       
 20322                     if (test) { // reorder match array and unescape special chars for tests
       
 20323                         if (match[2]) {
       
 20324                             match[2] = match[2].replace(/\\/g, '');
       
 20325                         }
       
 20326                         return [match[2], test]; 
       
 20327                     } else { // selector token not supported (possibly missing CSS3 module)
       
 20328                         return false;
       
 20329                     }
       
 20330                 }
       
 20331             }
       
 20332             ],
       
 20333 
       
 20334         _getToken: function(token) {
       
 20335             return {
       
 20336                 tagName: null,
       
 20337                 id: null,
       
 20338                 className: null,
       
 20339                 attributes: {},
       
 20340                 combinator: null,
       
 20341                 tests: []
       
 20342             };
       
 20343         },
       
 20344 
       
 20345         /*
       
 20346             Break selector into token units per simple selector.
       
 20347             Combinator is attached to the previous token.
       
 20348          */
       
 20349         _tokenize: function(selector) {
       
 20350             selector = selector || '';
       
 20351             selector = Selector._parseSelector(Y.Lang.trim(selector)); 
       
 20352             var token = Selector._getToken(),     // one token per simple selector (left selector holds combinator)
       
 20353                 query = selector, // original query for debug report
       
 20354                 tokens = [],    // array of tokens
       
 20355                 found = false,  // whether or not any matches were found this pass
       
 20356                 match,         // the regex match
       
 20357                 test,
       
 20358                 i, parser;
       
 20359 
       
 20360             /*
       
 20361                 Search for selector patterns, store, and strip them from the selector string
       
 20362                 until no patterns match (invalid selector) or we run out of chars.
       
 20363 
       
 20364                 Multiple attributes and pseudos are allowed, in any order.
       
 20365                 for example:
       
 20366                     'form:first-child[type=button]:not(button)[lang|=en]'
       
 20367             */
       
 20368             outer:
       
 20369             do {
       
 20370                 found = false; // reset after full pass
       
 20371                 for (i = 0; (parser = Selector._parsers[i++]);) {
       
 20372                     if ( (match = parser.re.exec(selector)) ) { // note assignment
       
 20373                         if (parser.name !== COMBINATOR ) {
       
 20374                             token.selector = selector;
       
 20375                         }
       
 20376                         selector = selector.replace(match[0], ''); // strip current match from selector
       
 20377                         if (!selector.length) {
       
 20378                             token.last = true;
       
 20379                         }
       
 20380 
       
 20381                         if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
       
 20382                             match[1] = Selector._attrFilters[match[1]];
       
 20383                         }
       
 20384 
       
 20385                         test = parser.fn(match, token);
       
 20386                         if (test === false) { // selector not supported
       
 20387                             found = false;
       
 20388                             break outer;
       
 20389                         } else if (test) {
       
 20390                             token.tests.push(test);
       
 20391                         }
       
 20392 
       
 20393                         if (!selector.length || parser.name === COMBINATOR) {
       
 20394                             tokens.push(token);
       
 20395                             token = Selector._getToken(token);
       
 20396                             if (parser.name === COMBINATOR) {
       
 20397                                 token.combinator = Y.Selector.combinators[match[1]];
       
 20398                             }
       
 20399                         }
       
 20400                         found = true;
       
 20401                     }
       
 20402                 }
       
 20403             } while (found && selector.length);
       
 20404 
       
 20405             if (!found || selector.length) { // not fully parsed
       
 20406                 tokens = [];
       
 20407             }
       
 20408             return tokens;
       
 20409         },
       
 20410 
       
 20411         _replaceMarkers: function(selector) {
       
 20412             selector = selector.replace(/\[/g, '\uE003');
       
 20413             selector = selector.replace(/\]/g, '\uE004');
       
 20414 
       
 20415             selector = selector.replace(/\(/g, '\uE005');
       
 20416             selector = selector.replace(/\)/g, '\uE006');
       
 20417             return selector;
       
 20418         },
       
 20419 
       
 20420         _replaceShorthand: function(selector) {
       
 20421             var shorthand = Y.Selector.shorthand,
       
 20422                 re;
       
 20423 
       
 20424             for (re in shorthand) {
       
 20425                 if (shorthand.hasOwnProperty(re)) {
       
 20426                     selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]);
       
 20427                 }
       
 20428             }
       
 20429 
       
 20430             return selector;
       
 20431         },
       
 20432 
       
 20433         _parseSelector: function(selector) {
       
 20434             var replaced = Y.Selector._replaceSelector(selector),
       
 20435                 selector = replaced.selector;
       
 20436 
       
 20437             // replace shorthand (".foo, #bar") after pseudos and attrs
       
 20438             // to avoid replacing unescaped chars
       
 20439             selector = Y.Selector._replaceShorthand(selector);
       
 20440 
       
 20441             selector = Y.Selector._restore('attr', selector, replaced.attrs);
       
 20442             selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
       
 20443 
       
 20444             // replace braces and parens before restoring escaped chars
       
 20445             // to avoid replacing ecaped markers
       
 20446             selector = Y.Selector._replaceMarkers(selector);
       
 20447             selector = Y.Selector._restore('esc', selector, replaced.esc);
       
 20448 
       
 20449             return selector;
       
 20450         },
       
 20451 
       
 20452         _attrFilters: {
       
 20453             'class': 'className',
       
 20454             'for': 'htmlFor'
       
 20455         },
       
 20456 
       
 20457         getters: {
       
 20458             href: function(node, attr) {
       
 20459                 return Y.DOM.getAttribute(node, attr);
       
 20460             },
       
 20461 
       
 20462             id: function(node, attr) {
       
 20463                 return Y.DOM.getId(node);
       
 20464             }
       
 20465         }
       
 20466     };
       
 20467 
       
 20468 Y.mix(Y.Selector, SelectorCSS2, true);
       
 20469 Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
       
 20470 
       
 20471 // IE wants class with native queries
       
 20472 if (Y.Selector.useNative && Y.config.doc.querySelector) {
       
 20473     Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
       
 20474 }
       
 20475 
       
 20476 
       
 20477 
       
 20478 }, '@VERSION@', {"requires": ["selector-native"]});
       
 20479 YUI.add('selector-css3', function (Y, NAME) {
       
 20480 
       
 20481 /**
       
 20482  * The selector css3 module provides support for css3 selectors.
       
 20483  * @module dom
       
 20484  * @submodule selector-css3
       
 20485  * @for Selector
       
 20486  */
       
 20487 
       
 20488 /*
       
 20489     an+b = get every _a_th node starting at the _b_th
       
 20490     0n+b = no repeat ("0" and "n" may both be omitted (together) , e.g. "0n+1" or "1", not "0+1"), return only the _b_th element
       
 20491     1n+b =  get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
       
 20492     an+0 = get every _a_th element, "0" may be omitted 
       
 20493 */
       
 20494 
       
 20495 Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
       
 20496 
       
 20497 Y.Selector._getNth = function(node, expr, tag, reverse) {
       
 20498     Y.Selector._reNth.test(expr);
       
 20499     var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
       
 20500         n = RegExp.$2, // "n"
       
 20501         oddeven = RegExp.$3, // "odd" or "even"
       
 20502         b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
       
 20503         result = [],
       
 20504         siblings = Y.DOM._children(node.parentNode, tag),
       
 20505         op;
       
 20506 
       
 20507     if (oddeven) {
       
 20508         a = 2; // always every other
       
 20509         op = '+';
       
 20510         n = 'n';
       
 20511         b = (oddeven === 'odd') ? 1 : 0;
       
 20512     } else if ( isNaN(a) ) {
       
 20513         a = (n) ? 1 : 0; // start from the first or no repeat
       
 20514     }
       
 20515 
       
 20516     if (a === 0) { // just the first
       
 20517         if (reverse) {
       
 20518             b = siblings.length - b + 1; 
       
 20519         }
       
 20520 
       
 20521         if (siblings[b - 1] === node) {
       
 20522             return true;
       
 20523         } else {
       
 20524             return false;
       
 20525         }
       
 20526 
       
 20527     } else if (a < 0) {
       
 20528         reverse = !!reverse;
       
 20529         a = Math.abs(a);
       
 20530     }
       
 20531 
       
 20532     if (!reverse) {
       
 20533         for (var i = b - 1, len = siblings.length; i < len; i += a) {
       
 20534             if ( i >= 0 && siblings[i] === node ) {
       
 20535                 return true;
       
 20536             }
       
 20537         }
       
 20538     } else {
       
 20539         for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
       
 20540             if ( i < len && siblings[i] === node ) {
       
 20541                 return true;
       
 20542             }
       
 20543         }
       
 20544     }
       
 20545     return false;
       
 20546 };
       
 20547 
       
 20548 Y.mix(Y.Selector.pseudos, {
       
 20549     'root': function(node) {
       
 20550         return node === node.ownerDocument.documentElement;
       
 20551     },
       
 20552 
       
 20553     'nth-child': function(node, expr) {
       
 20554         return Y.Selector._getNth(node, expr);
       
 20555     },
       
 20556 
       
 20557     'nth-last-child': function(node, expr) {
       
 20558         return Y.Selector._getNth(node, expr, null, true);
       
 20559     },
       
 20560 
       
 20561     'nth-of-type': function(node, expr) {
       
 20562         return Y.Selector._getNth(node, expr, node.tagName);
       
 20563     },
       
 20564      
       
 20565     'nth-last-of-type': function(node, expr) {
       
 20566         return Y.Selector._getNth(node, expr, node.tagName, true);
       
 20567     },
       
 20568      
       
 20569     'last-child': function(node) {
       
 20570         var children = Y.DOM._children(node.parentNode);
       
 20571         return children[children.length - 1] === node;
       
 20572     },
       
 20573 
       
 20574     'first-of-type': function(node) {
       
 20575         return Y.DOM._children(node.parentNode, node.tagName)[0] === node;
       
 20576     },
       
 20577      
       
 20578     'last-of-type': function(node) {
       
 20579         var children = Y.DOM._children(node.parentNode, node.tagName);
       
 20580         return children[children.length - 1] === node;
       
 20581     },
       
 20582      
       
 20583     'only-child': function(node) {
       
 20584         var children = Y.DOM._children(node.parentNode);
       
 20585         return children.length === 1 && children[0] === node;
       
 20586     },
       
 20587 
       
 20588     'only-of-type': function(node) {
       
 20589         var children = Y.DOM._children(node.parentNode, node.tagName);
       
 20590         return children.length === 1 && children[0] === node;
       
 20591     },
       
 20592 
       
 20593     'empty': function(node) {
       
 20594         return node.childNodes.length === 0;
       
 20595     },
       
 20596 
       
 20597     'not': function(node, expr) {
       
 20598         return !Y.Selector.test(node, expr);
       
 20599     },
       
 20600 
       
 20601     'contains': function(node, expr) {
       
 20602         var text = node.innerText || node.textContent || '';
       
 20603         return text.indexOf(expr) > -1;
       
 20604     },
       
 20605 
       
 20606     'checked': function(node) {
       
 20607         return (node.checked === true || node.selected === true);
       
 20608     },
       
 20609 
       
 20610     enabled: function(node) {
       
 20611         return (node.disabled !== undefined && !node.disabled);
       
 20612     },
       
 20613 
       
 20614     disabled: function(node) {
       
 20615         return (node.disabled);
       
 20616     }
       
 20617 });
       
 20618 
       
 20619 Y.mix(Y.Selector.operators, {
       
 20620     '^=': '^{val}', // Match starts with value
       
 20621     '$=': '{val}$', // Match ends with value
       
 20622     '*=': '{val}' // Match contains value as substring 
       
 20623 });
       
 20624 
       
 20625 Y.Selector.combinators['~'] = {
       
 20626     axis: 'previousSibling'
       
 20627 };
       
 20628 
       
 20629 
       
 20630 }, '@VERSION@', {"requires": ["selector-native", "selector-css2"]});
       
 20631 YUI.add('yui-log', function (Y, NAME) {
       
 20632 
       
 20633 /**
       
 20634  * Provides console log capability and exposes a custom event for
       
 20635  * console implementations. This module is a `core` YUI module,
       
 20636  * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
       
 20637  *
       
 20638  * @module yui
       
 20639  * @submodule yui-log
       
 20640  */
       
 20641 
       
 20642 var INSTANCE = Y,
       
 20643     LOGEVENT = 'yui:log',
       
 20644     UNDEFINED = 'undefined',
       
 20645     LEVELS = { debug: 1,
       
 20646                info: 2,
       
 20647                warn: 4,
       
 20648                error: 8 };
       
 20649 
       
 20650 /**
       
 20651  * If the 'debug' config is true, a 'yui:log' event will be
       
 20652  * dispatched, which the Console widget and anything else
       
 20653  * can consume.  If the 'useBrowserConsole' config is true, it will
       
 20654  * write to the browser console if available.  YUI-specific log
       
 20655  * messages will only be present in the -debug versions of the
       
 20656  * JS files.  The build system is supposed to remove log statements
       
 20657  * from the raw and minified versions of the files.
       
 20658  *
       
 20659  * @method log
       
 20660  * @for YUI
       
 20661  * @param  {String}  msg  The message to log.
       
 20662  * @param  {String}  cat  The log category for the message.  Default
       
 20663  *                        categories are "info", "warn", "error", time".
       
 20664  *                        Custom categories can be used as well. (opt).
       
 20665  * @param  {String}  src  The source of the the message (opt).
       
 20666  * @param  {boolean} silent If true, the log event won't fire.
       
 20667  * @return {YUI}      YUI instance.
       
 20668  */
       
 20669 INSTANCE.log = function(msg, cat, src, silent) {
       
 20670     var bail, excl, incl, m, f, minlevel,
       
 20671         Y = INSTANCE,
       
 20672         c = Y.config,
       
 20673         publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
       
 20674     // suppress log message if the config is off or the event stack
       
 20675     // or the event call stack contains a consumer of the yui:log event
       
 20676     if (c.debug) {
       
 20677         // apply source filters
       
 20678         src = src || "";
       
 20679         if (typeof src !== "undefined") {
       
 20680             excl = c.logExclude;
       
 20681             incl = c.logInclude;
       
 20682             if (incl && !(src in incl)) {
       
 20683                 bail = 1;
       
 20684             } else if (incl && (src in incl)) {
       
 20685                 bail = !incl[src];
       
 20686             } else if (excl && (src in excl)) {
       
 20687                 bail = excl[src];
       
 20688             }
       
 20689 
       
 20690             // Determine the current minlevel as defined in configuration
       
 20691             Y.config.logLevel = Y.config.logLevel || 'debug';
       
 20692             minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
       
 20693 
       
 20694             if (cat in LEVELS && LEVELS[cat] < minlevel) {
       
 20695                 // Skip this message if the we don't meet the defined minlevel
       
 20696                 bail = 1;
       
 20697             }
       
 20698         }
       
 20699         if (!bail) {
       
 20700             if (c.useBrowserConsole) {
       
 20701                 m = (src) ? src + ': ' + msg : msg;
       
 20702                 if (Y.Lang.isFunction(c.logFn)) {
       
 20703                     c.logFn.call(Y, msg, cat, src);
       
 20704                 } else if (typeof console !== UNDEFINED && console.log) {
       
 20705                     f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
       
 20706                     console[f](m);
       
 20707                 } else if (typeof opera !== UNDEFINED) {
       
 20708                     opera.postError(m);
       
 20709                 }
       
 20710             }
       
 20711 
       
 20712             if (publisher && !silent) {
       
 20713 
       
 20714                 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
       
 20715                     publisher.publish(LOGEVENT, {
       
 20716                         broadcast: 2
       
 20717                     });
       
 20718                 }
       
 20719 
       
 20720                 publisher.fire(LOGEVENT, {
       
 20721                     msg: msg,
       
 20722                     cat: cat,
       
 20723                     src: src
       
 20724                 });
       
 20725             }
       
 20726         }
       
 20727     }
       
 20728 
       
 20729     return Y;
       
 20730 };
       
 20731 
       
 20732 /**
       
 20733  * Write a system message.  This message will be preserved in the
       
 20734  * minified and raw versions of the YUI files, unlike log statements.
       
 20735  * @method message
       
 20736  * @for YUI
       
 20737  * @param  {String}  msg  The message to log.
       
 20738  * @param  {String}  cat  The log category for the message.  Default
       
 20739  *                        categories are "info", "warn", "error", time".
       
 20740  *                        Custom categories can be used as well. (opt).
       
 20741  * @param  {String}  src  The source of the the message (opt).
       
 20742  * @param  {boolean} silent If true, the log event won't fire.
       
 20743  * @return {YUI}      YUI instance.
       
 20744  */
       
 20745 INSTANCE.message = function() {
       
 20746     return INSTANCE.log.apply(INSTANCE, arguments);
       
 20747 };
       
 20748 
       
 20749 
       
 20750 }, '@VERSION@', {"requires": ["yui-base"]});
       
 20751 YUI.add('dump', function (Y, NAME) {
       
 20752 
       
 20753 /**
       
 20754  * Returns a simple string representation of the object or array.
       
 20755  * Other types of objects will be returned unprocessed.  Arrays
       
 20756  * are expected to be indexed.  Use object notation for
       
 20757  * associative arrays.
       
 20758  *
       
 20759  * If included, the dump method is added to the YUI instance.
       
 20760  *
       
 20761  * @module dump
       
 20762  */
       
 20763 
       
 20764     var L = Y.Lang,
       
 20765         OBJ = '{...}',
       
 20766         FUN = 'f(){...}',
       
 20767         COMMA = ', ',
       
 20768         ARROW = ' => ',
       
 20769 
       
 20770     /**
       
 20771      * Returns a simple string representation of the object or array.
       
 20772      * Other types of objects will be returned unprocessed.  Arrays
       
 20773      * are expected to be indexed.
       
 20774      *
       
 20775      * @method dump
       
 20776      * @param {Object} o The object to dump.
       
 20777      * @param {Number} d How deep to recurse child objects, default 3.
       
 20778      * @return {String} the dump result.
       
 20779      * @for YUI
       
 20780      */
       
 20781     dump = function(o, d) {
       
 20782         var i, len, s = [], type = L.type(o);
       
 20783 
       
 20784         // Cast non-objects to string
       
 20785         // Skip dates because the std toString is what we want
       
 20786         // Skip HTMLElement-like objects because trying to dump
       
 20787         // an element will cause an unhandled exception in FF 2.x
       
 20788         if (!L.isObject(o)) {
       
 20789             return o + '';
       
 20790         } else if (type == 'date') {
       
 20791             return o;
       
 20792         } else if (o.nodeType && o.tagName) {
       
 20793             return o.tagName + '#' + o.id;
       
 20794         } else if (o.document && o.navigator) {
       
 20795             return 'window';
       
 20796         } else if (o.location && o.body) {
       
 20797             return 'document';
       
 20798         } else if (type == 'function') {
       
 20799             return FUN;
       
 20800         }
       
 20801 
       
 20802         // dig into child objects the depth specifed. Default 3
       
 20803         d = (L.isNumber(d)) ? d : 3;
       
 20804 
       
 20805         // arrays [1, 2, 3]
       
 20806         if (type == 'array') {
       
 20807             s.push('[');
       
 20808             for (i = 0, len = o.length; i < len; i = i + 1) {
       
 20809                 if (L.isObject(o[i])) {
       
 20810                     s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
       
 20811                 } else {
       
 20812                     s.push(o[i]);
       
 20813                 }
       
 20814                 s.push(COMMA);
       
 20815             }
       
 20816             if (s.length > 1) {
       
 20817                 s.pop();
       
 20818             }
       
 20819             s.push(']');
       
 20820         // regexp /foo/
       
 20821         } else if (type == 'regexp') {
       
 20822             s.push(o.toString());
       
 20823         // objects {k1 => v1, k2 => v2}
       
 20824         } else {
       
 20825             s.push('{');
       
 20826             for (i in o) {
       
 20827                 if (o.hasOwnProperty(i)) {
       
 20828                     try {
       
 20829                         s.push(i + ARROW);
       
 20830                         if (L.isObject(o[i])) {
       
 20831                             s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
       
 20832                         } else {
       
 20833                             s.push(o[i]);
       
 20834                         }
       
 20835                         s.push(COMMA);
       
 20836                     } catch (e) {
       
 20837                         s.push('Error: ' + e.message);
       
 20838                     }
       
 20839                 }
       
 20840             }
       
 20841             if (s.length > 1) {
       
 20842                 s.pop();
       
 20843             }
       
 20844             s.push('}');
       
 20845         }
       
 20846 
       
 20847         return s.join('');
       
 20848     };
       
 20849 
       
 20850     Y.dump = dump;
       
 20851     L.dump = dump;
       
 20852 
       
 20853 
       
 20854 
       
 20855 }, '@VERSION@', {"requires": ["yui-base"]});
       
 20856 YUI.add('transition-timer', function (Y, NAME) {
       
 20857 
       
 20858 /**
       
 20859 * Provides the base Transition class, for animating numeric properties.
       
 20860 *
       
 20861 * @module transition
       
 20862 * @submodule transition-timer
       
 20863 */
       
 20864 
       
 20865 
       
 20866 var Transition = Y.Transition;
       
 20867 
       
 20868 Y.mix(Transition.prototype, {
       
 20869     _start: function() {
       
 20870         if (Transition.useNative) {
       
 20871             this._runNative();
       
 20872         } else {
       
 20873             this._runTimer();
       
 20874         }
       
 20875     },
       
 20876 
       
 20877     _runTimer: function() {
       
 20878         var anim = this;
       
 20879         anim._initAttrs();
       
 20880 
       
 20881         Transition._running[Y.stamp(anim)] = anim;
       
 20882         anim._startTime = new Date();
       
 20883         Transition._startTimer();
       
 20884     },
       
 20885 
       
 20886     _endTimer: function() {
       
 20887         var anim = this;
       
 20888         delete Transition._running[Y.stamp(anim)];
       
 20889         anim._startTime = null;
       
 20890     },
       
 20891 
       
 20892     _runFrame: function() {
       
 20893         var t = new Date() - this._startTime;
       
 20894         this._runAttrs(t);
       
 20895     },
       
 20896 
       
 20897     _runAttrs: function(time) {
       
 20898         var anim = this,
       
 20899             node = anim._node,
       
 20900             config = anim._config,
       
 20901             uid = Y.stamp(node),
       
 20902             attrs = Transition._nodeAttrs[uid],
       
 20903             customAttr = Transition.behaviors,
       
 20904             done = false,
       
 20905             allDone = false,
       
 20906             data,
       
 20907             name,
       
 20908             attribute,
       
 20909             setter,
       
 20910             elapsed,
       
 20911             delay,
       
 20912             d,
       
 20913             t,
       
 20914             i;
       
 20915 
       
 20916         for (name in attrs) {
       
 20917             if ((attribute = attrs[name]) && attribute.transition === anim) {
       
 20918                 d = attribute.duration;
       
 20919                 delay = attribute.delay;
       
 20920                 elapsed = (time - delay) / 1000;
       
 20921                 t = time;
       
 20922                 data = {
       
 20923                     type: 'propertyEnd',
       
 20924                     propertyName: name,
       
 20925                     config: config,
       
 20926                     elapsedTime: elapsed
       
 20927                 };
       
 20928 
       
 20929                 setter = (i in customAttr && 'set' in customAttr[i]) ?
       
 20930                         customAttr[i].set : Transition.DEFAULT_SETTER;
       
 20931 
       
 20932                 done = (t >= d);
       
 20933 
       
 20934                 if (t > d) {
       
 20935                     t = d;
       
 20936                 }
       
 20937 
       
 20938                 if (!delay || time >= delay) {
       
 20939                     setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
       
 20940                         attribute.easing, attribute.unit);
       
 20941 
       
 20942                     if (done) {
       
 20943                         delete attrs[name];
       
 20944                         anim._count--;
       
 20945 
       
 20946                         if (config[name] && config[name].on && config[name].on.end) {
       
 20947                             config[name].on.end.call(Y.one(node), data);
       
 20948                         }
       
 20949 
       
 20950                         //node.fire('transition:propertyEnd', data);
       
 20951 
       
 20952                         if (!allDone && anim._count <= 0) {
       
 20953                             allDone = true;
       
 20954                             anim._end(elapsed);
       
 20955                             anim._endTimer();
       
 20956                         }
       
 20957                     }
       
 20958                 }
       
 20959 
       
 20960             }
       
 20961         }
       
 20962     },
       
 20963 
       
 20964     _initAttrs: function() {
       
 20965         var anim = this,
       
 20966             customAttr = Transition.behaviors,
       
 20967             uid = Y.stamp(anim._node),
       
 20968             attrs = Transition._nodeAttrs[uid],
       
 20969             attribute,
       
 20970             duration,
       
 20971             delay,
       
 20972             easing,
       
 20973             val,
       
 20974             name,
       
 20975             mTo,
       
 20976             mFrom,
       
 20977             unit, begin, end;
       
 20978 
       
 20979         for (name in attrs) {
       
 20980             if ((attribute = attrs[name]) && attribute.transition === anim) {
       
 20981                 duration = attribute.duration * 1000;
       
 20982                 delay = attribute.delay * 1000;
       
 20983                 easing = attribute.easing;
       
 20984                 val = attribute.value;
       
 20985 
       
 20986                 // only allow supported properties
       
 20987                 if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
       
 20988                     begin = (name in customAttr && 'get' in customAttr[name])  ?
       
 20989                             customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
       
 20990 
       
 20991                     mFrom = Transition.RE_UNITS.exec(begin);
       
 20992                     mTo = Transition.RE_UNITS.exec(val);
       
 20993 
       
 20994                     begin = mFrom ? mFrom[1] : begin;
       
 20995                     end = mTo ? mTo[1] : val;
       
 20996                     unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
       
 20997 
       
 20998                     if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
       
 20999                         unit = Transition.DEFAULT_UNIT;
       
 21000                     }
       
 21001 
       
 21002                     if (typeof easing === 'string') {
       
 21003                         if (easing.indexOf('cubic-bezier') > -1) {
       
 21004                             easing = easing.substring(13, easing.length - 1).split(',');
       
 21005                         } else if (Transition.easings[easing]) {
       
 21006                             easing = Transition.easings[easing];
       
 21007                         }
       
 21008                     }
       
 21009 
       
 21010                     attribute.from = Number(begin);
       
 21011                     attribute.to = Number(end);
       
 21012                     attribute.unit = unit;
       
 21013                     attribute.easing = easing;
       
 21014                     attribute.duration = duration + delay;
       
 21015                     attribute.delay = delay;
       
 21016                 } else {
       
 21017                     delete attrs[name];
       
 21018                     anim._count--;
       
 21019                 }
       
 21020             }
       
 21021         }
       
 21022     },
       
 21023 
       
 21024     destroy: function() {
       
 21025         this.detachAll();
       
 21026         this._node = null;
       
 21027     }
       
 21028 }, true);
       
 21029 
       
 21030 Y.mix(Y.Transition, {
       
 21031     _runtimeAttrs: {},
       
 21032     /*
       
 21033      * Regex of properties that should use the default unit.
       
 21034      *
       
 21035      * @property RE_DEFAULT_UNIT
       
 21036      * @static
       
 21037      */
       
 21038     RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
       
 21039 
       
 21040     /*
       
 21041      * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
       
 21042      *
       
 21043      * @property DEFAULT_UNIT
       
 21044      * @static
       
 21045      */
       
 21046     DEFAULT_UNIT: 'px',
       
 21047 
       
 21048     /*
       
 21049      * Time in milliseconds passed to setInterval for frame processing
       
 21050      *
       
 21051      * @property intervalTime
       
 21052      * @default 20
       
 21053      * @static
       
 21054      */
       
 21055     intervalTime: 20,
       
 21056 
       
 21057     /*
       
 21058      * Bucket for custom getters and setters
       
 21059      *
       
 21060      * @property behaviors
       
 21061      * @static
       
 21062      */
       
 21063     behaviors: {
       
 21064         left: {
       
 21065             get: function(anim, attr) {
       
 21066                 return Y.DOM._getAttrOffset(anim._node, attr);
       
 21067             }
       
 21068         }
       
 21069     },
       
 21070 
       
 21071     /*
       
 21072      * The default setter to use when setting object properties.
       
 21073      *
       
 21074      * @property DEFAULT_SETTER
       
 21075      * @static
       
 21076      */
       
 21077     DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
       
 21078         from = Number(from);
       
 21079         to = Number(to);
       
 21080 
       
 21081         var node = anim._node,
       
 21082             val = Transition.cubicBezier(fn, elapsed / duration);
       
 21083 
       
 21084         val = from + val[0] * (to - from);
       
 21085 
       
 21086         if (node) {
       
 21087             if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
       
 21088                 unit = unit || '';
       
 21089                 Y.DOM.setStyle(node, att, val + unit);
       
 21090             }
       
 21091         } else {
       
 21092             anim._end();
       
 21093         }
       
 21094     },
       
 21095 
       
 21096     /*
       
 21097      * The default getter to use when getting object properties.
       
 21098      *
       
 21099      * @property DEFAULT_GETTER
       
 21100      * @static
       
 21101      */
       
 21102     DEFAULT_GETTER: function(anim, att) {
       
 21103         var node = anim._node,
       
 21104             val = '';
       
 21105 
       
 21106         if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
       
 21107             val = Y.DOM.getComputedStyle(node, att);
       
 21108         }
       
 21109 
       
 21110         return val;
       
 21111     },
       
 21112 
       
 21113     _startTimer: function() {
       
 21114         if (!Transition._timer) {
       
 21115             Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
       
 21116         }
       
 21117     },
       
 21118 
       
 21119     _stopTimer: function() {
       
 21120         clearInterval(Transition._timer);
       
 21121         Transition._timer = null;
       
 21122     },
       
 21123 
       
 21124     /*
       
 21125      * Called per Interval to handle each animation frame.
       
 21126      * @method _runFrame
       
 21127      * @private
       
 21128      * @static
       
 21129      */
       
 21130     _runFrame: function() {
       
 21131         var done = true,
       
 21132             anim;
       
 21133         for (anim in Transition._running) {
       
 21134             if (Transition._running[anim]._runFrame) {
       
 21135                 done = false;
       
 21136                 Transition._running[anim]._runFrame();
       
 21137             }
       
 21138         }
       
 21139 
       
 21140         if (done) {
       
 21141             Transition._stopTimer();
       
 21142         }
       
 21143     },
       
 21144 
       
 21145     cubicBezier: function(p, t) {
       
 21146         var x0 = 0,
       
 21147             y0 = 0,
       
 21148             x1 = p[0],
       
 21149             y1 = p[1],
       
 21150             x2 = p[2],
       
 21151             y2 = p[3],
       
 21152             x3 = 1,
       
 21153             y3 = 0,
       
 21154 
       
 21155             A = x3 - 3 * x2 + 3 * x1 - x0,
       
 21156             B = 3 * x2 - 6 * x1 + 3 * x0,
       
 21157             C = 3 * x1 - 3 * x0,
       
 21158             D = x0,
       
 21159             E = y3 - 3 * y2 + 3 * y1 - y0,
       
 21160             F = 3 * y2 - 6 * y1 + 3 * y0,
       
 21161             G = 3 * y1 - 3 * y0,
       
 21162             H = y0,
       
 21163 
       
 21164             x = (((A*t) + B)*t + C)*t + D,
       
 21165             y = (((E*t) + F)*t + G)*t + H;
       
 21166 
       
 21167         return [x, y];
       
 21168     },
       
 21169 
       
 21170     easings: {
       
 21171         ease: [0.25, 0, 1, 0.25],
       
 21172         linear: [0, 0, 1, 1],
       
 21173         'ease-in': [0.42, 0, 1, 1],
       
 21174         'ease-out': [0, 0, 0.58, 1],
       
 21175         'ease-in-out': [0.42, 0, 0.58, 1]
       
 21176     },
       
 21177 
       
 21178     _running: {},
       
 21179     _timer: null,
       
 21180 
       
 21181     RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
       
 21182 }, true);
       
 21183 
       
 21184 Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
       
 21185 
       
 21186 Y.Transition = Transition;
       
 21187 
       
 21188 
       
 21189 }, '@VERSION@', {"requires": ["transition"]});
       
 21190 YUI.add('yui', function (Y, NAME) {
       
 21191 
       
 21192 // empty
       
 21193 
       
 21194 
       
 21195 
       
 21196 }, '@VERSION@', {
       
 21197     "use": [
       
 21198         "yui",
       
 21199         "oop",
       
 21200         "dom",
       
 21201         "event-custom-base",
       
 21202         "event-base",
       
 21203         "pluginhost",
       
 21204         "node",
       
 21205         "event-delegate",
       
 21206         "io-base",
       
 21207         "json-parse",
       
 21208         "transition",
       
 21209         "selector-css3",
       
 21210         "dom-style-ie",
       
 21211         "querystring-stringify-simple"
       
 21212     ]
       
 21213 });
       
 21214 var Y = YUI().use('*');