src/cm/media/js/lib/yui/yui_3.10.3/build/simpleyui/simpleyui-debug.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         // Y.log(Y.id + ' initialized', 'info', 'yui');
       
   536     },
       
   537 
       
   538     /**
       
   539     Executes the named method on the specified YUI instance if that method is
       
   540     whitelisted.
       
   541 
       
   542     @method applyTo
       
   543     @param {String} id YUI instance id.
       
   544     @param {String} method Name of the method to execute. For example:
       
   545         'Object.keys'.
       
   546     @param {Array} args Arguments to apply to the method.
       
   547     @return {Mixed} Return value from the applied method, or `null` if the
       
   548         specified instance was not found or the method was not whitelisted.
       
   549     **/
       
   550     applyTo: function(id, method, args) {
       
   551         if (!(method in APPLY_TO_AUTH)) {
       
   552             this.log(method + ': applyTo not allowed', 'warn', 'yui');
       
   553             return null;
       
   554         }
       
   555 
       
   556         var instance = instances[id], nest, m, i;
       
   557         if (instance) {
       
   558             nest = method.split('.');
       
   559             m = instance;
       
   560             for (i = 0; i < nest.length; i = i + 1) {
       
   561                 m = m[nest[i]];
       
   562                 if (!m) {
       
   563                     this.log('applyTo not found: ' + method, 'warn', 'yui');
       
   564                 }
       
   565             }
       
   566             return m && m.apply(instance, args);
       
   567         }
       
   568 
       
   569         return null;
       
   570     },
       
   571 
       
   572 /**
       
   573 Registers a YUI module and makes it available for use in a `YUI().use()` call or
       
   574 as a dependency for other modules.
       
   575 
       
   576 The easiest way to create a first-class YUI module is to use
       
   577 <a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
       
   578 tool.
       
   579 
       
   580 Shifter will automatically wrap your module code in a `YUI.add()` call along
       
   581 with any configuration info required for the module.
       
   582 
       
   583 @example
       
   584 
       
   585     YUI.add('davglass', function (Y) {
       
   586         Y.davglass = function () {
       
   587             Y.log('Dav was here!');
       
   588         };
       
   589     }, '3.4.0', {
       
   590         requires: ['harley-davidson', 'mt-dew']
       
   591     });
       
   592 
       
   593 @method add
       
   594 @param {String} name Module name.
       
   595 @param {Function} fn Function containing module code. This function will be
       
   596     executed whenever the module is attached to a specific YUI instance.
       
   597 
       
   598     @param {YUI} fn.Y The YUI instance to which this module is attached.
       
   599     @param {String} fn.name Name of the module
       
   600 
       
   601 @param {String} version Module version number. This is currently used only for
       
   602     informational purposes, and is not used internally by YUI.
       
   603 
       
   604 @param {Object} [config] Module config.
       
   605     @param {Array} [config.requires] Array of other module names that must be
       
   606         attached before this module can be attached.
       
   607     @param {Array} [config.optional] Array of optional module names that should
       
   608         be attached before this module is attached if they've already been
       
   609         loaded. If the `loadOptional` YUI option is `true`, optional modules
       
   610         that have not yet been loaded will be loaded just as if they were hard
       
   611         requirements.
       
   612     @param {Array} [config.use] Array of module names that are included within
       
   613         or otherwise provided by this module, and which should be attached
       
   614         automatically when this module is attached. This makes it possible to
       
   615         create "virtual rollup" modules that simply attach a collection of other
       
   616         modules or submodules.
       
   617 
       
   618 @return {YUI} This YUI instance.
       
   619 **/
       
   620     add: function(name, fn, version, details) {
       
   621         details = details || {};
       
   622         var env = YUI.Env,
       
   623             mod = {
       
   624                 name: name,
       
   625                 fn: fn,
       
   626                 version: version,
       
   627                 details: details
       
   628             },
       
   629             //Instance hash so we don't apply it to the same instance twice
       
   630             applied = {},
       
   631             loader, inst,
       
   632             i, versions = env.versions;
       
   633 
       
   634         env.mods[name] = mod;
       
   635         versions[version] = versions[version] || {};
       
   636         versions[version][name] = mod;
       
   637 
       
   638         for (i in instances) {
       
   639             if (instances.hasOwnProperty(i)) {
       
   640                 inst = instances[i];
       
   641                 if (!applied[inst.id]) {
       
   642                     applied[inst.id] = true;
       
   643                     loader = inst.Env._loader;
       
   644                     if (loader) {
       
   645                         if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
       
   646                             loader.addModule(details, name);
       
   647                         }
       
   648                     }
       
   649                 }
       
   650             }
       
   651         }
       
   652 
       
   653         return this;
       
   654     },
       
   655 
       
   656     /**
       
   657     Executes the callback function associated with each required module,
       
   658     attaching the module to this YUI instance.
       
   659 
       
   660     @method _attach
       
   661     @param {Array} r The array of modules to attach
       
   662     @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
       
   663         is not attached.
       
   664     @private
       
   665     **/
       
   666     _attach: function(r, moot) {
       
   667         var i, name, mod, details, req, use, after,
       
   668             mods = YUI.Env.mods,
       
   669             aliases = YUI.Env.aliases,
       
   670             Y = this, j,
       
   671             cache = YUI.Env._renderedMods,
       
   672             loader = Y.Env._loader,
       
   673             done = Y.Env._attached,
       
   674             len = r.length, loader, def, go,
       
   675             c = [];
       
   676 
       
   677         //Check for conditional modules (in a second+ instance) and add their requirements
       
   678         //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
       
   679         for (i = 0; i < len; i++) {
       
   680             name = r[i];
       
   681             mod = mods[name];
       
   682             c.push(name);
       
   683             if (loader && loader.conditions[name]) {
       
   684                 for (j in loader.conditions[name]) {
       
   685                     if (loader.conditions[name].hasOwnProperty(j)) {
       
   686                         def = loader.conditions[name][j];
       
   687                         go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
       
   688                         if (go) {
       
   689                             c.push(def.name);
       
   690                         }
       
   691                     }
       
   692                 }
       
   693             }
       
   694         }
       
   695         r = c;
       
   696         len = r.length;
       
   697 
       
   698         for (i = 0; i < len; i++) {
       
   699             if (!done[r[i]]) {
       
   700                 name = r[i];
       
   701                 mod = mods[name];
       
   702 
       
   703                 if (aliases && aliases[name] && !mod) {
       
   704                     Y._attach(aliases[name]);
       
   705                     continue;
       
   706                 }
       
   707                 if (!mod) {
       
   708                     if (loader && loader.moduleInfo[name]) {
       
   709                         mod = loader.moduleInfo[name];
       
   710                         moot = true;
       
   711                     }
       
   712 
       
   713                     // Y.log('no js def for: ' + name, 'info', 'yui');
       
   714 
       
   715                     //if (!loader || !loader.moduleInfo[name]) {
       
   716                     //if ((!loader || !loader.moduleInfo[name]) && !moot) {
       
   717                     if (!moot && name) {
       
   718                         if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
       
   719                             Y.Env._missed.push(name);
       
   720                             Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
       
   721                             Y.message('NOT loaded: ' + name, 'warn', 'yui');
       
   722                         }
       
   723                     }
       
   724                 } else {
       
   725                     done[name] = true;
       
   726                     //Don't like this, but in case a mod was asked for once, then we fetch it
       
   727                     //We need to remove it from the missed list ^davglass
       
   728                     for (j = 0; j < Y.Env._missed.length; j++) {
       
   729                         if (Y.Env._missed[j] === name) {
       
   730                             Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
       
   731                             Y.Env._missed.splice(j, 1);
       
   732                         }
       
   733                     }
       
   734                     /*
       
   735                         If it's a temp module, we need to redo it's requirements if it's already loaded
       
   736                         since it may have been loaded by another instance and it's dependencies might
       
   737                         have been redefined inside the fetched file.
       
   738                     */
       
   739                     if (loader && cache && cache[name] && cache[name].temp) {
       
   740                         loader.getRequires(cache[name]);
       
   741                         req = [];
       
   742                         for (j in loader.moduleInfo[name].expanded_map) {
       
   743                             if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
       
   744                                 req.push(j);
       
   745                             }
       
   746                         }
       
   747                         Y._attach(req);
       
   748                     }
       
   749 
       
   750                     details = mod.details;
       
   751                     req = details.requires;
       
   752                     use = details.use;
       
   753                     after = details.after;
       
   754                     //Force Intl load if there is a language (Loader logic) @todo fix this shit
       
   755                     if (details.lang) {
       
   756                         req = req || [];
       
   757                         req.unshift('intl');
       
   758                     }
       
   759 
       
   760                     if (req) {
       
   761                         for (j = 0; j < req.length; j++) {
       
   762                             if (!done[req[j]]) {
       
   763                                 if (!Y._attach(req)) {
       
   764                                     return false;
       
   765                                 }
       
   766                                 break;
       
   767                             }
       
   768                         }
       
   769                     }
       
   770 
       
   771                     if (after) {
       
   772                         for (j = 0; j < after.length; j++) {
       
   773                             if (!done[after[j]]) {
       
   774                                 if (!Y._attach(after, true)) {
       
   775                                     return false;
       
   776                                 }
       
   777                                 break;
       
   778                             }
       
   779                         }
       
   780                     }
       
   781 
       
   782                     if (mod.fn) {
       
   783                             if (Y.config.throwFail) {
       
   784                                 mod.fn(Y, name);
       
   785                             } else {
       
   786                                 try {
       
   787                                     mod.fn(Y, name);
       
   788                                 } catch (e) {
       
   789                                     Y.error('Attach error: ' + name, e, name);
       
   790                                 return false;
       
   791                             }
       
   792                         }
       
   793                     }
       
   794 
       
   795                     if (use) {
       
   796                         for (j = 0; j < use.length; j++) {
       
   797                             if (!done[use[j]]) {
       
   798                                 if (!Y._attach(use)) {
       
   799                                     return false;
       
   800                                 }
       
   801                                 break;
       
   802                             }
       
   803                         }
       
   804                     }
       
   805 
       
   806 
       
   807 
       
   808                 }
       
   809             }
       
   810         }
       
   811 
       
   812         return true;
       
   813     },
       
   814 
       
   815     /**
       
   816     Delays the `use` callback until another event has taken place such as
       
   817     `window.onload`, `domready`, `contentready`, or `available`.
       
   818 
       
   819     @private
       
   820     @method _delayCallback
       
   821     @param {Function} cb The original `use` callback.
       
   822     @param {String|Object} until Either an event name ('load', 'domready', etc.)
       
   823         or an object containing event/args keys for contentready/available.
       
   824     @return {Function}
       
   825     **/
       
   826     _delayCallback: function(cb, until) {
       
   827 
       
   828         var Y = this,
       
   829             mod = ['event-base'];
       
   830 
       
   831         until = (Y.Lang.isObject(until) ? until : { event: until });
       
   832 
       
   833         if (until.event === 'load') {
       
   834             mod.push('event-synthetic');
       
   835         }
       
   836 
       
   837         Y.log('Delaying use callback until: ' + until.event, 'info', 'yui');
       
   838         return function() {
       
   839             Y.log('Use callback fired, waiting on delay', 'info', 'yui');
       
   840             var args = arguments;
       
   841             Y._use(mod, function() {
       
   842                 Y.log('Delayed use wrapper callback after dependencies', 'info', 'yui');
       
   843                 Y.on(until.event, function() {
       
   844                     args[1].delayUntil = until.event;
       
   845                     Y.log('Delayed use callback done after ' + until.event, 'info', 'yui');
       
   846                     cb.apply(Y, args);
       
   847                 }, until.args);
       
   848             });
       
   849         };
       
   850     },
       
   851 
       
   852     /**
       
   853     Attaches one or more modules to this YUI instance. When this is executed,
       
   854     the requirements of the desired modules are analyzed, and one of several
       
   855     things can happen:
       
   856 
       
   857 
       
   858       * All required modules have already been loaded, and just need to be
       
   859         attached to this YUI instance. In this case, the `use()` callback will
       
   860         be executed synchronously after the modules are attached.
       
   861 
       
   862       * One or more modules have not yet been loaded, or the Get utility is not
       
   863         available, or the `bootstrap` config option is `false`. In this case,
       
   864         a warning is issued indicating that modules are missing, but all
       
   865         available modules will still be attached and the `use()` callback will
       
   866         be executed synchronously.
       
   867 
       
   868       * One or more modules are missing and the Loader is not available but the
       
   869         Get utility is, and `bootstrap` is not `false`. In this case, the Get
       
   870         utility will be used to load the Loader, and we will then proceed to
       
   871         the following state:
       
   872 
       
   873       * One or more modules are missing and the Loader is available. In this
       
   874         case, the Loader will be used to resolve the dependency tree for the
       
   875         missing modules and load them and their dependencies. When the Loader is
       
   876         finished loading modules, the `use()` callback will be executed
       
   877         asynchronously.
       
   878 
       
   879     @example
       
   880 
       
   881         // Loads and attaches dd and its dependencies.
       
   882         YUI().use('dd', function (Y) {
       
   883             // ...
       
   884         });
       
   885 
       
   886         // Loads and attaches dd and node as well as all of their dependencies.
       
   887         YUI().use(['dd', 'node'], function (Y) {
       
   888             // ...
       
   889         });
       
   890 
       
   891         // Attaches all modules that have already been loaded.
       
   892         YUI().use('*', function (Y) {
       
   893             // ...
       
   894         });
       
   895 
       
   896         // Attaches a gallery module.
       
   897         YUI().use('gallery-yql', function (Y) {
       
   898             // ...
       
   899         });
       
   900 
       
   901         // Attaches a YUI 2in3 module.
       
   902         YUI().use('yui2-datatable', function (Y) {
       
   903             // ...
       
   904         });
       
   905 
       
   906     @method use
       
   907     @param {String|Array} modules* One or more module names to attach.
       
   908     @param {Function} [callback] Callback function to be executed once all
       
   909         specified modules and their dependencies have been attached.
       
   910     @param {YUI} callback.Y The YUI instance created for this sandbox.
       
   911     @param {Object} callback.status Object containing `success`, `msg` and
       
   912         `data` properties.
       
   913     @chainable
       
   914     **/
       
   915     use: function() {
       
   916         var args = SLICE.call(arguments, 0),
       
   917             callback = args[args.length - 1],
       
   918             Y = this,
       
   919             i = 0,
       
   920             name,
       
   921             Env = Y.Env,
       
   922             provisioned = true;
       
   923 
       
   924         // The last argument supplied to use can be a load complete callback
       
   925         if (Y.Lang.isFunction(callback)) {
       
   926             args.pop();
       
   927             if (Y.config.delayUntil) {
       
   928                 callback = Y._delayCallback(callback, Y.config.delayUntil);
       
   929             }
       
   930         } else {
       
   931             callback = null;
       
   932         }
       
   933         if (Y.Lang.isArray(args[0])) {
       
   934             args = args[0];
       
   935         }
       
   936 
       
   937         if (Y.config.cacheUse) {
       
   938             while ((name = args[i++])) {
       
   939                 if (!Env._attached[name]) {
       
   940                     provisioned = false;
       
   941                     break;
       
   942                 }
       
   943             }
       
   944 
       
   945             if (provisioned) {
       
   946                 if (args.length) {
       
   947                     Y.log('already provisioned: ' + args, 'info', 'yui');
       
   948                 }
       
   949                 Y._notify(callback, ALREADY_DONE, args);
       
   950                 return Y;
       
   951             }
       
   952         }
       
   953 
       
   954         if (Y._loading) {
       
   955             Y._useQueue = Y._useQueue || new Y.Queue();
       
   956             Y._useQueue.add([args, callback]);
       
   957         } else {
       
   958             Y._use(args, function(Y, response) {
       
   959                 Y._notify(callback, response, args);
       
   960             });
       
   961         }
       
   962 
       
   963         return Y;
       
   964     },
       
   965 
       
   966     /**
       
   967     Handles Loader notifications about attachment/load errors.
       
   968 
       
   969     @method _notify
       
   970     @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
       
   971     @param {Object} response Response returned from Loader.
       
   972     @param {Array} args Arguments passed from Loader.
       
   973     @private
       
   974     **/
       
   975     _notify: function(callback, response, args) {
       
   976         if (!response.success && this.config.loadErrorFn) {
       
   977             this.config.loadErrorFn.call(this, this, callback, response, args);
       
   978         } else if (callback) {
       
   979             if (this.Env._missed && this.Env._missed.length) {
       
   980                 response.msg = 'Missing modules: ' + this.Env._missed.join();
       
   981                 response.success = false;
       
   982             }
       
   983             if (this.config.throwFail) {
       
   984                 callback(this, response);
       
   985             } else {
       
   986                 try {
       
   987                     callback(this, response);
       
   988                 } catch (e) {
       
   989                     this.error('use callback error', e, args);
       
   990                 }
       
   991             }
       
   992         }
       
   993     },
       
   994 
       
   995     /**
       
   996     Called from the `use` method queue to ensure that only one set of loading
       
   997     logic is performed at a time.
       
   998 
       
   999     @method _use
       
  1000     @param {String} args* One or more modules to attach.
       
  1001     @param {Function} [callback] Function to call once all required modules have
       
  1002         been attached.
       
  1003     @private
       
  1004     **/
       
  1005     _use: function(args, callback) {
       
  1006 
       
  1007         if (!this.Array) {
       
  1008             this._attach(['yui-base']);
       
  1009         }
       
  1010 
       
  1011         var len, loader, handleBoot,
       
  1012             Y = this,
       
  1013             G_ENV = YUI.Env,
       
  1014             mods = G_ENV.mods,
       
  1015             Env = Y.Env,
       
  1016             used = Env._used,
       
  1017             aliases = G_ENV.aliases,
       
  1018             queue = G_ENV._loaderQueue,
       
  1019             firstArg = args[0],
       
  1020             YArray = Y.Array,
       
  1021             config = Y.config,
       
  1022             boot = config.bootstrap,
       
  1023             missing = [],
       
  1024             i,
       
  1025             r = [],
       
  1026             ret = true,
       
  1027             fetchCSS = config.fetchCSS,
       
  1028             process = function(names, skip) {
       
  1029 
       
  1030                 var i = 0, a = [], name, len, m, req, use;
       
  1031 
       
  1032                 if (!names.length) {
       
  1033                     return;
       
  1034                 }
       
  1035 
       
  1036                 if (aliases) {
       
  1037                     len = names.length;
       
  1038                     for (i = 0; i < len; i++) {
       
  1039                         if (aliases[names[i]] && !mods[names[i]]) {
       
  1040                             a = [].concat(a, aliases[names[i]]);
       
  1041                         } else {
       
  1042                             a.push(names[i]);
       
  1043                         }
       
  1044                     }
       
  1045                     names = a;
       
  1046                 }
       
  1047 
       
  1048                 len = names.length;
       
  1049 
       
  1050                 for (i = 0; i < len; i++) {
       
  1051                     name = names[i];
       
  1052                     if (!skip) {
       
  1053                         r.push(name);
       
  1054                     }
       
  1055 
       
  1056                     // only attach a module once
       
  1057                     if (used[name]) {
       
  1058                         continue;
       
  1059                     }
       
  1060 
       
  1061                     m = mods[name];
       
  1062                     req = null;
       
  1063                     use = null;
       
  1064 
       
  1065                     if (m) {
       
  1066                         used[name] = true;
       
  1067                         req = m.details.requires;
       
  1068                         use = m.details.use;
       
  1069                     } else {
       
  1070                         // CSS files don't register themselves, see if it has
       
  1071                         // been loaded
       
  1072                         if (!G_ENV._loaded[VERSION][name]) {
       
  1073                             missing.push(name);
       
  1074                         } else {
       
  1075                             used[name] = true; // probably css
       
  1076                         }
       
  1077                     }
       
  1078 
       
  1079                     // make sure requirements are attached
       
  1080                     if (req && req.length) {
       
  1081                         process(req);
       
  1082                     }
       
  1083 
       
  1084                     // make sure we grab the submodule dependencies too
       
  1085                     if (use && use.length) {
       
  1086                         process(use, 1);
       
  1087                     }
       
  1088                 }
       
  1089 
       
  1090             },
       
  1091 
       
  1092             handleLoader = function(fromLoader) {
       
  1093                 var response = fromLoader || {
       
  1094                         success: true,
       
  1095                         msg: 'not dynamic'
       
  1096                     },
       
  1097                     redo, origMissing,
       
  1098                     ret = true,
       
  1099                     data = response.data;
       
  1100 
       
  1101                 Y._loading = false;
       
  1102 
       
  1103                 if (data) {
       
  1104                     origMissing = missing;
       
  1105                     missing = [];
       
  1106                     r = [];
       
  1107                     process(data);
       
  1108                     redo = missing.length;
       
  1109                     if (redo) {
       
  1110                         if ([].concat(missing).sort().join() ==
       
  1111                                 origMissing.sort().join()) {
       
  1112                             redo = false;
       
  1113                         }
       
  1114                     }
       
  1115                 }
       
  1116 
       
  1117                 if (redo && data) {
       
  1118                     Y._loading = true;
       
  1119                     Y._use(missing, function() {
       
  1120                         Y.log('Nested use callback: ' + data, 'info', 'yui');
       
  1121                         if (Y._attach(data)) {
       
  1122                             Y._notify(callback, response, data);
       
  1123                         }
       
  1124                     });
       
  1125                 } else {
       
  1126                     if (data) {
       
  1127                         // Y.log('attaching from loader: ' + data, 'info', 'yui');
       
  1128                         ret = Y._attach(data);
       
  1129                     }
       
  1130                     if (ret) {
       
  1131                         Y._notify(callback, response, args);
       
  1132                     }
       
  1133                 }
       
  1134 
       
  1135                 if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
       
  1136                     Y._use.apply(Y, Y._useQueue.next());
       
  1137                 }
       
  1138 
       
  1139             };
       
  1140 
       
  1141 // Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
       
  1142 
       
  1143         // YUI().use('*'); // bind everything available
       
  1144         if (firstArg === '*') {
       
  1145             args = [];
       
  1146             for (i in mods) {
       
  1147                 if (mods.hasOwnProperty(i)) {
       
  1148                     args.push(i);
       
  1149                 }
       
  1150             }
       
  1151             ret = Y._attach(args);
       
  1152             if (ret) {
       
  1153                 handleLoader();
       
  1154             }
       
  1155             return Y;
       
  1156         }
       
  1157 
       
  1158         if ((mods.loader || mods['loader-base']) && !Y.Loader) {
       
  1159             Y.log('Loader was found in meta, but it is not attached. Attaching..', 'info', 'yui');
       
  1160             Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
       
  1161         }
       
  1162 
       
  1163         // Y.log('before loader requirements: ' + args, 'info', 'yui');
       
  1164 
       
  1165         // use loader to expand dependencies and sort the
       
  1166         // requirements if it is available.
       
  1167         if (boot && Y.Loader && args.length) {
       
  1168             Y.log('Using loader to expand dependencies', 'info', 'yui');
       
  1169             loader = getLoader(Y);
       
  1170             loader.require(args);
       
  1171             loader.ignoreRegistered = true;
       
  1172             loader._boot = true;
       
  1173             loader.calculate(null, (fetchCSS) ? null : 'js');
       
  1174             args = loader.sorted;
       
  1175             loader._boot = false;
       
  1176         }
       
  1177 
       
  1178         process(args);
       
  1179 
       
  1180         len = missing.length;
       
  1181 
       
  1182 
       
  1183         if (len) {
       
  1184             missing = YArray.dedupe(missing);
       
  1185             len = missing.length;
       
  1186 Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
       
  1187         }
       
  1188 
       
  1189 
       
  1190         // dynamic load
       
  1191         if (boot && len && Y.Loader) {
       
  1192 // Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
       
  1193             Y.log('Using Loader', 'info', 'yui');
       
  1194             Y._loading = true;
       
  1195             loader = getLoader(Y);
       
  1196             loader.onEnd = handleLoader;
       
  1197             loader.context = Y;
       
  1198             loader.data = args;
       
  1199             loader.ignoreRegistered = false;
       
  1200             loader.require(missing);
       
  1201             loader.insert(null, (fetchCSS) ? null : 'js');
       
  1202 
       
  1203         } else if (boot && len && Y.Get && !Env.bootstrapped) {
       
  1204 
       
  1205             Y._loading = true;
       
  1206 
       
  1207             handleBoot = function() {
       
  1208                 Y._loading = false;
       
  1209                 queue.running = false;
       
  1210                 Env.bootstrapped = true;
       
  1211                 G_ENV._bootstrapping = false;
       
  1212                 if (Y._attach(['loader'])) {
       
  1213                     Y._use(args, callback);
       
  1214                 }
       
  1215             };
       
  1216 
       
  1217             if (G_ENV._bootstrapping) {
       
  1218 Y.log('Waiting for loader', 'info', 'yui');
       
  1219                 queue.add(handleBoot);
       
  1220             } else {
       
  1221                 G_ENV._bootstrapping = true;
       
  1222 Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
       
  1223                 Y.Get.script(config.base + config.loaderPath, {
       
  1224                     onEnd: handleBoot
       
  1225                 });
       
  1226             }
       
  1227 
       
  1228         } else {
       
  1229             Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
       
  1230             ret = Y._attach(args);
       
  1231             if (ret) {
       
  1232                 handleLoader();
       
  1233             }
       
  1234         }
       
  1235 
       
  1236         return Y;
       
  1237     },
       
  1238 
       
  1239 
       
  1240     /**
       
  1241     Utility method for safely creating namespaces if they don't already exist.
       
  1242     May be called statically on the YUI global object or as a method on a YUI
       
  1243     instance.
       
  1244 
       
  1245     When called statically, a namespace will be created on the YUI global
       
  1246     object:
       
  1247 
       
  1248         // Create `YUI.your.namespace.here` as nested objects, preserving any
       
  1249         // objects that already exist instead of overwriting them.
       
  1250         YUI.namespace('your.namespace.here');
       
  1251 
       
  1252     When called as a method on a YUI instance, a namespace will be created on
       
  1253     that instance:
       
  1254 
       
  1255         // Creates `Y.property.package`.
       
  1256         Y.namespace('property.package');
       
  1257 
       
  1258     Dots in the input string cause `namespace` to create nested objects for each
       
  1259     token. If any part of the requested namespace already exists, the current
       
  1260     object will be left in place and will not be overwritten. This allows
       
  1261     multiple calls to `namespace` to preserve existing namespaced properties.
       
  1262 
       
  1263     If the first token in the namespace string is "YAHOO", that token is
       
  1264     discarded. This is legacy behavior for backwards compatibility with YUI 2.
       
  1265 
       
  1266     Be careful with namespace tokens. Reserved words may work in some browsers
       
  1267     and not others. For instance, the following will fail in some browsers
       
  1268     because the supported version of JavaScript reserves the word "long":
       
  1269 
       
  1270         Y.namespace('really.long.nested.namespace');
       
  1271 
       
  1272     Note: If you pass multiple arguments to create multiple namespaces, only the
       
  1273     last one created is returned from this function.
       
  1274 
       
  1275     @method namespace
       
  1276     @param {String} namespace* One or more namespaces to create.
       
  1277     @return {Object} Reference to the last namespace object created.
       
  1278     **/
       
  1279     namespace: function() {
       
  1280         var a = arguments, o, i = 0, j, d, arg;
       
  1281 
       
  1282         for (; i < a.length; i++) {
       
  1283             o = this; //Reset base object per argument or it will get reused from the last
       
  1284             arg = a[i];
       
  1285             if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
       
  1286                 d = arg.split(PERIOD);
       
  1287                 for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
       
  1288                     o[d[j]] = o[d[j]] || {};
       
  1289                     o = o[d[j]];
       
  1290                 }
       
  1291             } else {
       
  1292                 o[arg] = o[arg] || {};
       
  1293                 o = o[arg]; //Reset base object to the new object so it's returned
       
  1294             }
       
  1295         }
       
  1296         return o;
       
  1297     },
       
  1298 
       
  1299     // this is replaced if the log module is included
       
  1300     log: NOOP,
       
  1301     message: NOOP,
       
  1302     // this is replaced if the dump module is included
       
  1303     dump: function (o) { return ''+o; },
       
  1304 
       
  1305     /**
       
  1306     Reports an error.
       
  1307 
       
  1308     The reporting mechanism is controlled by the `throwFail` configuration
       
  1309     attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
       
  1310     truthy, a JS exception is thrown.
       
  1311 
       
  1312     If an `errorFn` is specified in the config it must return `true` to indicate
       
  1313     that the exception was handled and keep it from being thrown.
       
  1314 
       
  1315     @method error
       
  1316     @param {String} msg Error message.
       
  1317     @param {Error|String} [e] JavaScript error object or an error string.
       
  1318     @param {String} [src] Source of the error (such as the name of the module in
       
  1319         which the error occurred).
       
  1320     @chainable
       
  1321     **/
       
  1322     error: function(msg, e, src) {
       
  1323         //TODO Add check for window.onerror here
       
  1324 
       
  1325         var Y = this, ret;
       
  1326 
       
  1327         if (Y.config.errorFn) {
       
  1328             ret = Y.config.errorFn.apply(Y, arguments);
       
  1329         }
       
  1330 
       
  1331         if (!ret) {
       
  1332             throw (e || new Error(msg));
       
  1333         } else {
       
  1334             Y.message(msg, 'error', ''+src); // don't scrub this one
       
  1335         }
       
  1336 
       
  1337         return Y;
       
  1338     },
       
  1339 
       
  1340     /**
       
  1341     Generates an id string that is unique among all YUI instances in this
       
  1342     execution context.
       
  1343 
       
  1344     @method guid
       
  1345     @param {String} [pre] Prefix.
       
  1346     @return {String} Unique id.
       
  1347     **/
       
  1348     guid: function(pre) {
       
  1349         var id = this.Env._guidp + '_' + (++this.Env._uidx);
       
  1350         return (pre) ? (pre + id) : id;
       
  1351     },
       
  1352 
       
  1353     /**
       
  1354     Returns a unique id associated with the given object and (if *readOnly* is
       
  1355     falsy) stamps the object with that id so it can be identified in the future.
       
  1356 
       
  1357     Stamping an object involves adding a `_yuid` property to it that contains
       
  1358     the object's id. One exception to this is that in Internet Explorer, DOM
       
  1359     nodes have a `uniqueID` property that contains a browser-generated unique
       
  1360     id, which will be used instead of a YUI-generated id when available.
       
  1361 
       
  1362     @method stamp
       
  1363     @param {Object} o Object to stamp.
       
  1364     @param {Boolean} readOnly If truthy and the given object has not already
       
  1365         been stamped, the object will not be modified and `null` will be
       
  1366         returned.
       
  1367     @return {String} Object's unique id, or `null` if *readOnly* was truthy and
       
  1368         the given object was not already stamped.
       
  1369     **/
       
  1370     stamp: function(o, readOnly) {
       
  1371         var uid;
       
  1372         if (!o) {
       
  1373             return o;
       
  1374         }
       
  1375 
       
  1376         // IE generates its own unique ID for dom nodes
       
  1377         // The uniqueID property of a document node returns a new ID
       
  1378         if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
       
  1379             uid = o.uniqueID;
       
  1380         } else {
       
  1381             uid = (typeof o === 'string') ? o : o._yuid;
       
  1382         }
       
  1383 
       
  1384         if (!uid) {
       
  1385             uid = this.guid();
       
  1386             if (!readOnly) {
       
  1387                 try {
       
  1388                     o._yuid = uid;
       
  1389                 } catch (e) {
       
  1390                     uid = null;
       
  1391                 }
       
  1392             }
       
  1393         }
       
  1394         return uid;
       
  1395     },
       
  1396 
       
  1397     /**
       
  1398     Destroys this YUI instance.
       
  1399 
       
  1400     @method destroy
       
  1401     @since 3.3.0
       
  1402     **/
       
  1403     destroy: function() {
       
  1404         var Y = this;
       
  1405         if (Y.Event) {
       
  1406             Y.Event._unload();
       
  1407         }
       
  1408         delete instances[Y.id];
       
  1409         delete Y.Env;
       
  1410         delete Y.config;
       
  1411     }
       
  1412 
       
  1413     /**
       
  1414     Safe `instanceof` wrapper that works around a memory leak in IE when the
       
  1415     object being tested is `window` or `document`.
       
  1416 
       
  1417     Unless you are testing objects that may be `window` or `document`, you
       
  1418     should use the native `instanceof` operator instead of this method.
       
  1419 
       
  1420     @method instanceOf
       
  1421     @param {Object} o Object to check.
       
  1422     @param {Object} type Class to check against.
       
  1423     @since 3.3.0
       
  1424     **/
       
  1425 };
       
  1426 
       
  1427     YUI.prototype = proto;
       
  1428 
       
  1429     // inheritance utilities are not available yet
       
  1430     for (prop in proto) {
       
  1431         if (proto.hasOwnProperty(prop)) {
       
  1432             YUI[prop] = proto[prop];
       
  1433         }
       
  1434     }
       
  1435 
       
  1436     /**
       
  1437     Applies a configuration to all YUI instances in this execution context.
       
  1438 
       
  1439     The main use case for this method is in "mashups" where several third-party
       
  1440     scripts need to write to a global YUI config, but cannot share a single
       
  1441     centrally-managed config object. This way they can all call
       
  1442     `YUI.applyConfig({})` instead of overwriting the single global config.
       
  1443 
       
  1444     @example
       
  1445 
       
  1446         YUI.applyConfig({
       
  1447             modules: {
       
  1448                 davglass: {
       
  1449                     fullpath: './davglass.js'
       
  1450                 }
       
  1451             }
       
  1452         });
       
  1453 
       
  1454         YUI.applyConfig({
       
  1455             modules: {
       
  1456                 foo: {
       
  1457                     fullpath: './foo.js'
       
  1458                 }
       
  1459             }
       
  1460         });
       
  1461 
       
  1462         YUI().use('davglass', function (Y) {
       
  1463             // Module davglass will be available here.
       
  1464         });
       
  1465 
       
  1466     @method applyConfig
       
  1467     @param {Object} o Configuration object to apply.
       
  1468     @static
       
  1469     @since 3.5.0
       
  1470     **/
       
  1471     YUI.applyConfig = function(o) {
       
  1472         if (!o) {
       
  1473             return;
       
  1474         }
       
  1475         //If there is a GlobalConfig, apply it first to set the defaults
       
  1476         if (YUI.GlobalConfig) {
       
  1477             this.prototype.applyConfig.call(this, YUI.GlobalConfig);
       
  1478         }
       
  1479         //Apply this config to it
       
  1480         this.prototype.applyConfig.call(this, o);
       
  1481         //Reset GlobalConfig to the combined config
       
  1482         YUI.GlobalConfig = this.config;
       
  1483     };
       
  1484 
       
  1485     // set up the environment
       
  1486     YUI._init();
       
  1487 
       
  1488     if (hasWin) {
       
  1489         // add a window load event at load time so we can capture
       
  1490         // the case where it fires before dynamic loading is
       
  1491         // complete.
       
  1492         add(window, 'load', handleLoad);
       
  1493     } else {
       
  1494         handleLoad();
       
  1495     }
       
  1496 
       
  1497     YUI.Env.add = add;
       
  1498     YUI.Env.remove = remove;
       
  1499 
       
  1500     /*global exports*/
       
  1501     // Support the CommonJS method for exporting our single global
       
  1502     if (typeof exports == 'object') {
       
  1503         exports.YUI = YUI;
       
  1504         /**
       
  1505         * Set a method to be called when `Get.script` is called in Node.js
       
  1506         * `Get` will open the file, then pass it's content and it's path
       
  1507         * to this method before attaching it. Commonly used for code coverage
       
  1508         * instrumentation. <strong>Calling this multiple times will only
       
  1509         * attach the last hook method</strong>. This method is only
       
  1510         * available in Node.js.
       
  1511         * @method setLoadHook
       
  1512         * @static
       
  1513         * @param {Function} fn The function to set
       
  1514         * @param {String} fn.data The content of the file
       
  1515         * @param {String} fn.path The file path of the file
       
  1516         */
       
  1517         YUI.setLoadHook = function(fn) {
       
  1518             YUI._getLoadHook = fn;
       
  1519         };
       
  1520         /**
       
  1521         * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
       
  1522         * @method _getLoadHook
       
  1523         * @private
       
  1524         * @param {String} data The content of the file
       
  1525         * @param {String} path The file path of the file
       
  1526         */
       
  1527         YUI._getLoadHook = null;
       
  1528     }
       
  1529 
       
  1530 }());
       
  1531 
       
  1532 
       
  1533 /**
       
  1534 Config object that contains all of the configuration options for
       
  1535 this `YUI` instance.
       
  1536 
       
  1537 This object is supplied by the implementer when instantiating YUI. Some
       
  1538 properties have default values if they are not supplied by the implementer.
       
  1539 
       
  1540 This object should not be updated directly because some values are cached. Use
       
  1541 `applyConfig()` to update the config object on a YUI instance that has already
       
  1542 been configured.
       
  1543 
       
  1544 @class config
       
  1545 @static
       
  1546 **/
       
  1547 
       
  1548 /**
       
  1549 If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
       
  1550 if they're needed to load additional dependencies and aren't already available.
       
  1551 
       
  1552 Setting this to `false` will prevent YUI from automatically loading the Loader
       
  1553 and module metadata, so you will need to manually ensure that they're available
       
  1554 or handle dependency resolution yourself.
       
  1555 
       
  1556 @property {Boolean} bootstrap
       
  1557 @default true
       
  1558 **/
       
  1559 
       
  1560 /**
       
  1561 If `true`, `Y.log()` messages will be written to the browser's debug console
       
  1562 when available and when `useBrowserConsole` is also `true`.
       
  1563 
       
  1564 @property {Boolean} debug
       
  1565 @default true
       
  1566 **/
       
  1567 
       
  1568 /**
       
  1569 Log messages to the browser console if `debug` is `true` and the browser has a
       
  1570 supported console.
       
  1571 
       
  1572 @property {Boolean} useBrowserConsole
       
  1573 @default true
       
  1574 **/
       
  1575 
       
  1576 /**
       
  1577 A hash of log sources that should be logged. If specified, only messages from
       
  1578 these sources will be logged. Others will be discarded.
       
  1579 
       
  1580 @property {Object} logInclude
       
  1581 @type object
       
  1582 **/
       
  1583 
       
  1584 /**
       
  1585 A hash of log sources that should be not be logged. If specified, all sources
       
  1586 will be logged *except* those on this list.
       
  1587 
       
  1588 @property {Object} logExclude
       
  1589 **/
       
  1590 
       
  1591 /**
       
  1592 When the YUI seed file is dynamically loaded after the `window.onload` event has
       
  1593 fired, set this to `true` to tell YUI that it shouldn't wait for `window.onload`
       
  1594 to occur.
       
  1595 
       
  1596 This ensures that components that rely on `window.onload` and the `domready`
       
  1597 custom event will work as expected even when YUI is dynamically injected.
       
  1598 
       
  1599 @property {Boolean} injected
       
  1600 @default false
       
  1601 **/
       
  1602 
       
  1603 /**
       
  1604 If `true`, `Y.error()` will generate or re-throw a JavaScript error. Otherwise,
       
  1605 errors are merely logged silently.
       
  1606 
       
  1607 @property {Boolean} throwFail
       
  1608 @default true
       
  1609 **/
       
  1610 
       
  1611 /**
       
  1612 Reference to the global object for this execution context.
       
  1613 
       
  1614 In a browser, this is the current `window` object. In Node.js, this is the
       
  1615 Node.js `global` object.
       
  1616 
       
  1617 @property {Object} global
       
  1618 **/
       
  1619 
       
  1620 /**
       
  1621 The browser window or frame that this YUI instance should operate in.
       
  1622 
       
  1623 When running in Node.js, this property is `undefined`, since there is no
       
  1624 `window` object. Use `global` to get a reference to the global object that will
       
  1625 work in both browsers and Node.js.
       
  1626 
       
  1627 @property {Window} win
       
  1628 **/
       
  1629 
       
  1630 /**
       
  1631 The browser `document` object associated with this YUI instance's `win` object.
       
  1632 
       
  1633 When running in Node.js, this property is `undefined`, since there is no
       
  1634 `document` object.
       
  1635 
       
  1636 @property {Document} doc
       
  1637 **/
       
  1638 
       
  1639 /**
       
  1640 A list of modules that defines the YUI core (overrides the default list).
       
  1641 
       
  1642 @property {Array} core
       
  1643 @type Array
       
  1644 @default ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3']
       
  1645 **/
       
  1646 
       
  1647 /**
       
  1648 A list of languages to use in order of preference.
       
  1649 
       
  1650 This list is matched against the list of available languages in modules that the
       
  1651 YUI instance uses to determine the best possible localization of language
       
  1652 sensitive modules.
       
  1653 
       
  1654 Languages are represented using BCP 47 language tags, such as "en-GB" for
       
  1655 English as used in the United Kingdom, or "zh-Hans-CN" for simplified Chinese as
       
  1656 used in China. The list may be provided as a comma-separated string or as an
       
  1657 array.
       
  1658 
       
  1659 @property {String|String[]} lang
       
  1660 **/
       
  1661 
       
  1662 /**
       
  1663 Default date format.
       
  1664 
       
  1665 @property {String} dateFormat
       
  1666 @deprecated Use configuration in `DataType.Date.format()` instead.
       
  1667 **/
       
  1668 
       
  1669 /**
       
  1670 Default locale.
       
  1671 
       
  1672 @property {String} locale
       
  1673 @deprecated Use `config.lang` instead.
       
  1674 **/
       
  1675 
       
  1676 /**
       
  1677 Default generic polling interval in milliseconds.
       
  1678 
       
  1679 @property {Number} pollInterval
       
  1680 @default 20
       
  1681 **/
       
  1682 
       
  1683 /**
       
  1684 The number of dynamic `<script>` nodes to insert by default before automatically
       
  1685 removing them when loading scripts.
       
  1686 
       
  1687 This applies only to script nodes because removing the node will not make the
       
  1688 evaluated script unavailable. Dynamic CSS nodes are not auto purged, because
       
  1689 removing a linked style sheet will also remove the style definitions.
       
  1690 
       
  1691 @property {Number} purgethreshold
       
  1692 @default 20
       
  1693 **/
       
  1694 
       
  1695 /**
       
  1696 Delay in milliseconds to wait after a window `resize` event before firing the
       
  1697 event. If another `resize` event occurs before this delay has elapsed, the
       
  1698 delay will start over to ensure that `resize` events are throttled.
       
  1699 
       
  1700 @property {Number} windowResizeDelay
       
  1701 @default 40
       
  1702 **/
       
  1703 
       
  1704 /**
       
  1705 Base directory for dynamic loading.
       
  1706 
       
  1707 @property {String} base
       
  1708 **/
       
  1709 
       
  1710 /**
       
  1711 Base URL for a dynamic combo handler. This will be used to make combo-handled
       
  1712 module requests if `combine` is set to `true.
       
  1713 
       
  1714 @property {String} comboBase
       
  1715 @default "http://yui.yahooapis.com/combo?"
       
  1716 **/
       
  1717 
       
  1718 /**
       
  1719 Root path to prepend to each module path when creating a combo-handled request.
       
  1720 
       
  1721 This is updated for each YUI release to point to a specific version of the
       
  1722 library; for example: "3.8.0/build/".
       
  1723 
       
  1724 @property {String} root
       
  1725 **/
       
  1726 
       
  1727 /**
       
  1728 Filter to apply to module urls. This filter will modify the default path for all
       
  1729 modules.
       
  1730 
       
  1731 The default path for the YUI library is the minified version of the files (e.g.,
       
  1732 event-min.js). The filter property can be a predefined filter or a custom
       
  1733 filter. The valid predefined filters are:
       
  1734 
       
  1735   - **debug**: Loads debug versions of modules (e.g., event-debug.js).
       
  1736   - **raw**: Loads raw, non-minified versions of modules without debug logging
       
  1737     (e.g., event.js).
       
  1738 
       
  1739 You can also define a custom filter, which must be an object literal containing
       
  1740 a search regular expression and a replacement string:
       
  1741 
       
  1742     myFilter: {
       
  1743         searchExp : "-min\\.js",
       
  1744         replaceStr: "-debug.js"
       
  1745     }
       
  1746 
       
  1747 @property {Object|String} filter
       
  1748 **/
       
  1749 
       
  1750 /**
       
  1751 Skin configuration and customizations.
       
  1752 
       
  1753 @property {Object} skin
       
  1754 @param {String} [skin.defaultSkin='sam'] Default skin name. This skin will be
       
  1755     applied automatically to skinnable components if not overridden by a
       
  1756     component-specific skin name.
       
  1757 @param {String} [skin.base='assets/skins/'] Default base path for a skin,
       
  1758     relative to Loader's `base` path.
       
  1759 @param {Object} [skin.overrides] Component-specific skin name overrides. Specify
       
  1760     a component name as the key and, as the value, a string or array of strings
       
  1761     for a skin or skins that should be loaded for that component instead of the
       
  1762     `defaultSkin`.
       
  1763 **/
       
  1764 
       
  1765 /**
       
  1766 Hash of per-component filter specifications. If specified for a given component,
       
  1767 this overrides the global `filter` config.
       
  1768 
       
  1769 @property {Object} filters
       
  1770 **/
       
  1771 
       
  1772 /**
       
  1773 If `true`, YUI will use a combo handler to load multiple modules in as few
       
  1774 requests as possible.
       
  1775 
       
  1776 The YUI CDN (which YUI uses by default) supports combo handling, but other
       
  1777 servers may not. If the server from which you're loading YUI does not support
       
  1778 combo handling, set this to `false`.
       
  1779 
       
  1780 Providing a value for the `base` config property will cause `combine` to default
       
  1781 to `false` instead of `true`.
       
  1782 
       
  1783 @property {Boolean} combine
       
  1784 @default true
       
  1785 */
       
  1786 
       
  1787 /**
       
  1788 Array of module names that should never be dynamically loaded.
       
  1789 
       
  1790 @property {String[]} ignore
       
  1791 **/
       
  1792 
       
  1793 /**
       
  1794 Array of module names that should always be loaded when required, even if
       
  1795 already present on the page.
       
  1796 
       
  1797 @property {String[]} force
       
  1798 **/
       
  1799 
       
  1800 /**
       
  1801 DOM element or id that should be used as the insertion point for dynamically
       
  1802 added `<script>` and `<link>` nodes.
       
  1803 
       
  1804 @property {HTMLElement|String} insertBefore
       
  1805 **/
       
  1806 
       
  1807 /**
       
  1808 Object hash containing attributes to add to dynamically added `<script>` nodes.
       
  1809 
       
  1810 @property {Object} jsAttributes
       
  1811 **/
       
  1812 
       
  1813 /**
       
  1814 Object hash containing attributes to add to dynamically added `<link>` nodes.
       
  1815 
       
  1816 @property {Object} cssAttributes
       
  1817 **/
       
  1818 
       
  1819 /**
       
  1820 Timeout in milliseconds before a dynamic JS or CSS request will be considered a
       
  1821 failure. If not set, no timeout will be enforced.
       
  1822 
       
  1823 @property {Number} timeout
       
  1824 **/
       
  1825 
       
  1826 /**
       
  1827 Callback for the 'CSSComplete' event. When dynamically loading YUI components
       
  1828 with CSS, this property fires when the CSS is finished loading.
       
  1829 
       
  1830 This provides an opportunity to enhance the presentation of a loading page a
       
  1831 little bit before the entire loading process is done.
       
  1832 
       
  1833 @property {Function} onCSS
       
  1834 **/
       
  1835 
       
  1836 /**
       
  1837 A hash of module definitions to add to the list of available YUI modules. These
       
  1838 modules can then be dynamically loaded via the `use()` method.
       
  1839 
       
  1840 This is a hash in which keys are module names and values are objects containing
       
  1841 module metadata.
       
  1842 
       
  1843 See `Loader.addModule()` for the supported module metadata fields. Also see
       
  1844 `groups`, which provides a way to configure the base and combo spec for a set of
       
  1845 modules.
       
  1846 
       
  1847 @example
       
  1848 
       
  1849     modules: {
       
  1850         mymod1: {
       
  1851             requires: ['node'],
       
  1852             fullpath: '/mymod1/mymod1.js'
       
  1853         },
       
  1854 
       
  1855         mymod2: {
       
  1856             requires: ['mymod1'],
       
  1857             fullpath: '/mymod2/mymod2.js'
       
  1858         },
       
  1859 
       
  1860         mymod3: '/js/mymod3.js',
       
  1861         mycssmod: '/css/mycssmod.css'
       
  1862     }
       
  1863 
       
  1864 @property {Object} modules
       
  1865 **/
       
  1866 
       
  1867 /**
       
  1868 Aliases are dynamic groups of modules that can be used as shortcuts.
       
  1869 
       
  1870 @example
       
  1871 
       
  1872     YUI({
       
  1873         aliases: {
       
  1874             davglass: [ 'node', 'yql', 'dd' ],
       
  1875             mine: [ 'davglass', 'autocomplete']
       
  1876         }
       
  1877     }).use('mine', function (Y) {
       
  1878         // Node, YQL, DD & AutoComplete available here.
       
  1879     });
       
  1880 
       
  1881 @property {Object} aliases
       
  1882 **/
       
  1883 
       
  1884 /**
       
  1885 A hash of module group definitions.
       
  1886 
       
  1887 For each group you can specify a list of modules and the base path and
       
  1888 combo spec to use when dynamically loading the modules.
       
  1889 
       
  1890 @example
       
  1891 
       
  1892     groups: {
       
  1893         yui2: {
       
  1894             // specify whether or not this group has a combo service
       
  1895             combine: true,
       
  1896 
       
  1897             // The comboSeperator to use with this group's combo handler
       
  1898             comboSep: ';',
       
  1899 
       
  1900             // The maxURLLength for this server
       
  1901             maxURLLength: 500,
       
  1902 
       
  1903             // the base path for non-combo paths
       
  1904             base: 'http://yui.yahooapis.com/2.8.0r4/build/',
       
  1905 
       
  1906             // the path to the combo service
       
  1907             comboBase: 'http://yui.yahooapis.com/combo?',
       
  1908 
       
  1909             // a fragment to prepend to the path attribute when
       
  1910             // when building combo urls
       
  1911             root: '2.8.0r4/build/',
       
  1912 
       
  1913             // the module definitions
       
  1914             modules:  {
       
  1915                 yui2_yde: {
       
  1916                     path: "yahoo-dom-event/yahoo-dom-event.js"
       
  1917                 },
       
  1918                 yui2_anim: {
       
  1919                     path: "animation/animation.js",
       
  1920                     requires: ['yui2_yde']
       
  1921                 }
       
  1922             }
       
  1923         }
       
  1924     }
       
  1925 
       
  1926 @property {Object} groups
       
  1927 **/
       
  1928 
       
  1929 /**
       
  1930 Path to the Loader JS file, relative to the `base` path.
       
  1931 
       
  1932 This is used to dynamically bootstrap the Loader when it's needed and isn't yet
       
  1933 available.
       
  1934 
       
  1935 @property {String} loaderPath
       
  1936 @default "loader/loader-min.js"
       
  1937 **/
       
  1938 
       
  1939 /**
       
  1940 If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
       
  1941 `false` to prevent YUI from loading any CSS, or set it to the string `"force"`
       
  1942 to force CSS dependencies to be loaded even if their associated JS modules are
       
  1943 already loaded.
       
  1944 
       
  1945 @property {Boolean|String} fetchCSS
       
  1946 @default true
       
  1947 **/
       
  1948 
       
  1949 /**
       
  1950 Default gallery version used to build gallery module urls.
       
  1951 
       
  1952 @property {String} gallery
       
  1953 @since 3.1.0
       
  1954 **/
       
  1955 
       
  1956 /**
       
  1957 Default YUI 2 version used to build YUI 2 module urls.
       
  1958 
       
  1959 This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
       
  1960 `2in3` config for pulling different revisions of the wrapped YUI 2 modules.
       
  1961 
       
  1962 @property {String} yui2
       
  1963 @default "2.9.0"
       
  1964 @since 3.1.0
       
  1965 **/
       
  1966 
       
  1967 /**
       
  1968 Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
       
  1969 
       
  1970 @property {String} 2in3
       
  1971 @default "4"
       
  1972 @since 3.1.0
       
  1973 **/
       
  1974 
       
  1975 /**
       
  1976 Alternate console log function that should be used in environments without a
       
  1977 supported native console. This function is executed with the YUI instance as its
       
  1978 `this` object.
       
  1979 
       
  1980 @property {Function} logFn
       
  1981 @since 3.1.0
       
  1982 **/
       
  1983 
       
  1984 /**
       
  1985 The minimum log level to log messages for. Log levels are defined
       
  1986 incrementally. Messages greater than or equal to the level specified will
       
  1987 be shown. All others will be discarded. The order of log levels in
       
  1988 increasing priority is:
       
  1989 
       
  1990     debug
       
  1991     info
       
  1992     warn
       
  1993     error
       
  1994 
       
  1995 @property {String} logLevel
       
  1996 @default 'debug'
       
  1997 @since 3.10.0
       
  1998 **/
       
  1999 
       
  2000 /**
       
  2001 Callback to execute when `Y.error()` is called. It receives the error message
       
  2002 and a JavaScript error object if one was provided.
       
  2003 
       
  2004 This function is executed with the YUI instance as its `this` object.
       
  2005 
       
  2006 Returning `true` from this function will prevent an exception from being thrown.
       
  2007 
       
  2008 @property {Function} errorFn
       
  2009 @param {String} errorFn.msg Error message
       
  2010 @param {Object} [errorFn.err] Error object (if one was provided).
       
  2011 @since 3.2.0
       
  2012 **/
       
  2013 
       
  2014 /**
       
  2015 A callback to execute when Loader fails to load one or more resources.
       
  2016 
       
  2017 This could be because of a script load failure. It could also be because a
       
  2018 module fails to register itself when the `requireRegistration` config is `true`.
       
  2019 
       
  2020 If this function is defined, the `use()` callback will only be called when the
       
  2021 loader succeeds. Otherwise, `use()` will always executes unless there was a
       
  2022 JavaScript error when attaching a module.
       
  2023 
       
  2024 @property {Function} loadErrorFn
       
  2025 @since 3.3.0
       
  2026 **/
       
  2027 
       
  2028 /**
       
  2029 If `true`, Loader will expect all loaded scripts to be first-class YUI modules
       
  2030 that register themselves with the YUI global, and will trigger a failure if a
       
  2031 loaded script does not register a YUI module.
       
  2032 
       
  2033 @property {Boolean} requireRegistration
       
  2034 @default false
       
  2035 @since 3.3.0
       
  2036 **/
       
  2037 
       
  2038 /**
       
  2039 Cache serviced use() requests.
       
  2040 
       
  2041 @property {Boolean} cacheUse
       
  2042 @default true
       
  2043 @since 3.3.0
       
  2044 @deprecated No longer used.
       
  2045 **/
       
  2046 
       
  2047 /**
       
  2048 Whether or not YUI should use native ES5 functionality when available for
       
  2049 features like `Y.Array.each()`, `Y.Object()`, etc.
       
  2050 
       
  2051 When `false`, YUI will always use its own fallback implementations instead of
       
  2052 relying on ES5 functionality, even when ES5 functionality is available.
       
  2053 
       
  2054 @property {Boolean} useNativeES5
       
  2055 @default true
       
  2056 @since 3.5.0
       
  2057 **/
       
  2058 
       
  2059 /**
       
  2060  * Leverage native JSON stringify if the browser has a native
       
  2061  * implementation.  In general, this is a good idea.  See the Known Issues
       
  2062  * section in the JSON user guide for caveats.  The default value is true
       
  2063  * for browsers with native JSON support.
       
  2064  *
       
  2065  * @property useNativeJSONStringify
       
  2066  * @type Boolean
       
  2067  * @default true
       
  2068  * @since 3.8.0
       
  2069  */
       
  2070 
       
  2071  /**
       
  2072  * Leverage native JSON parse if the browser has a native implementation.
       
  2073  * In general, this is a good idea.  See the Known Issues section in the
       
  2074  * JSON user guide for caveats.  The default value is true for browsers with
       
  2075  * native JSON support.
       
  2076  *
       
  2077  * @property useNativeJSONParse
       
  2078  * @type Boolean
       
  2079  * @default true
       
  2080  * @since 3.8.0
       
  2081  */
       
  2082 
       
  2083 /**
       
  2084 Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
       
  2085 
       
  2086 @property {Object|String} delayUntil
       
  2087 @since 3.6.0
       
  2088 @example
       
  2089 
       
  2090 You can use `load` or `domready` strings by default:
       
  2091 
       
  2092     YUI({
       
  2093         delayUntil: 'domready'
       
  2094     }, function (Y) {
       
  2095         // This will not execute until 'domeready' occurs.
       
  2096     });
       
  2097 
       
  2098 Or you can delay until a node is available (with `available` or `contentready`):
       
  2099 
       
  2100     YUI({
       
  2101         delayUntil: {
       
  2102             event: 'available',
       
  2103             args : '#foo'
       
  2104         }
       
  2105     }, function (Y) {
       
  2106         // This will not execute until a node matching the selector "#foo" is
       
  2107         // available in the DOM.
       
  2108     });
       
  2109 
       
  2110 **/
       
  2111 YUI.add('yui-base', function (Y, NAME) {
       
  2112 
       
  2113 /*
       
  2114  * YUI stub
       
  2115  * @module yui
       
  2116  * @submodule yui-base
       
  2117  */
       
  2118 /**
       
  2119  * The YUI module contains the components required for building the YUI
       
  2120  * seed file.  This includes the script loading mechanism, a simple queue,
       
  2121  * and the core utilities for the library.
       
  2122  * @module yui
       
  2123  * @submodule yui-base
       
  2124  */
       
  2125 
       
  2126 /**
       
  2127  * Provides core language utilites and extensions used throughout YUI.
       
  2128  *
       
  2129  * @class Lang
       
  2130  * @static
       
  2131  */
       
  2132 
       
  2133 var L = Y.Lang || (Y.Lang = {}),
       
  2134 
       
  2135 STRING_PROTO = String.prototype,
       
  2136 TOSTRING     = Object.prototype.toString,
       
  2137 
       
  2138 TYPES = {
       
  2139     'undefined'        : 'undefined',
       
  2140     'number'           : 'number',
       
  2141     'boolean'          : 'boolean',
       
  2142     'string'           : 'string',
       
  2143     '[object Function]': 'function',
       
  2144     '[object RegExp]'  : 'regexp',
       
  2145     '[object Array]'   : 'array',
       
  2146     '[object Date]'    : 'date',
       
  2147     '[object Error]'   : 'error'
       
  2148 },
       
  2149 
       
  2150 SUBREGEX        = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
       
  2151 TRIMREGEX       = /^\s+|\s+$/g,
       
  2152 NATIVE_FN_REGEX = /\{\s*\[(?:native code|function)\]\s*\}/i;
       
  2153 
       
  2154 // -- Protected Methods --------------------------------------------------------
       
  2155 
       
  2156 /**
       
  2157 Returns `true` if the given function appears to be implemented in native code,
       
  2158 `false` otherwise. Will always return `false` -- even in ES5-capable browsers --
       
  2159 if the `useNativeES5` YUI config option is set to `false`.
       
  2160 
       
  2161 This isn't guaranteed to be 100% accurate and won't work for anything other than
       
  2162 functions, but it can be useful for determining whether a function like
       
  2163 `Array.prototype.forEach` is native or a JS shim provided by another library.
       
  2164 
       
  2165 There's a great article by @kangax discussing certain flaws with this technique:
       
  2166 <http://perfectionkills.com/detecting-built-in-host-methods/>
       
  2167 
       
  2168 While his points are valid, it's still possible to benefit from this function
       
  2169 as long as it's used carefully and sparingly, and in such a way that false
       
  2170 negatives have minimal consequences. It's used internally to avoid using
       
  2171 potentially broken non-native ES5 shims that have been added to the page by
       
  2172 other libraries.
       
  2173 
       
  2174 @method _isNative
       
  2175 @param {Function} fn Function to test.
       
  2176 @return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
       
  2177 @static
       
  2178 @protected
       
  2179 @since 3.5.0
       
  2180 **/
       
  2181 L._isNative = function (fn) {
       
  2182     return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
       
  2183 };
       
  2184 
       
  2185 // -- Public Methods -----------------------------------------------------------
       
  2186 
       
  2187 /**
       
  2188  * Determines whether or not the provided item is an array.
       
  2189  *
       
  2190  * Returns `false` for array-like collections such as the function `arguments`
       
  2191  * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
       
  2192  * test for an array-like collection.
       
  2193  *
       
  2194  * @method isArray
       
  2195  * @param o The object to test.
       
  2196  * @return {boolean} true if o is an array.
       
  2197  * @static
       
  2198  */
       
  2199 L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
       
  2200     return L.type(o) === 'array';
       
  2201 };
       
  2202 
       
  2203 /**
       
  2204  * Determines whether or not the provided item is a boolean.
       
  2205  * @method isBoolean
       
  2206  * @static
       
  2207  * @param o The object to test.
       
  2208  * @return {boolean} true if o is a boolean.
       
  2209  */
       
  2210 L.isBoolean = function(o) {
       
  2211     return typeof o === 'boolean';
       
  2212 };
       
  2213 
       
  2214 /**
       
  2215  * Determines whether or not the supplied item is a date instance.
       
  2216  * @method isDate
       
  2217  * @static
       
  2218  * @param o The object to test.
       
  2219  * @return {boolean} true if o is a date.
       
  2220  */
       
  2221 L.isDate = function(o) {
       
  2222     return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
       
  2223 };
       
  2224 
       
  2225 /**
       
  2226  * <p>
       
  2227  * Determines whether or not the provided item is a function.
       
  2228  * Note: Internet Explorer thinks certain functions are objects:
       
  2229  * </p>
       
  2230  *
       
  2231  * <pre>
       
  2232  * var obj = document.createElement("object");
       
  2233  * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
       
  2234  * &nbsp;
       
  2235  * var input = document.createElement("input"); // append to body
       
  2236  * Y.Lang.isFunction(input.focus) // reports false in IE
       
  2237  * </pre>
       
  2238  *
       
  2239  * <p>
       
  2240  * You will have to implement additional tests if these functions
       
  2241  * matter to you.
       
  2242  * </p>
       
  2243  *
       
  2244  * @method isFunction
       
  2245  * @static
       
  2246  * @param o The object to test.
       
  2247  * @return {boolean} true if o is a function.
       
  2248  */
       
  2249 L.isFunction = function(o) {
       
  2250     return L.type(o) === 'function';
       
  2251 };
       
  2252 
       
  2253 /**
       
  2254  * Determines whether or not the provided item is null.
       
  2255  * @method isNull
       
  2256  * @static
       
  2257  * @param o The object to test.
       
  2258  * @return {boolean} true if o is null.
       
  2259  */
       
  2260 L.isNull = function(o) {
       
  2261     return o === null;
       
  2262 };
       
  2263 
       
  2264 /**
       
  2265  * Determines whether or not the provided item is a legal number.
       
  2266  * @method isNumber
       
  2267  * @static
       
  2268  * @param o The object to test.
       
  2269  * @return {boolean} true if o is a number.
       
  2270  */
       
  2271 L.isNumber = function(o) {
       
  2272     return typeof o === 'number' && isFinite(o);
       
  2273 };
       
  2274 
       
  2275 /**
       
  2276  * Determines whether or not the provided item is of type object
       
  2277  * or function. Note that arrays are also objects, so
       
  2278  * <code>Y.Lang.isObject([]) === true</code>.
       
  2279  * @method isObject
       
  2280  * @static
       
  2281  * @param o The object to test.
       
  2282  * @param failfn {boolean} fail if the input is a function.
       
  2283  * @return {boolean} true if o is an object.
       
  2284  * @see isPlainObject
       
  2285  */
       
  2286 L.isObject = function(o, failfn) {
       
  2287     var t = typeof o;
       
  2288     return (o && (t === 'object' ||
       
  2289         (!failfn && (t === 'function' || L.isFunction(o))))) || false;
       
  2290 };
       
  2291 
       
  2292 /**
       
  2293  * Determines whether or not the provided item is a string.
       
  2294  * @method isString
       
  2295  * @static
       
  2296  * @param o The object to test.
       
  2297  * @return {boolean} true if o is a string.
       
  2298  */
       
  2299 L.isString = function(o) {
       
  2300     return typeof o === 'string';
       
  2301 };
       
  2302 
       
  2303 /**
       
  2304  * Determines whether or not the provided item is undefined.
       
  2305  * @method isUndefined
       
  2306  * @static
       
  2307  * @param o The object to test.
       
  2308  * @return {boolean} true if o is undefined.
       
  2309  */
       
  2310 L.isUndefined = function(o) {
       
  2311     return typeof o === 'undefined';
       
  2312 };
       
  2313 
       
  2314 /**
       
  2315  * A convenience method for detecting a legitimate non-null value.
       
  2316  * Returns false for null/undefined/NaN, true for other values,
       
  2317  * including 0/false/''
       
  2318  * @method isValue
       
  2319  * @static
       
  2320  * @param o The item to test.
       
  2321  * @return {boolean} true if it is not null/undefined/NaN || false.
       
  2322  */
       
  2323 L.isValue = function(o) {
       
  2324     var t = L.type(o);
       
  2325 
       
  2326     switch (t) {
       
  2327         case 'number':
       
  2328             return isFinite(o);
       
  2329 
       
  2330         case 'null': // fallthru
       
  2331         case 'undefined':
       
  2332             return false;
       
  2333 
       
  2334         default:
       
  2335             return !!t;
       
  2336     }
       
  2337 };
       
  2338 
       
  2339 /**
       
  2340  * Returns the current time in milliseconds.
       
  2341  *
       
  2342  * @method now
       
  2343  * @return {Number} Current time in milliseconds.
       
  2344  * @static
       
  2345  * @since 3.3.0
       
  2346  */
       
  2347 L.now = Date.now || function () {
       
  2348     return new Date().getTime();
       
  2349 };
       
  2350 
       
  2351 /**
       
  2352  * Lightweight version of <code>Y.substitute</code>. Uses the same template
       
  2353  * structure as <code>Y.substitute</code>, but doesn't support recursion,
       
  2354  * auto-object coersion, or formats.
       
  2355  * @method sub
       
  2356  * @param {string} s String to be modified.
       
  2357  * @param {object} o Object containing replacement values.
       
  2358  * @return {string} the substitute result.
       
  2359  * @static
       
  2360  * @since 3.2.0
       
  2361  */
       
  2362 L.sub = function(s, o) {
       
  2363     return s.replace ? s.replace(SUBREGEX, function (match, key) {
       
  2364         return L.isUndefined(o[key]) ? match : o[key];
       
  2365     }) : s;
       
  2366 };
       
  2367 
       
  2368 /**
       
  2369  * Returns a string without any leading or trailing whitespace.  If
       
  2370  * the input is not a string, the input will be returned untouched.
       
  2371  * @method trim
       
  2372  * @static
       
  2373  * @param s {string} the string to trim.
       
  2374  * @return {string} the trimmed string.
       
  2375  */
       
  2376 L.trim = STRING_PROTO.trim ? function(s) {
       
  2377     return s && s.trim ? s.trim() : s;
       
  2378 } : function (s) {
       
  2379     try {
       
  2380         return s.replace(TRIMREGEX, '');
       
  2381     } catch (e) {
       
  2382         return s;
       
  2383     }
       
  2384 };
       
  2385 
       
  2386 /**
       
  2387  * Returns a string without any leading whitespace.
       
  2388  * @method trimLeft
       
  2389  * @static
       
  2390  * @param s {string} the string to trim.
       
  2391  * @return {string} the trimmed string.
       
  2392  */
       
  2393 L.trimLeft = STRING_PROTO.trimLeft ? function (s) {
       
  2394     return s.trimLeft();
       
  2395 } : function (s) {
       
  2396     return s.replace(/^\s+/, '');
       
  2397 };
       
  2398 
       
  2399 /**
       
  2400  * Returns a string without any trailing whitespace.
       
  2401  * @method trimRight
       
  2402  * @static
       
  2403  * @param s {string} the string to trim.
       
  2404  * @return {string} the trimmed string.
       
  2405  */
       
  2406 L.trimRight = STRING_PROTO.trimRight ? function (s) {
       
  2407     return s.trimRight();
       
  2408 } : function (s) {
       
  2409     return s.replace(/\s+$/, '');
       
  2410 };
       
  2411 
       
  2412 /**
       
  2413 Returns one of the following strings, representing the type of the item passed
       
  2414 in:
       
  2415 
       
  2416  * "array"
       
  2417  * "boolean"
       
  2418  * "date"
       
  2419  * "error"
       
  2420  * "function"
       
  2421  * "null"
       
  2422  * "number"
       
  2423  * "object"
       
  2424  * "regexp"
       
  2425  * "string"
       
  2426  * "undefined"
       
  2427 
       
  2428 Known issues:
       
  2429 
       
  2430  * `typeof HTMLElementCollection` returns function in Safari, but
       
  2431     `Y.Lang.type()` reports "object", which could be a good thing --
       
  2432     but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
       
  2433 
       
  2434 @method type
       
  2435 @param o the item to test.
       
  2436 @return {string} the detected type.
       
  2437 @static
       
  2438 **/
       
  2439 L.type = function(o) {
       
  2440     return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
       
  2441 };
       
  2442 /**
       
  2443 @module yui
       
  2444 @submodule yui-base
       
  2445 */
       
  2446 
       
  2447 var Lang   = Y.Lang,
       
  2448     Native = Array.prototype,
       
  2449 
       
  2450     hasOwn = Object.prototype.hasOwnProperty;
       
  2451 
       
  2452 /**
       
  2453 Provides utility methods for working with arrays. Additional array helpers can
       
  2454 be found in the `collection` and `array-extras` modules.
       
  2455 
       
  2456 `Y.Array(thing)` returns a native array created from _thing_. Depending on
       
  2457 _thing_'s type, one of the following will happen:
       
  2458 
       
  2459   * Arrays are returned unmodified unless a non-zero _startIndex_ is
       
  2460     specified.
       
  2461   * Array-like collections (see `Array.test()`) are converted to arrays.
       
  2462   * For everything else, a new array is created with _thing_ as the sole
       
  2463     item.
       
  2464 
       
  2465 Note: elements that are also collections, such as `<form>` and `<select>`
       
  2466 elements, are not automatically converted to arrays. To force a conversion,
       
  2467 pass `true` as the value of the _force_ parameter.
       
  2468 
       
  2469 @class Array
       
  2470 @constructor
       
  2471 @param {Any} thing The thing to arrayify.
       
  2472 @param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
       
  2473   collection, a subset of items starting at the specified index will be
       
  2474   returned.
       
  2475 @param {Boolean} [force=false] If `true`, _thing_ will be treated as an
       
  2476   array-like collection no matter what.
       
  2477 @return {Array} A native array created from _thing_, according to the rules
       
  2478   described above.
       
  2479 **/
       
  2480 function YArray(thing, startIndex, force) {
       
  2481     var len, result;
       
  2482 
       
  2483     /*jshint expr: true*/
       
  2484     startIndex || (startIndex = 0);
       
  2485 
       
  2486     if (force || YArray.test(thing)) {
       
  2487         // IE throws when trying to slice HTMLElement collections.
       
  2488         try {
       
  2489             return Native.slice.call(thing, startIndex);
       
  2490         } catch (ex) {
       
  2491             result = [];
       
  2492 
       
  2493             for (len = thing.length; startIndex < len; ++startIndex) {
       
  2494                 result.push(thing[startIndex]);
       
  2495             }
       
  2496 
       
  2497             return result;
       
  2498         }
       
  2499     }
       
  2500 
       
  2501     return [thing];
       
  2502 }
       
  2503 
       
  2504 Y.Array = YArray;
       
  2505 
       
  2506 /**
       
  2507 Dedupes an array of strings, returning an array that's guaranteed to contain
       
  2508 only one copy of a given string.
       
  2509 
       
  2510 This method differs from `Array.unique()` in that it's optimized for use only
       
  2511 with strings, whereas `unique` may be used with other types (but is slower).
       
  2512 Using `dedupe()` with non-string values may result in unexpected behavior.
       
  2513 
       
  2514 @method dedupe
       
  2515 @param {String[]} array Array of strings to dedupe.
       
  2516 @return {Array} Deduped copy of _array_.
       
  2517 @static
       
  2518 @since 3.4.0
       
  2519 **/
       
  2520 YArray.dedupe = function (array) {
       
  2521     var hash    = {},
       
  2522         results = [],
       
  2523         i, item, len;
       
  2524 
       
  2525     for (i = 0, len = array.length; i < len; ++i) {
       
  2526         item = array[i];
       
  2527 
       
  2528         if (!hasOwn.call(hash, item)) {
       
  2529             hash[item] = 1;
       
  2530             results.push(item);
       
  2531         }
       
  2532     }
       
  2533 
       
  2534     return results;
       
  2535 };
       
  2536 
       
  2537 /**
       
  2538 Executes the supplied function on each item in the array. This method wraps
       
  2539 the native ES5 `Array.forEach()` method if available.
       
  2540 
       
  2541 @method each
       
  2542 @param {Array} array Array to iterate.
       
  2543 @param {Function} fn Function to execute on each item in the array. The function
       
  2544   will receive the following arguments:
       
  2545     @param {Any} fn.item Current array item.
       
  2546     @param {Number} fn.index Current array index.
       
  2547     @param {Array} fn.array Array being iterated.
       
  2548 @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  2549 @return {YUI} The YUI instance.
       
  2550 @static
       
  2551 **/
       
  2552 YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
       
  2553     Native.forEach.call(array || [], fn, thisObj || Y);
       
  2554     return Y;
       
  2555 } : function (array, fn, thisObj) {
       
  2556     for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
       
  2557         if (i in array) {
       
  2558             fn.call(thisObj || Y, array[i], i, array);
       
  2559         }
       
  2560     }
       
  2561 
       
  2562     return Y;
       
  2563 };
       
  2564 
       
  2565 /**
       
  2566 Alias for `each()`.
       
  2567 
       
  2568 @method forEach
       
  2569 @static
       
  2570 **/
       
  2571 
       
  2572 /**
       
  2573 Returns an object using the first array as keys and the second as values. If
       
  2574 the second array is not provided, or if it doesn't contain the same number of
       
  2575 values as the first array, then `true` will be used in place of the missing
       
  2576 values.
       
  2577 
       
  2578 @example
       
  2579 
       
  2580     Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
       
  2581     // => {a: 'foo', b: 'bar', c: true}
       
  2582 
       
  2583 @method hash
       
  2584 @param {String[]} keys Array of strings to use as keys.
       
  2585 @param {Array} [values] Array to use as values.
       
  2586 @return {Object} Hash using the first array as keys and the second as values.
       
  2587 @static
       
  2588 **/
       
  2589 YArray.hash = function (keys, values) {
       
  2590     var hash = {},
       
  2591         vlen = (values && values.length) || 0,
       
  2592         i, len;
       
  2593 
       
  2594     for (i = 0, len = keys.length; i < len; ++i) {
       
  2595         if (i in keys) {
       
  2596             hash[keys[i]] = vlen > i && i in values ? values[i] : true;
       
  2597         }
       
  2598     }
       
  2599 
       
  2600     return hash;
       
  2601 };
       
  2602 
       
  2603 /**
       
  2604 Returns the index of the first item in the array that's equal (using a strict
       
  2605 equality check) to the specified _value_, or `-1` if the value isn't found.
       
  2606 
       
  2607 This method wraps the native ES5 `Array.indexOf()` method if available.
       
  2608 
       
  2609 @method indexOf
       
  2610 @param {Array} array Array to search.
       
  2611 @param {Any} value Value to search for.
       
  2612 @param {Number} [from=0] The index at which to begin the search.
       
  2613 @return {Number} Index of the item strictly equal to _value_, or `-1` if not
       
  2614     found.
       
  2615 @static
       
  2616 **/
       
  2617 YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
       
  2618     return Native.indexOf.call(array, value, from);
       
  2619 } : function (array, value, from) {
       
  2620     // http://es5.github.com/#x15.4.4.14
       
  2621     var len = array.length;
       
  2622 
       
  2623     from = +from || 0;
       
  2624     from = (from > 0 || -1) * Math.floor(Math.abs(from));
       
  2625 
       
  2626     if (from < 0) {
       
  2627         from += len;
       
  2628 
       
  2629         if (from < 0) {
       
  2630             from = 0;
       
  2631         }
       
  2632     }
       
  2633 
       
  2634     for (; from < len; ++from) {
       
  2635         if (from in array && array[from] === value) {
       
  2636             return from;
       
  2637         }
       
  2638     }
       
  2639 
       
  2640     return -1;
       
  2641 };
       
  2642 
       
  2643 /**
       
  2644 Numeric sort convenience function.
       
  2645 
       
  2646 The native `Array.prototype.sort()` function converts values to strings and
       
  2647 sorts them in lexicographic order, which is unsuitable for sorting numeric
       
  2648 values. Provide `Array.numericSort` as a custom sort function when you want
       
  2649 to sort values in numeric order.
       
  2650 
       
  2651 @example
       
  2652 
       
  2653     [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
       
  2654     // => [4, 8, 15, 16, 23, 42]
       
  2655 
       
  2656 @method numericSort
       
  2657 @param {Number} a First value to compare.
       
  2658 @param {Number} b Second value to compare.
       
  2659 @return {Number} Difference between _a_ and _b_.
       
  2660 @static
       
  2661 **/
       
  2662 YArray.numericSort = function (a, b) {
       
  2663     return a - b;
       
  2664 };
       
  2665 
       
  2666 /**
       
  2667 Executes the supplied function on each item in the array. Returning a truthy
       
  2668 value from the function will stop the processing of remaining items.
       
  2669 
       
  2670 @method some
       
  2671 @param {Array} array Array to iterate over.
       
  2672 @param {Function} fn Function to execute on each item. The function will receive
       
  2673   the following arguments:
       
  2674     @param {Any} fn.value Current array item.
       
  2675     @param {Number} fn.index Current array index.
       
  2676     @param {Array} fn.array Array being iterated over.
       
  2677 @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  2678 @return {Boolean} `true` if the function returns a truthy value on any of the
       
  2679   items in the array; `false` otherwise.
       
  2680 @static
       
  2681 **/
       
  2682 YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
       
  2683     return Native.some.call(array, fn, thisObj);
       
  2684 } : function (array, fn, thisObj) {
       
  2685     for (var i = 0, len = array.length; i < len; ++i) {
       
  2686         if (i in array && fn.call(thisObj, array[i], i, array)) {
       
  2687             return true;
       
  2688         }
       
  2689     }
       
  2690 
       
  2691     return false;
       
  2692 };
       
  2693 
       
  2694 /**
       
  2695 Evaluates _obj_ to determine if it's an array, an array-like collection, or
       
  2696 something else. This is useful when working with the function `arguments`
       
  2697 collection and `HTMLElement` collections.
       
  2698 
       
  2699 Note: This implementation doesn't consider elements that are also
       
  2700 collections, such as `<form>` and `<select>`, to be array-like.
       
  2701 
       
  2702 @method test
       
  2703 @param {Object} obj Object to test.
       
  2704 @return {Number} A number indicating the results of the test:
       
  2705 
       
  2706   * 0: Neither an array nor an array-like collection.
       
  2707   * 1: Real array.
       
  2708   * 2: Array-like collection.
       
  2709 
       
  2710 @static
       
  2711 **/
       
  2712 YArray.test = function (obj) {
       
  2713     var result = 0;
       
  2714 
       
  2715     if (Lang.isArray(obj)) {
       
  2716         result = 1;
       
  2717     } else if (Lang.isObject(obj)) {
       
  2718         try {
       
  2719             // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
       
  2720             // or functions without apply/call (Safari
       
  2721             // HTMLElementCollection bug).
       
  2722             if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
       
  2723                 result = 2;
       
  2724             }
       
  2725         } catch (ex) {}
       
  2726     }
       
  2727 
       
  2728     return result;
       
  2729 };
       
  2730 /**
       
  2731  * The YUI module contains the components required for building the YUI
       
  2732  * seed file.  This includes the script loading mechanism, a simple queue,
       
  2733  * and the core utilities for the library.
       
  2734  * @module yui
       
  2735  * @submodule yui-base
       
  2736  */
       
  2737 
       
  2738 /**
       
  2739  * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
       
  2740  * removed using next().
       
  2741  *
       
  2742  * @class Queue
       
  2743  * @constructor
       
  2744  * @param {MIXED} item* 0..n items to seed the queue.
       
  2745  */
       
  2746 function Queue() {
       
  2747     this._init();
       
  2748     this.add.apply(this, arguments);
       
  2749 }
       
  2750 
       
  2751 Queue.prototype = {
       
  2752     /**
       
  2753      * Initialize the queue
       
  2754      *
       
  2755      * @method _init
       
  2756      * @protected
       
  2757      */
       
  2758     _init: function() {
       
  2759         /**
       
  2760          * The collection of enqueued items
       
  2761          *
       
  2762          * @property _q
       
  2763          * @type Array
       
  2764          * @protected
       
  2765          */
       
  2766         this._q = [];
       
  2767     },
       
  2768 
       
  2769     /**
       
  2770      * Get the next item in the queue. FIFO support
       
  2771      *
       
  2772      * @method next
       
  2773      * @return {MIXED} the next item in the queue.
       
  2774      */
       
  2775     next: function() {
       
  2776         return this._q.shift();
       
  2777     },
       
  2778 
       
  2779     /**
       
  2780      * Get the last in the queue. LIFO support.
       
  2781      *
       
  2782      * @method last
       
  2783      * @return {MIXED} the last item in the queue.
       
  2784      */
       
  2785     last: function() {
       
  2786         return this._q.pop();
       
  2787     },
       
  2788 
       
  2789     /**
       
  2790      * Add 0..n items to the end of the queue.
       
  2791      *
       
  2792      * @method add
       
  2793      * @param {MIXED} item* 0..n items.
       
  2794      * @return {object} this queue.
       
  2795      */
       
  2796     add: function() {
       
  2797         this._q.push.apply(this._q, arguments);
       
  2798 
       
  2799         return this;
       
  2800     },
       
  2801 
       
  2802     /**
       
  2803      * Returns the current number of queued items.
       
  2804      *
       
  2805      * @method size
       
  2806      * @return {Number} The size.
       
  2807      */
       
  2808     size: function() {
       
  2809         return this._q.length;
       
  2810     }
       
  2811 };
       
  2812 
       
  2813 Y.Queue = Queue;
       
  2814 
       
  2815 YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
       
  2816 
       
  2817 /**
       
  2818 The YUI module contains the components required for building the YUI seed file.
       
  2819 This includes the script loading mechanism, a simple queue, and the core
       
  2820 utilities for the library.
       
  2821 
       
  2822 @module yui
       
  2823 @submodule yui-base
       
  2824 **/
       
  2825 
       
  2826 var CACHED_DELIMITER = '__',
       
  2827 
       
  2828     hasOwn   = Object.prototype.hasOwnProperty,
       
  2829     isObject = Y.Lang.isObject;
       
  2830 
       
  2831 /**
       
  2832 Returns a wrapper for a function which caches the return value of that function,
       
  2833 keyed off of the combined string representation of the argument values provided
       
  2834 when the wrapper is called.
       
  2835 
       
  2836 Calling this function again with the same arguments will return the cached value
       
  2837 rather than executing the wrapped function.
       
  2838 
       
  2839 Note that since the cache is keyed off of the string representation of arguments
       
  2840 passed to the wrapper function, arguments that aren't strings and don't provide
       
  2841 a meaningful `toString()` method may result in unexpected caching behavior. For
       
  2842 example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
       
  2843 string `[object Object]` when used as a cache key.
       
  2844 
       
  2845 @method cached
       
  2846 @param {Function} source The function to memoize.
       
  2847 @param {Object} [cache={}] Object in which to store cached values. You may seed
       
  2848   this object with pre-existing cached values if desired.
       
  2849 @param {any} [refetch] If supplied, this value is compared with the cached value
       
  2850   using a `==` comparison. If the values are equal, the wrapped function is
       
  2851   executed again even though a cached value exists.
       
  2852 @return {Function} Wrapped function.
       
  2853 @for YUI
       
  2854 **/
       
  2855 Y.cached = function (source, cache, refetch) {
       
  2856     /*jshint expr: true*/
       
  2857     cache || (cache = {});
       
  2858 
       
  2859     return function (arg) {
       
  2860         var key = arguments.length > 1 ?
       
  2861                 Array.prototype.join.call(arguments, CACHED_DELIMITER) :
       
  2862                 String(arg);
       
  2863         
       
  2864         /*jshint eqeqeq: false*/
       
  2865         if (!(key in cache) || (refetch && cache[key] == refetch)) {
       
  2866             cache[key] = source.apply(source, arguments);
       
  2867         }
       
  2868 
       
  2869         return cache[key];
       
  2870     };
       
  2871 };
       
  2872 
       
  2873 /**
       
  2874 Returns the `location` object from the window/frame in which this YUI instance
       
  2875 operates, or `undefined` when executing in a non-browser environment
       
  2876 (e.g. Node.js).
       
  2877 
       
  2878 It is _not_ recommended to hold references to the `window.location` object
       
  2879 outside of the scope of a function in which its properties are being accessed or
       
  2880 its methods are being called. This is because of a nasty bug/issue that exists
       
  2881 in both Safari and MobileSafari browsers:
       
  2882 [WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
       
  2883 
       
  2884 @method getLocation
       
  2885 @return {location} The `location` object from the window/frame in which this YUI
       
  2886     instance operates.
       
  2887 @since 3.5.0
       
  2888 **/
       
  2889 Y.getLocation = function () {
       
  2890     // It is safer to look this up every time because yui-base is attached to a
       
  2891     // YUI instance before a user's config is applied; i.e. `Y.config.win` does
       
  2892     // not point the correct window object when this file is loaded.
       
  2893     var win = Y.config.win;
       
  2894 
       
  2895     // It is not safe to hold a reference to the `location` object outside the
       
  2896     // scope in which it is being used. The WebKit engine used in Safari and
       
  2897     // MobileSafari will "disconnect" the `location` object from the `window`
       
  2898     // when a page is restored from back/forward history cache.
       
  2899     return win && win.location;
       
  2900 };
       
  2901 
       
  2902 /**
       
  2903 Returns a new object containing all of the properties of all the supplied
       
  2904 objects. The properties from later objects will overwrite those in earlier
       
  2905 objects.
       
  2906 
       
  2907 Passing in a single object will create a shallow copy of it. For a deep copy,
       
  2908 use `clone()`.
       
  2909 
       
  2910 @method merge
       
  2911 @param {Object} objects* One or more objects to merge.
       
  2912 @return {Object} A new merged object.
       
  2913 **/
       
  2914 Y.merge = function () {
       
  2915     var i      = 0,
       
  2916         len    = arguments.length,
       
  2917         result = {},
       
  2918         key,
       
  2919         obj;
       
  2920 
       
  2921     for (; i < len; ++i) {
       
  2922         obj = arguments[i];
       
  2923 
       
  2924         for (key in obj) {
       
  2925             if (hasOwn.call(obj, key)) {
       
  2926                 result[key] = obj[key];
       
  2927             }
       
  2928         }
       
  2929     }
       
  2930 
       
  2931     return result;
       
  2932 };
       
  2933 
       
  2934 /**
       
  2935 Mixes _supplier_'s properties into _receiver_.
       
  2936 
       
  2937 Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
       
  2938 shadowed unless the _overwrite_ parameter is `true`, and will not be merged
       
  2939 unless the _merge_ parameter is `true`.
       
  2940 
       
  2941 In the default mode (0), only properties the supplier owns are copied (prototype
       
  2942 properties are not copied). The following copying modes are available:
       
  2943 
       
  2944   * `0`: _Default_. Object to object.
       
  2945   * `1`: Prototype to prototype.
       
  2946   * `2`: Prototype to prototype and object to object.
       
  2947   * `3`: Prototype to object.
       
  2948   * `4`: Object to prototype.
       
  2949 
       
  2950 @method mix
       
  2951 @param {Function|Object} receiver The object or function to receive the mixed
       
  2952   properties.
       
  2953 @param {Function|Object} supplier The object or function supplying the
       
  2954   properties to be mixed.
       
  2955 @param {Boolean} [overwrite=false] If `true`, properties that already exist
       
  2956   on the receiver will be overwritten with properties from the supplier.
       
  2957 @param {String[]} [whitelist] An array of property names to copy. If
       
  2958   specified, only the whitelisted properties will be copied, and all others
       
  2959   will be ignored.
       
  2960 @param {Number} [mode=0] Mix mode to use. See above for available modes.
       
  2961 @param {Boolean} [merge=false] If `true`, objects and arrays that already
       
  2962   exist on the receiver will have the corresponding object/array from the
       
  2963   supplier merged into them, rather than being skipped or overwritten. When
       
  2964   both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
       
  2965 @return {Function|Object|YUI} The receiver, or the YUI instance if the
       
  2966   specified receiver is falsy.
       
  2967 **/
       
  2968 Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
       
  2969     var alwaysOverwrite, exists, from, i, key, len, to;
       
  2970 
       
  2971     // If no supplier is given, we return the receiver. If no receiver is given,
       
  2972     // we return Y. Returning Y doesn't make much sense to me, but it's
       
  2973     // grandfathered in for backcompat reasons.
       
  2974     if (!receiver || !supplier) {
       
  2975         return receiver || Y;
       
  2976     }
       
  2977 
       
  2978     if (mode) {
       
  2979         // In mode 2 (prototype to prototype and object to object), we recurse
       
  2980         // once to do the proto to proto mix. The object to object mix will be
       
  2981         // handled later on.
       
  2982         if (mode === 2) {
       
  2983             Y.mix(receiver.prototype, supplier.prototype, overwrite,
       
  2984                     whitelist, 0, merge);
       
  2985         }
       
  2986 
       
  2987         // Depending on which mode is specified, we may be copying from or to
       
  2988         // the prototypes of the supplier and receiver.
       
  2989         from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
       
  2990         to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
       
  2991 
       
  2992         // If either the supplier or receiver doesn't actually have a
       
  2993         // prototype property, then we could end up with an undefined `from`
       
  2994         // or `to`. If that happens, we abort and return the receiver.
       
  2995         if (!from || !to) {
       
  2996             return receiver;
       
  2997         }
       
  2998     } else {
       
  2999         from = supplier;
       
  3000         to   = receiver;
       
  3001     }
       
  3002 
       
  3003     // If `overwrite` is truthy and `merge` is falsy, then we can skip a
       
  3004     // property existence check on each iteration and save some time.
       
  3005     alwaysOverwrite = overwrite && !merge;
       
  3006 
       
  3007     if (whitelist) {
       
  3008         for (i = 0, len = whitelist.length; i < len; ++i) {
       
  3009             key = whitelist[i];
       
  3010 
       
  3011             // We call `Object.prototype.hasOwnProperty` instead of calling
       
  3012             // `hasOwnProperty` on the object itself, since the object's
       
  3013             // `hasOwnProperty` method may have been overridden or removed.
       
  3014             // Also, some native objects don't implement a `hasOwnProperty`
       
  3015             // method.
       
  3016             if (!hasOwn.call(from, key)) {
       
  3017                 continue;
       
  3018             }
       
  3019 
       
  3020             // The `key in to` check here is (sadly) intentional for backwards
       
  3021             // compatibility reasons. It prevents undesired shadowing of
       
  3022             // prototype members on `to`.
       
  3023             exists = alwaysOverwrite ? false : key in to;
       
  3024 
       
  3025             if (merge && exists && isObject(to[key], true)
       
  3026                     && isObject(from[key], true)) {
       
  3027                 // If we're in merge mode, and the key is present on both
       
  3028                 // objects, and the value on both objects is either an object or
       
  3029                 // an array (but not a function), then we recurse to merge the
       
  3030                 // `from` value into the `to` value instead of overwriting it.
       
  3031                 //
       
  3032                 // Note: It's intentional that the whitelist isn't passed to the
       
  3033                 // recursive call here. This is legacy behavior that lots of
       
  3034                 // code still depends on.
       
  3035                 Y.mix(to[key], from[key], overwrite, null, 0, merge);
       
  3036             } else if (overwrite || !exists) {
       
  3037                 // We're not in merge mode, so we'll only copy the `from` value
       
  3038                 // to the `to` value if we're in overwrite mode or if the
       
  3039                 // current key doesn't exist on the `to` object.
       
  3040                 to[key] = from[key];
       
  3041             }
       
  3042         }
       
  3043     } else {
       
  3044         for (key in from) {
       
  3045             // The code duplication here is for runtime performance reasons.
       
  3046             // Combining whitelist and non-whitelist operations into a single
       
  3047             // loop or breaking the shared logic out into a function both result
       
  3048             // in worse performance, and Y.mix is critical enough that the byte
       
  3049             // tradeoff is worth it.
       
  3050             if (!hasOwn.call(from, key)) {
       
  3051                 continue;
       
  3052             }
       
  3053 
       
  3054             // The `key in to` check here is (sadly) intentional for backwards
       
  3055             // compatibility reasons. It prevents undesired shadowing of
       
  3056             // prototype members on `to`.
       
  3057             exists = alwaysOverwrite ? false : key in to;
       
  3058 
       
  3059             if (merge && exists && isObject(to[key], true)
       
  3060                     && isObject(from[key], true)) {
       
  3061                 Y.mix(to[key], from[key], overwrite, null, 0, merge);
       
  3062             } else if (overwrite || !exists) {
       
  3063                 to[key] = from[key];
       
  3064             }
       
  3065         }
       
  3066 
       
  3067         // If this is an IE browser with the JScript enumeration bug, force
       
  3068         // enumeration of the buggy properties by making a recursive call with
       
  3069         // the buggy properties as the whitelist.
       
  3070         if (Y.Object._hasEnumBug) {
       
  3071             Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
       
  3072         }
       
  3073     }
       
  3074 
       
  3075     return receiver;
       
  3076 };
       
  3077 /**
       
  3078  * The YUI module contains the components required for building the YUI
       
  3079  * seed file.  This includes the script loading mechanism, a simple queue,
       
  3080  * and the core utilities for the library.
       
  3081  * @module yui
       
  3082  * @submodule yui-base
       
  3083  */
       
  3084 
       
  3085 /**
       
  3086  * Adds utilities to the YUI instance for working with objects.
       
  3087  *
       
  3088  * @class Object
       
  3089  */
       
  3090 
       
  3091 var Lang   = Y.Lang,
       
  3092     hasOwn = Object.prototype.hasOwnProperty,
       
  3093 
       
  3094     UNDEFINED, // <-- Note the comma. We're still declaring vars.
       
  3095 
       
  3096 /**
       
  3097  * Returns a new object that uses _obj_ as its prototype. This method wraps the
       
  3098  * native ES5 `Object.create()` method if available, but doesn't currently
       
  3099  * pass through `Object.create()`'s second argument (properties) in order to
       
  3100  * ensure compatibility with older browsers.
       
  3101  *
       
  3102  * @method ()
       
  3103  * @param {Object} obj Prototype object.
       
  3104  * @return {Object} New object using _obj_ as its prototype.
       
  3105  * @static
       
  3106  */
       
  3107 O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
       
  3108     // We currently wrap the native Object.create instead of simply aliasing it
       
  3109     // to ensure consistency with our fallback shim, which currently doesn't
       
  3110     // support Object.create()'s second argument (properties). Once we have a
       
  3111     // safe fallback for the properties arg, we can stop wrapping
       
  3112     // Object.create().
       
  3113     return Object.create(obj);
       
  3114 } : (function () {
       
  3115     // Reusable constructor function for the Object.create() shim.
       
  3116     function F() {}
       
  3117 
       
  3118     // The actual shim.
       
  3119     return function (obj) {
       
  3120         F.prototype = obj;
       
  3121         return new F();
       
  3122     };
       
  3123 }()),
       
  3124 
       
  3125 /**
       
  3126  * Property names that IE doesn't enumerate in for..in loops, even when they
       
  3127  * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
       
  3128  * manually enumerate these properties.
       
  3129  *
       
  3130  * @property _forceEnum
       
  3131  * @type String[]
       
  3132  * @protected
       
  3133  * @static
       
  3134  */
       
  3135 forceEnum = O._forceEnum = [
       
  3136     'hasOwnProperty',
       
  3137     'isPrototypeOf',
       
  3138     'propertyIsEnumerable',
       
  3139     'toString',
       
  3140     'toLocaleString',
       
  3141     'valueOf'
       
  3142 ],
       
  3143 
       
  3144 /**
       
  3145  * `true` if this browser has the JScript enumeration bug that prevents
       
  3146  * enumeration of the properties named in the `_forceEnum` array, `false`
       
  3147  * otherwise.
       
  3148  *
       
  3149  * See:
       
  3150  *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
       
  3151  *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
       
  3152  *
       
  3153  * @property _hasEnumBug
       
  3154  * @type Boolean
       
  3155  * @protected
       
  3156  * @static
       
  3157  */
       
  3158 hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
       
  3159 
       
  3160 /**
       
  3161  * `true` if this browser incorrectly considers the `prototype` property of
       
  3162  * functions to be enumerable. Currently known to affect Opera 11.50.
       
  3163  *
       
  3164  * @property _hasProtoEnumBug
       
  3165  * @type Boolean
       
  3166  * @protected
       
  3167  * @static
       
  3168  */
       
  3169 hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
       
  3170 
       
  3171 /**
       
  3172  * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
       
  3173  * exists only on _obj_'s prototype. This is essentially a safer version of
       
  3174  * `obj.hasOwnProperty()`.
       
  3175  *
       
  3176  * @method owns
       
  3177  * @param {Object} obj Object to test.
       
  3178  * @param {String} key Property name to look for.
       
  3179  * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
       
  3180  * @static
       
  3181  */
       
  3182 owns = O.owns = function (obj, key) {
       
  3183     return !!obj && hasOwn.call(obj, key);
       
  3184 }; // <-- End of var declarations.
       
  3185 
       
  3186 /**
       
  3187  * Alias for `owns()`.
       
  3188  *
       
  3189  * @method hasKey
       
  3190  * @param {Object} obj Object to test.
       
  3191  * @param {String} key Property name to look for.
       
  3192  * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
       
  3193  * @static
       
  3194  */
       
  3195 O.hasKey = owns;
       
  3196 
       
  3197 /**
       
  3198  * Returns an array containing the object's enumerable keys. Does not include
       
  3199  * prototype keys or non-enumerable keys.
       
  3200  *
       
  3201  * Note that keys are returned in enumeration order (that is, in the same order
       
  3202  * that they would be enumerated by a `for-in` loop), which may not be the same
       
  3203  * as the order in which they were defined.
       
  3204  *
       
  3205  * This method is an alias for the native ES5 `Object.keys()` method if
       
  3206  * available.
       
  3207  *
       
  3208  * @example
       
  3209  *
       
  3210  *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
       
  3211  *     // => ['a', 'b', 'c']
       
  3212  *
       
  3213  * @method keys
       
  3214  * @param {Object} obj An object.
       
  3215  * @return {String[]} Array of keys.
       
  3216  * @static
       
  3217  */
       
  3218 O.keys = Lang._isNative(Object.keys) ? Object.keys : function (obj) {
       
  3219     if (!Lang.isObject(obj)) {
       
  3220         throw new TypeError('Object.keys called on a non-object');
       
  3221     }
       
  3222 
       
  3223     var keys = [],
       
  3224         i, key, len;
       
  3225 
       
  3226     if (hasProtoEnumBug && typeof obj === 'function') {
       
  3227         for (key in obj) {
       
  3228             if (owns(obj, key) && key !== 'prototype') {
       
  3229                 keys.push(key);
       
  3230             }
       
  3231         }
       
  3232     } else {
       
  3233         for (key in obj) {
       
  3234             if (owns(obj, key)) {
       
  3235                 keys.push(key);
       
  3236             }
       
  3237         }
       
  3238     }
       
  3239 
       
  3240     if (hasEnumBug) {
       
  3241         for (i = 0, len = forceEnum.length; i < len; ++i) {
       
  3242             key = forceEnum[i];
       
  3243 
       
  3244             if (owns(obj, key)) {
       
  3245                 keys.push(key);
       
  3246             }
       
  3247         }
       
  3248     }
       
  3249 
       
  3250     return keys;
       
  3251 };
       
  3252 
       
  3253 /**
       
  3254  * Returns an array containing the values of the object's enumerable keys.
       
  3255  *
       
  3256  * Note that values are returned in enumeration order (that is, in the same
       
  3257  * order that they would be enumerated by a `for-in` loop), which may not be the
       
  3258  * same as the order in which they were defined.
       
  3259  *
       
  3260  * @example
       
  3261  *
       
  3262  *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
       
  3263  *     // => ['foo', 'bar', 'baz']
       
  3264  *
       
  3265  * @method values
       
  3266  * @param {Object} obj An object.
       
  3267  * @return {Array} Array of values.
       
  3268  * @static
       
  3269  */
       
  3270 O.values = function (obj) {
       
  3271     var keys   = O.keys(obj),
       
  3272         i      = 0,
       
  3273         len    = keys.length,
       
  3274         values = [];
       
  3275 
       
  3276     for (; i < len; ++i) {
       
  3277         values.push(obj[keys[i]]);
       
  3278     }
       
  3279 
       
  3280     return values;
       
  3281 };
       
  3282 
       
  3283 /**
       
  3284  * Returns the number of enumerable keys owned by an object.
       
  3285  *
       
  3286  * @method size
       
  3287  * @param {Object} obj An object.
       
  3288  * @return {Number} The object's size.
       
  3289  * @static
       
  3290  */
       
  3291 O.size = function (obj) {
       
  3292     try {
       
  3293         return O.keys(obj).length;
       
  3294     } catch (ex) {
       
  3295         return 0; // Legacy behavior for non-objects.
       
  3296     }
       
  3297 };
       
  3298 
       
  3299 /**
       
  3300  * Returns `true` if the object owns an enumerable property with the specified
       
  3301  * value.
       
  3302  *
       
  3303  * @method hasValue
       
  3304  * @param {Object} obj An object.
       
  3305  * @param {any} value The value to search for.
       
  3306  * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
       
  3307  * @static
       
  3308  */
       
  3309 O.hasValue = function (obj, value) {
       
  3310     return Y.Array.indexOf(O.values(obj), value) > -1;
       
  3311 };
       
  3312 
       
  3313 /**
       
  3314  * Executes a function on each enumerable property in _obj_. The function
       
  3315  * receives the value, the key, and the object itself as parameters (in that
       
  3316  * order).
       
  3317  *
       
  3318  * By default, only properties owned by _obj_ are enumerated. To include
       
  3319  * prototype properties, set the _proto_ parameter to `true`.
       
  3320  *
       
  3321  * @method each
       
  3322  * @param {Object} obj Object to enumerate.
       
  3323  * @param {Function} fn Function to execute on each enumerable property.
       
  3324  *   @param {mixed} fn.value Value of the current property.
       
  3325  *   @param {String} fn.key Key of the current property.
       
  3326  *   @param {Object} fn.obj Object being enumerated.
       
  3327  * @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  3328  * @param {Boolean} [proto=false] Include prototype properties.
       
  3329  * @return {YUI} the YUI instance.
       
  3330  * @chainable
       
  3331  * @static
       
  3332  */
       
  3333 O.each = function (obj, fn, thisObj, proto) {
       
  3334     var key;
       
  3335 
       
  3336     for (key in obj) {
       
  3337         if (proto || owns(obj, key)) {
       
  3338             fn.call(thisObj || Y, obj[key], key, obj);
       
  3339         }
       
  3340     }
       
  3341 
       
  3342     return Y;
       
  3343 };
       
  3344 
       
  3345 /**
       
  3346  * Executes a function on each enumerable property in _obj_, but halts if the
       
  3347  * function returns a truthy value. The function receives the value, the key,
       
  3348  * and the object itself as paramters (in that order).
       
  3349  *
       
  3350  * By default, only properties owned by _obj_ are enumerated. To include
       
  3351  * prototype properties, set the _proto_ parameter to `true`.
       
  3352  *
       
  3353  * @method some
       
  3354  * @param {Object} obj Object to enumerate.
       
  3355  * @param {Function} fn Function to execute on each enumerable property.
       
  3356  *   @param {mixed} fn.value Value of the current property.
       
  3357  *   @param {String} fn.key Key of the current property.
       
  3358  *   @param {Object} fn.obj Object being enumerated.
       
  3359  * @param {Object} [thisObj] `this` object to use when calling _fn_.
       
  3360  * @param {Boolean} [proto=false] Include prototype properties.
       
  3361  * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
       
  3362  *   `false` otherwise.
       
  3363  * @static
       
  3364  */
       
  3365 O.some = function (obj, fn, thisObj, proto) {
       
  3366     var key;
       
  3367 
       
  3368     for (key in obj) {
       
  3369         if (proto || owns(obj, key)) {
       
  3370             if (fn.call(thisObj || Y, obj[key], key, obj)) {
       
  3371                 return true;
       
  3372             }
       
  3373         }
       
  3374     }
       
  3375 
       
  3376     return false;
       
  3377 };
       
  3378 
       
  3379 /**
       
  3380  * Retrieves the sub value at the provided path,
       
  3381  * from the value object provided.
       
  3382  *
       
  3383  * @method getValue
       
  3384  * @static
       
  3385  * @param o The object from which to extract the property value.
       
  3386  * @param path {Array} A path array, specifying the object traversal path
       
  3387  * from which to obtain the sub value.
       
  3388  * @return {Any} The value stored in the path, undefined if not found,
       
  3389  * undefined if the source is not an object.  Returns the source object
       
  3390  * if an empty path is provided.
       
  3391  */
       
  3392 O.getValue = function(o, path) {
       
  3393     if (!Lang.isObject(o)) {
       
  3394         return UNDEFINED;
       
  3395     }
       
  3396 
       
  3397     var i,
       
  3398         p = Y.Array(path),
       
  3399         l = p.length;
       
  3400 
       
  3401     for (i = 0; o !== UNDEFINED && i < l; i++) {
       
  3402         o = o[p[i]];
       
  3403     }
       
  3404 
       
  3405     return o;
       
  3406 };
       
  3407 
       
  3408 /**
       
  3409  * Sets the sub-attribute value at the provided path on the
       
  3410  * value object.  Returns the modified value object, or
       
  3411  * undefined if the path is invalid.
       
  3412  *
       
  3413  * @method setValue
       
  3414  * @static
       
  3415  * @param o             The object on which to set the sub value.
       
  3416  * @param path {Array}  A path array, specifying the object traversal path
       
  3417  *                      at which to set the sub value.
       
  3418  * @param val {Any}     The new value for the sub-attribute.
       
  3419  * @return {Object}     The modified object, with the new sub value set, or
       
  3420  *                      undefined, if the path was invalid.
       
  3421  */
       
  3422 O.setValue = function(o, path, val) {
       
  3423     var i,
       
  3424         p = Y.Array(path),
       
  3425         leafIdx = p.length - 1,
       
  3426         ref = o;
       
  3427 
       
  3428     if (leafIdx >= 0) {
       
  3429         for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
       
  3430             ref = ref[p[i]];
       
  3431         }
       
  3432 
       
  3433         if (ref !== UNDEFINED) {
       
  3434             ref[p[i]] = val;
       
  3435         } else {
       
  3436             return UNDEFINED;
       
  3437         }
       
  3438     }
       
  3439 
       
  3440     return o;
       
  3441 };
       
  3442 
       
  3443 /**
       
  3444  * Returns `true` if the object has no enumerable properties of its own.
       
  3445  *
       
  3446  * @method isEmpty
       
  3447  * @param {Object} obj An object.
       
  3448  * @return {Boolean} `true` if the object is empty.
       
  3449  * @static
       
  3450  * @since 3.2.0
       
  3451  */
       
  3452 O.isEmpty = function (obj) {
       
  3453     return !O.keys(Object(obj)).length;
       
  3454 };
       
  3455 /**
       
  3456  * The YUI module contains the components required for building the YUI seed
       
  3457  * file.  This includes the script loading mechanism, a simple queue, and the
       
  3458  * core utilities for the library.
       
  3459  * @module yui
       
  3460  * @submodule yui-base
       
  3461  */
       
  3462 
       
  3463 /**
       
  3464  * YUI user agent detection.
       
  3465  * Do not fork for a browser if it can be avoided.  Use feature detection when
       
  3466  * you can.  Use the user agent as a last resort.  For all fields listed
       
  3467  * as @type float, UA stores a version number for the browser engine,
       
  3468  * 0 otherwise.  This value may or may not map to the version number of
       
  3469  * the browser using the engine.  The value is presented as a float so
       
  3470  * that it can easily be used for boolean evaluation as well as for
       
  3471  * looking for a particular range of versions.  Because of this,
       
  3472  * some of the granularity of the version info may be lost.  The fields that
       
  3473  * are @type string default to null.  The API docs list the values that
       
  3474  * these fields can have.
       
  3475  * @class UA
       
  3476  * @static
       
  3477  */
       
  3478 
       
  3479 /**
       
  3480 * Static method on `YUI.Env` for parsing a UA string.  Called at instantiation
       
  3481 * to populate `Y.UA`.
       
  3482 *
       
  3483 * @static
       
  3484 * @method parseUA
       
  3485 * @param {String} [subUA=navigator.userAgent] UA string to parse
       
  3486 * @return {Object} The Y.UA object
       
  3487 */
       
  3488 YUI.Env.parseUA = function(subUA) {
       
  3489 
       
  3490     var numberify = function(s) {
       
  3491             var c = 0;
       
  3492             return parseFloat(s.replace(/\./g, function() {
       
  3493                 return (c++ === 1) ? '' : '.';
       
  3494             }));
       
  3495         },
       
  3496 
       
  3497         win = Y.config.win,
       
  3498 
       
  3499         nav = win && win.navigator,
       
  3500 
       
  3501         o = {
       
  3502 
       
  3503         /**
       
  3504          * Internet Explorer version number or 0.  Example: 6
       
  3505          * @property ie
       
  3506          * @type float
       
  3507          * @static
       
  3508          */
       
  3509         ie: 0,
       
  3510 
       
  3511         /**
       
  3512          * Opera version number or 0.  Example: 9.2
       
  3513          * @property opera
       
  3514          * @type float
       
  3515          * @static
       
  3516          */
       
  3517         opera: 0,
       
  3518 
       
  3519         /**
       
  3520          * Gecko engine revision number.  Will evaluate to 1 if Gecko
       
  3521          * is detected but the revision could not be found. Other browsers
       
  3522          * will be 0.  Example: 1.8
       
  3523          * <pre>
       
  3524          * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
       
  3525          * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
       
  3526          * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
       
  3527          * Firefox 3.0   <-- 1.9
       
  3528          * Firefox 3.5   <-- 1.91
       
  3529          * </pre>
       
  3530          * @property gecko
       
  3531          * @type float
       
  3532          * @static
       
  3533          */
       
  3534         gecko: 0,
       
  3535 
       
  3536         /**
       
  3537          * AppleWebKit version.  KHTML browsers that are not WebKit browsers
       
  3538          * will evaluate to 1, other browsers 0.  Example: 418.9
       
  3539          * <pre>
       
  3540          * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
       
  3541          *                                   latest available for Mac OSX 10.3.
       
  3542          * Safari 2.0.2:         416     <-- hasOwnProperty introduced
       
  3543          * Safari 2.0.4:         418     <-- preventDefault fixed
       
  3544          * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
       
  3545          *                                   different versions of webkit
       
  3546          * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
       
  3547          *                                   updated, but not updated
       
  3548          *                                   to the latest patch.
       
  3549          * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
       
  3550          * SVG and many major issues fixed).
       
  3551          * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
       
  3552          * update from 2.x via the 10.4.11 OS patch.
       
  3553          * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
       
  3554          *                                   yahoo.com user agent hack removed.
       
  3555          * </pre>
       
  3556          * http://en.wikipedia.org/wiki/Safari_version_history
       
  3557          * @property webkit
       
  3558          * @type float
       
  3559          * @static
       
  3560          */
       
  3561         webkit: 0,
       
  3562 
       
  3563         /**
       
  3564          * Safari will be detected as webkit, but this property will also
       
  3565          * be populated with the Safari version number
       
  3566          * @property safari
       
  3567          * @type float
       
  3568          * @static
       
  3569          */
       
  3570         safari: 0,
       
  3571 
       
  3572         /**
       
  3573          * Chrome will be detected as webkit, but this property will also
       
  3574          * be populated with the Chrome version number
       
  3575          * @property chrome
       
  3576          * @type float
       
  3577          * @static
       
  3578          */
       
  3579         chrome: 0,
       
  3580 
       
  3581         /**
       
  3582          * The mobile property will be set to a string containing any relevant
       
  3583          * user agent information when a modern mobile browser is detected.
       
  3584          * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
       
  3585          * devices with the WebKit-based browser, and Opera Mini.
       
  3586          * @property mobile
       
  3587          * @type string
       
  3588          * @default null
       
  3589          * @static
       
  3590          */
       
  3591         mobile: null,
       
  3592 
       
  3593         /**
       
  3594          * Adobe AIR version number or 0.  Only populated if webkit is detected.
       
  3595          * Example: 1.0
       
  3596          * @property air
       
  3597          * @type float
       
  3598          */
       
  3599         air: 0,
       
  3600         /**
       
  3601          * PhantomJS version number or 0.  Only populated if webkit is detected.
       
  3602          * Example: 1.0
       
  3603          * @property phantomjs
       
  3604          * @type float
       
  3605          */
       
  3606         phantomjs: 0,
       
  3607         /**
       
  3608          * Detects Apple iPad's OS version
       
  3609          * @property ipad
       
  3610          * @type float
       
  3611          * @static
       
  3612          */
       
  3613         ipad: 0,
       
  3614         /**
       
  3615          * Detects Apple iPhone's OS version
       
  3616          * @property iphone
       
  3617          * @type float
       
  3618          * @static
       
  3619          */
       
  3620         iphone: 0,
       
  3621         /**
       
  3622          * Detects Apples iPod's OS version
       
  3623          * @property ipod
       
  3624          * @type float
       
  3625          * @static
       
  3626          */
       
  3627         ipod: 0,
       
  3628         /**
       
  3629          * General truthy check for iPad, iPhone or iPod
       
  3630          * @property ios
       
  3631          * @type Boolean
       
  3632          * @default null
       
  3633          * @static
       
  3634          */
       
  3635         ios: null,
       
  3636         /**
       
  3637          * Detects Googles Android OS version
       
  3638          * @property android
       
  3639          * @type float
       
  3640          * @static
       
  3641          */
       
  3642         android: 0,
       
  3643         /**
       
  3644          * Detects Kindle Silk
       
  3645          * @property silk
       
  3646          * @type float
       
  3647          * @static
       
  3648          */
       
  3649         silk: 0,
       
  3650         /**
       
  3651          * Detects Kindle Silk Acceleration
       
  3652          * @property accel
       
  3653          * @type Boolean
       
  3654          * @static
       
  3655          */
       
  3656         accel: false,
       
  3657         /**
       
  3658          * Detects Palms WebOS version
       
  3659          * @property webos
       
  3660          * @type float
       
  3661          * @static
       
  3662          */
       
  3663         webos: 0,
       
  3664 
       
  3665         /**
       
  3666          * Google Caja version number or 0.
       
  3667          * @property caja
       
  3668          * @type float
       
  3669          */
       
  3670         caja: nav && nav.cajaVersion,
       
  3671 
       
  3672         /**
       
  3673          * Set to true if the page appears to be in SSL
       
  3674          * @property secure
       
  3675          * @type boolean
       
  3676          * @static
       
  3677          */
       
  3678         secure: false,
       
  3679 
       
  3680         /**
       
  3681          * The operating system.  Currently only detecting windows or macintosh
       
  3682          * @property os
       
  3683          * @type string
       
  3684          * @default null
       
  3685          * @static
       
  3686          */
       
  3687         os: null,
       
  3688 
       
  3689         /**
       
  3690          * The Nodejs Version
       
  3691          * @property nodejs
       
  3692          * @type float
       
  3693          * @default 0
       
  3694          * @static
       
  3695          */
       
  3696         nodejs: 0,
       
  3697         /**
       
  3698         * Window8/IE10 Application host environment
       
  3699         * @property winjs
       
  3700         * @type Boolean
       
  3701         * @static
       
  3702         */
       
  3703         winjs: !!((typeof Windows !== "undefined") && Windows.System),
       
  3704         /**
       
  3705         * Are touch/msPointer events available on this device
       
  3706         * @property touchEnabled
       
  3707         * @type Boolean
       
  3708         * @static
       
  3709         */
       
  3710         touchEnabled: false
       
  3711     },
       
  3712 
       
  3713     ua = subUA || nav && nav.userAgent,
       
  3714 
       
  3715     loc = win && win.location,
       
  3716 
       
  3717     href = loc && loc.href,
       
  3718 
       
  3719     m;
       
  3720 
       
  3721     /**
       
  3722     * The User Agent string that was parsed
       
  3723     * @property userAgent
       
  3724     * @type String
       
  3725     * @static
       
  3726     */
       
  3727     o.userAgent = ua;
       
  3728 
       
  3729 
       
  3730     o.secure = href && (href.toLowerCase().indexOf('https') === 0);
       
  3731 
       
  3732     if (ua) {
       
  3733 
       
  3734         if ((/windows|win32/i).test(ua)) {
       
  3735             o.os = 'windows';
       
  3736         } else if ((/macintosh|mac_powerpc/i).test(ua)) {
       
  3737             o.os = 'macintosh';
       
  3738         } else if ((/android/i).test(ua)) {
       
  3739             o.os = 'android';
       
  3740         } else if ((/symbos/i).test(ua)) {
       
  3741             o.os = 'symbos';
       
  3742         } else if ((/linux/i).test(ua)) {
       
  3743             o.os = 'linux';
       
  3744         } else if ((/rhino/i).test(ua)) {
       
  3745             o.os = 'rhino';
       
  3746         }
       
  3747 
       
  3748         // Modern KHTML browsers should qualify as Safari X-Grade
       
  3749         if ((/KHTML/).test(ua)) {
       
  3750             o.webkit = 1;
       
  3751         }
       
  3752         if ((/IEMobile|XBLWP7/).test(ua)) {
       
  3753             o.mobile = 'windows';
       
  3754         }
       
  3755         if ((/Fennec/).test(ua)) {
       
  3756             o.mobile = 'gecko';
       
  3757         }
       
  3758         // Modern WebKit browsers are at least X-Grade
       
  3759         m = ua.match(/AppleWebKit\/([^\s]*)/);
       
  3760         if (m && m[1]) {
       
  3761             o.webkit = numberify(m[1]);
       
  3762             o.safari = o.webkit;
       
  3763 
       
  3764             if (/PhantomJS/.test(ua)) {
       
  3765                 m = ua.match(/PhantomJS\/([^\s]*)/);
       
  3766                 if (m && m[1]) {
       
  3767                     o.phantomjs = numberify(m[1]);
       
  3768                 }
       
  3769             }
       
  3770 
       
  3771             // Mobile browser check
       
  3772             if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
       
  3773                 o.mobile = 'Apple'; // iPhone or iPod Touch
       
  3774 
       
  3775                 m = ua.match(/OS ([^\s]*)/);
       
  3776                 if (m && m[1]) {
       
  3777                     m = numberify(m[1].replace('_', '.'));
       
  3778                 }
       
  3779                 o.ios = m;
       
  3780                 o.os = 'ios';
       
  3781                 o.ipad = o.ipod = o.iphone = 0;
       
  3782 
       
  3783                 m = ua.match(/iPad|iPod|iPhone/);
       
  3784                 if (m && m[0]) {
       
  3785                     o[m[0].toLowerCase()] = o.ios;
       
  3786                 }
       
  3787             } else {
       
  3788                 m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
       
  3789                 if (m) {
       
  3790                     // Nokia N-series, webOS, ex: NokiaN95
       
  3791                     o.mobile = m[0];
       
  3792                 }
       
  3793                 if (/webOS/.test(ua)) {
       
  3794                     o.mobile = 'WebOS';
       
  3795                     m = ua.match(/webOS\/([^\s]*);/);
       
  3796                     if (m && m[1]) {
       
  3797                         o.webos = numberify(m[1]);
       
  3798                     }
       
  3799                 }
       
  3800                 if (/ Android/.test(ua)) {
       
  3801                     if (/Mobile/.test(ua)) {
       
  3802                         o.mobile = 'Android';
       
  3803                     }
       
  3804                     m = ua.match(/Android ([^\s]*);/);
       
  3805                     if (m && m[1]) {
       
  3806                         o.android = numberify(m[1]);
       
  3807                     }
       
  3808 
       
  3809                 }
       
  3810                 if (/Silk/.test(ua)) {
       
  3811                     m = ua.match(/Silk\/([^\s]*)\)/);
       
  3812                     if (m && m[1]) {
       
  3813                         o.silk = numberify(m[1]);
       
  3814                     }
       
  3815                     if (!o.android) {
       
  3816                         o.android = 2.34; //Hack for desktop mode in Kindle
       
  3817                         o.os = 'Android';
       
  3818                     }
       
  3819                     if (/Accelerated=true/.test(ua)) {
       
  3820                         o.accel = true;
       
  3821                     }
       
  3822                 }
       
  3823             }
       
  3824 
       
  3825             m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
       
  3826             if (m && m[1] && m[2]) {
       
  3827                 o.chrome = numberify(m[2]); // Chrome
       
  3828                 o.safari = 0; //Reset safari back to 0
       
  3829                 if (m[1] === 'CrMo') {
       
  3830                     o.mobile = 'chrome';
       
  3831                 }
       
  3832             } else {
       
  3833                 m = ua.match(/AdobeAIR\/([^\s]*)/);
       
  3834                 if (m) {
       
  3835                     o.air = m[0]; // Adobe AIR 1.0 or better
       
  3836                 }
       
  3837             }
       
  3838         }
       
  3839 
       
  3840         if (!o.webkit) { // not webkit
       
  3841 // @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
       
  3842             if (/Opera/.test(ua)) {
       
  3843                 m = ua.match(/Opera[\s\/]([^\s]*)/);
       
  3844                 if (m && m[1]) {
       
  3845                     o.opera = numberify(m[1]);
       
  3846                 }
       
  3847                 m = ua.match(/Version\/([^\s]*)/);
       
  3848                 if (m && m[1]) {
       
  3849                     o.opera = numberify(m[1]); // opera 10+
       
  3850                 }
       
  3851 
       
  3852                 if (/Opera Mobi/.test(ua)) {
       
  3853                     o.mobile = 'opera';
       
  3854                     m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
       
  3855                     if (m && m[1]) {
       
  3856                         o.opera = numberify(m[1]);
       
  3857                     }
       
  3858                 }
       
  3859                 m = ua.match(/Opera Mini[^;]*/);
       
  3860 
       
  3861                 if (m) {
       
  3862                     o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
       
  3863                 }
       
  3864             } else { // not opera or webkit
       
  3865                 m = ua.match(/MSIE\s([^;]*)/);
       
  3866                 if (m && m[1]) {
       
  3867                     o.ie = numberify(m[1]);
       
  3868                 } else { // not opera, webkit, or ie
       
  3869                     m = ua.match(/Gecko\/([^\s]*)/);
       
  3870                     if (m) {
       
  3871                         o.gecko = 1; // Gecko detected, look for revision
       
  3872                         m = ua.match(/rv:([^\s\)]*)/);
       
  3873                         if (m && m[1]) {
       
  3874                             o.gecko = numberify(m[1]);
       
  3875                             if (/Mobile|Tablet/.test(ua)) {
       
  3876                                 o.mobile = "ffos";
       
  3877                             }
       
  3878                         }
       
  3879                     }
       
  3880                 }
       
  3881             }
       
  3882         }
       
  3883     }
       
  3884 
       
  3885     //Check for known properties to tell if touch events are enabled on this device or if
       
  3886     //the number of MSPointer touchpoints on this device is greater than 0.
       
  3887     if (win && nav && !(o.chrome && o.chrome < 6)) {
       
  3888         o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
       
  3889     }
       
  3890 
       
  3891     //It was a parsed UA, do not assign the global value.
       
  3892     if (!subUA) {
       
  3893 
       
  3894         if (typeof process === 'object') {
       
  3895 
       
  3896             if (process.versions && process.versions.node) {
       
  3897                 //NodeJS
       
  3898                 o.os = process.platform;
       
  3899                 o.nodejs = numberify(process.versions.node);
       
  3900             }
       
  3901         }
       
  3902 
       
  3903         YUI.Env.UA = o;
       
  3904 
       
  3905     }
       
  3906 
       
  3907     return o;
       
  3908 };
       
  3909 
       
  3910 
       
  3911 Y.UA = YUI.Env.UA || YUI.Env.parseUA();
       
  3912 
       
  3913 /**
       
  3914 Performs a simple comparison between two version numbers, accounting for
       
  3915 standard versioning logic such as the fact that "535.8" is a lower version than
       
  3916 "535.24", even though a simple numerical comparison would indicate that it's
       
  3917 greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
       
  3918 considered equivalent.
       
  3919 
       
  3920 Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
       
  3921 1 if _a_ is higher than _b_.
       
  3922 
       
  3923 Versions may be numbers or strings containing numbers and dots. For example,
       
  3924 both `535` and `"535.8.10"` are acceptable. A version string containing
       
  3925 non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
       
  3926 
       
  3927 @method compareVersions
       
  3928 @param {Number|String} a First version number to compare.
       
  3929 @param {Number|String} b Second version number to compare.
       
  3930 @return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
       
  3931     higher than _b_.
       
  3932 **/
       
  3933 Y.UA.compareVersions = function (a, b) {
       
  3934     var aPart, aParts, bPart, bParts, i, len;
       
  3935 
       
  3936     if (a === b) {
       
  3937         return 0;
       
  3938     }
       
  3939 
       
  3940     aParts = (a + '').split('.');
       
  3941     bParts = (b + '').split('.');
       
  3942 
       
  3943     for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
       
  3944         aPart = parseInt(aParts[i], 10);
       
  3945         bPart = parseInt(bParts[i], 10);
       
  3946 
       
  3947         /*jshint expr: true*/
       
  3948         isNaN(aPart) && (aPart = 0);
       
  3949         isNaN(bPart) && (bPart = 0);
       
  3950 
       
  3951         if (aPart < bPart) {
       
  3952             return -1;
       
  3953         }
       
  3954 
       
  3955         if (aPart > bPart) {
       
  3956             return 1;
       
  3957         }
       
  3958     }
       
  3959 
       
  3960     return 0;
       
  3961 };
       
  3962 YUI.Env.aliases = {
       
  3963     "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
       
  3964     "anim-shape-transform": ["anim-shape"],
       
  3965     "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],
       
  3966     "attribute": ["attribute-base","attribute-complex"],
       
  3967     "attribute-events": ["attribute-observable"],
       
  3968     "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
       
  3969     "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
       
  3970     "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
       
  3971     "base": ["base-base","base-pluginhost","base-build"],
       
  3972     "cache": ["cache-base","cache-offline","cache-plugin"],
       
  3973     "charts": ["charts-base"],
       
  3974     "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
       
  3975     "color": ["color-base","color-hsl","color-harmony"],
       
  3976     "controller": ["router"],
       
  3977     "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
       
  3978     "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
       
  3979     "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
       
  3980     "datatype": ["datatype-date","datatype-number","datatype-xml"],
       
  3981     "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
       
  3982     "datatype-number": ["datatype-number-parse","datatype-number-format"],
       
  3983     "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
       
  3984     "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
       
  3985     "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
       
  3986     "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
       
  3987     "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"],
       
  3988     "event-custom": ["event-custom-base","event-custom-complex"],
       
  3989     "event-gestures": ["event-flick","event-move"],
       
  3990     "handlebars": ["handlebars-compiler"],
       
  3991     "highlight": ["highlight-base","highlight-accentfold"],
       
  3992     "history": ["history-base","history-hash","history-hash-ie","history-html5"],
       
  3993     "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
       
  3994     "json": ["json-parse","json-stringify"],
       
  3995     "loader": ["loader-base","loader-rollup","loader-yui3"],
       
  3996     "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
       
  3997     "pluginhost": ["pluginhost-base","pluginhost-config"],
       
  3998     "querystring": ["querystring-parse","querystring-stringify"],
       
  3999     "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
       
  4000     "resize": ["resize-base","resize-proxy","resize-constrain"],
       
  4001     "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
       
  4002     "template": ["template-base","template-micro"],
       
  4003     "text": ["text-accentfold","text-wordbreak"],
       
  4004     "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
       
  4005 };
       
  4006 
       
  4007 
       
  4008 }, '@VERSION@', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
       
  4009 YUI.add('get', function (Y, NAME) {
       
  4010 
       
  4011 /*jslint boss:true, expr:true, laxbreak: true */
       
  4012 
       
  4013 /**
       
  4014 Provides dynamic loading of remote JavaScript and CSS resources.
       
  4015 
       
  4016 @module get
       
  4017 @class Get
       
  4018 @static
       
  4019 **/
       
  4020 
       
  4021 var Lang = Y.Lang,
       
  4022 
       
  4023     CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
       
  4024 
       
  4025     Get, Transaction;
       
  4026 
       
  4027 Y.Get = Get = {
       
  4028     // -- Public Properties ----------------------------------------------------
       
  4029 
       
  4030     /**
       
  4031     Default options for CSS requests. Options specified here will override
       
  4032     global defaults for CSS requests.
       
  4033 
       
  4034     See the `options` property for all available options.
       
  4035 
       
  4036     @property cssOptions
       
  4037     @type Object
       
  4038     @static
       
  4039     @since 3.5.0
       
  4040     **/
       
  4041     cssOptions: {
       
  4042         attributes: {
       
  4043             rel: 'stylesheet'
       
  4044         },
       
  4045 
       
  4046         doc         : Y.config.linkDoc || Y.config.doc,
       
  4047         pollInterval: 50
       
  4048     },
       
  4049 
       
  4050     /**
       
  4051     Default options for JS requests. Options specified here will override global
       
  4052     defaults for JS requests.
       
  4053 
       
  4054     See the `options` property for all available options.
       
  4055 
       
  4056     @property jsOptions
       
  4057     @type Object
       
  4058     @static
       
  4059     @since 3.5.0
       
  4060     **/
       
  4061     jsOptions: {
       
  4062         autopurge: true,
       
  4063         doc      : Y.config.scriptDoc || Y.config.doc
       
  4064     },
       
  4065 
       
  4066     /**
       
  4067     Default options to use for all requests.
       
  4068 
       
  4069     Note that while all available options are documented here for ease of
       
  4070     discovery, some options (like callback functions) only make sense at the
       
  4071     transaction level.
       
  4072 
       
  4073     Callback functions specified via the options object or the `options`
       
  4074     parameter of the `css()`, `js()`, or `load()` methods will receive the
       
  4075     transaction object as a parameter. See `Y.Get.Transaction` for details on
       
  4076     the properties and methods available on transactions.
       
  4077 
       
  4078     @static
       
  4079     @since 3.5.0
       
  4080     @property {Object} options
       
  4081 
       
  4082     @property {Boolean} [options.async=false] Whether or not to load scripts
       
  4083         asynchronously, meaning they're requested in parallel and execution
       
  4084         order is not guaranteed. Has no effect on CSS, since CSS is always
       
  4085         loaded asynchronously.
       
  4086 
       
  4087     @property {Object} [options.attributes] HTML attribute name/value pairs that
       
  4088         should be added to inserted nodes. By default, the `charset` attribute
       
  4089         will be set to "utf-8" and nodes will be given an auto-generated `id`
       
  4090         attribute, but you can override these with your own values if desired.
       
  4091 
       
  4092     @property {Boolean} [options.autopurge] Whether or not to automatically
       
  4093         purge inserted nodes after the purge threshold is reached. This is
       
  4094         `true` by default for JavaScript, but `false` for CSS since purging a
       
  4095         CSS node will also remove any styling applied by the referenced file.
       
  4096 
       
  4097     @property {Object} [options.context] `this` object to use when calling
       
  4098         callback functions. Defaults to the transaction object.
       
  4099 
       
  4100     @property {Mixed} [options.data] Arbitrary data object to pass to "on*"
       
  4101         callbacks.
       
  4102 
       
  4103     @property {Document} [options.doc] Document into which nodes should be
       
  4104         inserted. By default, the current document is used.
       
  4105 
       
  4106     @property {HTMLElement|String} [options.insertBefore] HTML element or id
       
  4107         string of an element before which all generated nodes should be
       
  4108         inserted. If not specified, Get will automatically determine the best
       
  4109         place to insert nodes for maximum compatibility.
       
  4110 
       
  4111     @property {Function} [options.onEnd] Callback to execute after a transaction
       
  4112         is complete, regardless of whether it succeeded or failed.
       
  4113 
       
  4114     @property {Function} [options.onFailure] Callback to execute after a
       
  4115         transaction fails, times out, or is aborted.
       
  4116 
       
  4117     @property {Function} [options.onProgress] Callback to execute after each
       
  4118         individual request in a transaction either succeeds or fails.
       
  4119 
       
  4120     @property {Function} [options.onSuccess] Callback to execute after a
       
  4121         transaction completes successfully with no errors. Note that in browsers
       
  4122         that don't support the `error` event on CSS `<link>` nodes, a failed CSS
       
  4123         request may still be reported as a success because in these browsers
       
  4124         it can be difficult or impossible to distinguish between success and
       
  4125         failure for CSS resources.
       
  4126 
       
  4127     @property {Function} [options.onTimeout] Callback to execute after a
       
  4128         transaction times out.
       
  4129 
       
  4130     @property {Number} [options.pollInterval=50] Polling interval (in
       
  4131         milliseconds) for detecting CSS load completion in browsers that don't
       
  4132         support the `load` event on `<link>` nodes. This isn't used for
       
  4133         JavaScript.
       
  4134 
       
  4135     @property {Number} [options.purgethreshold=20] Number of nodes to insert
       
  4136         before triggering an automatic purge when `autopurge` is `true`.
       
  4137 
       
  4138     @property {Number} [options.timeout] Number of milliseconds to wait before
       
  4139         aborting a transaction. When a timeout occurs, the `onTimeout` callback
       
  4140         is called, followed by `onFailure` and finally `onEnd`. By default,
       
  4141         there is no timeout.
       
  4142 
       
  4143     @property {String} [options.type] Resource type ("css" or "js"). This option
       
  4144         is set automatically by the `css()` and `js()` functions and will be
       
  4145         ignored there, but may be useful when using the `load()` function. If
       
  4146         not specified, the type will be inferred from the URL, defaulting to
       
  4147         "js" if the URL doesn't contain a recognizable file extension.
       
  4148     **/
       
  4149     options: {
       
  4150         attributes: {
       
  4151             charset: 'utf-8'
       
  4152         },
       
  4153 
       
  4154         purgethreshold: 20
       
  4155     },
       
  4156 
       
  4157     // -- Protected Properties -------------------------------------------------
       
  4158 
       
  4159     /**
       
  4160     Regex that matches a CSS URL. Used to guess the file type when it's not
       
  4161     specified.
       
  4162 
       
  4163     @property REGEX_CSS
       
  4164     @type RegExp
       
  4165     @final
       
  4166     @protected
       
  4167     @static
       
  4168     @since 3.5.0
       
  4169     **/
       
  4170     REGEX_CSS: /\.css(?:[?;].*)?$/i,
       
  4171 
       
  4172     /**
       
  4173     Regex that matches a JS URL. Used to guess the file type when it's not
       
  4174     specified.
       
  4175 
       
  4176     @property REGEX_JS
       
  4177     @type RegExp
       
  4178     @final
       
  4179     @protected
       
  4180     @static
       
  4181     @since 3.5.0
       
  4182     **/
       
  4183     REGEX_JS : /\.js(?:[?;].*)?$/i,
       
  4184 
       
  4185     /**
       
  4186     Contains information about the current environment, such as what script and
       
  4187     link injection features it supports.
       
  4188 
       
  4189     This object is created and populated the first time the `_getEnv()` method
       
  4190     is called.
       
  4191 
       
  4192     @property _env
       
  4193     @type Object
       
  4194     @protected
       
  4195     @static
       
  4196     @since 3.5.0
       
  4197     **/
       
  4198 
       
  4199     /**
       
  4200     Mapping of document _yuid strings to <head> or <base> node references so we
       
  4201     don't have to look the node up each time we want to insert a request node.
       
  4202 
       
  4203     @property _insertCache
       
  4204     @type Object
       
  4205     @protected
       
  4206     @static
       
  4207     @since 3.5.0
       
  4208     **/
       
  4209     _insertCache: {},
       
  4210 
       
  4211     /**
       
  4212     Information about the currently pending transaction, if any.
       
  4213 
       
  4214     This is actually an object with two properties: `callback`, containing the
       
  4215     optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
       
  4216     containing the actual transaction instance.
       
  4217 
       
  4218     @property _pending
       
  4219     @type Object
       
  4220     @protected
       
  4221     @static
       
  4222     @since 3.5.0
       
  4223     **/
       
  4224     _pending: null,
       
  4225 
       
  4226     /**
       
  4227     HTML nodes eligible to be purged next time autopurge is triggered.
       
  4228 
       
  4229     @property _purgeNodes
       
  4230     @type HTMLElement[]
       
  4231     @protected
       
  4232     @static
       
  4233     @since 3.5.0
       
  4234     **/
       
  4235     _purgeNodes: [],
       
  4236 
       
  4237     /**
       
  4238     Queued transactions and associated callbacks.
       
  4239 
       
  4240     @property _queue
       
  4241     @type Object[]
       
  4242     @protected
       
  4243     @static
       
  4244     @since 3.5.0
       
  4245     **/
       
  4246     _queue: [],
       
  4247 
       
  4248     // -- Public Methods -------------------------------------------------------
       
  4249 
       
  4250     /**
       
  4251     Aborts the specified transaction.
       
  4252 
       
  4253     This will cause the transaction's `onFailure` callback to be called and
       
  4254     will prevent any new script and link nodes from being added to the document,
       
  4255     but any resources that have already been requested will continue loading
       
  4256     (there's no safe way to prevent this, unfortunately).
       
  4257 
       
  4258     *Note:* This method is deprecated as of 3.5.0, and will be removed in a
       
  4259     future version of YUI. Use the transaction-level `abort()` method instead.
       
  4260 
       
  4261     @method abort
       
  4262     @param {Get.Transaction} transaction Transaction to abort.
       
  4263     @deprecated Use the `abort()` method on the transaction instead.
       
  4264     @static
       
  4265     **/
       
  4266     abort: function (transaction) {
       
  4267         var i, id, item, len, pending;
       
  4268 
       
  4269         Y.log('`Y.Get.abort()` is deprecated as of 3.5.0. Use the `abort()` method on the transaction instead.', 'warn', 'get');
       
  4270 
       
  4271         if (!transaction.abort) {
       
  4272             id          = transaction;
       
  4273             pending     = this._pending;
       
  4274             transaction = null;
       
  4275 
       
  4276             if (pending && pending.transaction.id === id) {
       
  4277                 transaction   = pending.transaction;
       
  4278                 this._pending = null;
       
  4279             } else {
       
  4280                 for (i = 0, len = this._queue.length; i < len; ++i) {
       
  4281                     item = this._queue[i].transaction;
       
  4282 
       
  4283                     if (item.id === id) {
       
  4284                         transaction = item;
       
  4285                         this._queue.splice(i, 1);
       
  4286                         break;
       
  4287                     }
       
  4288                 }
       
  4289             }
       
  4290         }
       
  4291 
       
  4292         transaction && transaction.abort();
       
  4293     },
       
  4294 
       
  4295     /**
       
  4296     Loads one or more CSS files.
       
  4297 
       
  4298     The _urls_ parameter may be provided as a URL string, a request object,
       
  4299     or an array of URL strings and/or request objects.
       
  4300 
       
  4301     A request object is just an object that contains a `url` property and zero
       
  4302     or more options that should apply specifically to that request.
       
  4303     Request-specific options take priority over transaction-level options and
       
  4304     default options.
       
  4305 
       
  4306     URLs may be relative or absolute, and do not have to have the same origin
       
  4307     as the current page.
       
  4308 
       
  4309     The `options` parameter may be omitted completely and a callback passed in
       
  4310     its place, if desired.
       
  4311 
       
  4312     @example
       
  4313 
       
  4314         // Load a single CSS file and log a message on completion.
       
  4315         Y.Get.css('foo.css', function (err) {
       
  4316             if (err) {
       
  4317                 Y.log('foo.css failed to load!');
       
  4318             } else {
       
  4319                 Y.log('foo.css was loaded successfully');
       
  4320             }
       
  4321         });
       
  4322 
       
  4323         // Load multiple CSS files and log a message when all have finished
       
  4324         // loading.
       
  4325         var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
       
  4326 
       
  4327         Y.Get.css(urls, function (err) {
       
  4328             if (err) {
       
  4329                 Y.log('one or more files failed to load!');
       
  4330             } else {
       
  4331                 Y.log('all files loaded successfully');
       
  4332             }
       
  4333         });
       
  4334 
       
  4335         // Specify transaction-level options, which will apply to all requests
       
  4336         // within the transaction.
       
  4337         Y.Get.css(urls, {
       
  4338             attributes: {'class': 'my-css'},
       
  4339             timeout   : 5000
       
  4340         });
       
  4341 
       
  4342         // Specify per-request options, which override transaction-level and
       
  4343         // default options.
       
  4344         Y.Get.css([
       
  4345             {url: 'foo.css', attributes: {id: 'foo'}},
       
  4346             {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
       
  4347         ]);
       
  4348 
       
  4349     @method css
       
  4350     @param {String|Object|Array} urls URL string, request object, or array
       
  4351         of URLs and/or request objects to load.
       
  4352     @param {Object} [options] Options for this transaction. See the
       
  4353         `Y.Get.options` property for a complete list of available options.
       
  4354     @param {Function} [callback] Callback function to be called on completion.
       
  4355         This is a general callback and will be called before any more granular
       
  4356         callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
       
  4357         object.
       
  4358 
       
  4359         @param {Array|null} callback.err Array of errors that occurred during
       
  4360             the transaction, or `null` on success.
       
  4361         @param {Get.Transaction} callback.transaction Transaction object.
       
  4362 
       
  4363     @return {Get.Transaction} Transaction object.
       
  4364     @static
       
  4365     **/
       
  4366     css: function (urls, options, callback) {
       
  4367         return this._load('css', urls, options, callback);
       
  4368     },
       
  4369 
       
  4370     /**
       
  4371     Loads one or more JavaScript resources.
       
  4372 
       
  4373     The _urls_ parameter may be provided as a URL string, a request object,
       
  4374     or an array of URL strings and/or request objects.
       
  4375 
       
  4376     A request object is just an object that contains a `url` property and zero
       
  4377     or more options that should apply specifically to that request.
       
  4378     Request-specific options take priority over transaction-level options and
       
  4379     default options.
       
  4380 
       
  4381     URLs may be relative or absolute, and do not have to have the same origin
       
  4382     as the current page.
       
  4383 
       
  4384     The `options` parameter may be omitted completely and a callback passed in
       
  4385     its place, if desired.
       
  4386 
       
  4387     Scripts will be executed in the order they're specified unless the `async`
       
  4388     option is `true`, in which case they'll be loaded in parallel and executed
       
  4389     in whatever order they finish loading.
       
  4390 
       
  4391     @example
       
  4392 
       
  4393         // Load a single JS file and log a message on completion.
       
  4394         Y.Get.js('foo.js', function (err) {
       
  4395             if (err) {
       
  4396                 Y.log('foo.js failed to load!');
       
  4397             } else {
       
  4398                 Y.log('foo.js was loaded successfully');
       
  4399             }
       
  4400         });
       
  4401 
       
  4402         // Load multiple JS files, execute them in order, and log a message when
       
  4403         // all have finished loading.
       
  4404         var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
       
  4405 
       
  4406         Y.Get.js(urls, function (err) {
       
  4407             if (err) {
       
  4408                 Y.log('one or more files failed to load!');
       
  4409             } else {
       
  4410                 Y.log('all files loaded successfully');
       
  4411             }
       
  4412         });
       
  4413 
       
  4414         // Specify transaction-level options, which will apply to all requests
       
  4415         // within the transaction.
       
  4416         Y.Get.js(urls, {
       
  4417             attributes: {'class': 'my-js'},
       
  4418             timeout   : 5000
       
  4419         });
       
  4420 
       
  4421         // Specify per-request options, which override transaction-level and
       
  4422         // default options.
       
  4423         Y.Get.js([
       
  4424             {url: 'foo.js', attributes: {id: 'foo'}},
       
  4425             {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
       
  4426         ]);
       
  4427 
       
  4428     @method js
       
  4429     @param {String|Object|Array} urls URL string, request object, or array
       
  4430         of URLs and/or request objects to load.
       
  4431     @param {Object} [options] Options for this transaction. See the
       
  4432         `Y.Get.options` property for a complete list of available options.
       
  4433     @param {Function} [callback] Callback function to be called on completion.
       
  4434         This is a general callback and will be called before any more granular
       
  4435         callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
       
  4436         object.
       
  4437 
       
  4438         @param {Array|null} callback.err Array of errors that occurred during
       
  4439             the transaction, or `null` on success.
       
  4440         @param {Get.Transaction} callback.transaction Transaction object.
       
  4441 
       
  4442     @return {Get.Transaction} Transaction object.
       
  4443     @since 3.5.0
       
  4444     @static
       
  4445     **/
       
  4446     js: function (urls, options, callback) {
       
  4447         return this._load('js', urls, options, callback);
       
  4448     },
       
  4449 
       
  4450     /**
       
  4451     Loads one or more CSS and/or JavaScript resources in the same transaction.
       
  4452 
       
  4453     Use this method when you want to load both CSS and JavaScript in a single
       
  4454     transaction and be notified when all requested URLs have finished loading,
       
  4455     regardless of type.
       
  4456 
       
  4457     Behavior and options are the same as for the `css()` and `js()` methods. If
       
  4458     a resource type isn't specified in per-request options or transaction-level
       
  4459     options, Get will guess the file type based on the URL's extension (`.css`
       
  4460     or `.js`, with or without a following query string). If the file type can't
       
  4461     be guessed from the URL, a warning will be logged and Get will assume the
       
  4462     URL is a JavaScript resource.
       
  4463 
       
  4464     @example
       
  4465 
       
  4466         // Load both CSS and JS files in a single transaction, and log a message
       
  4467         // when all files have finished loading.
       
  4468         Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
       
  4469             if (err) {
       
  4470                 Y.log('one or more files failed to load!');
       
  4471             } else {
       
  4472                 Y.log('all files loaded successfully');
       
  4473             }
       
  4474         });
       
  4475 
       
  4476     @method load
       
  4477     @param {String|Object|Array} urls URL string, request object, or array
       
  4478         of URLs and/or request objects to load.
       
  4479     @param {Object} [options] Options for this transaction. See the
       
  4480         `Y.Get.options` property for a complete list of available options.
       
  4481     @param {Function} [callback] Callback function to be called on completion.
       
  4482         This is a general callback and will be called before any more granular
       
  4483         callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
       
  4484         object.
       
  4485 
       
  4486         @param {Array|null} err Array of errors that occurred during the
       
  4487             transaction, or `null` on success.
       
  4488         @param {Get.Transaction} Transaction object.
       
  4489 
       
  4490     @return {Get.Transaction} Transaction object.
       
  4491     @since 3.5.0
       
  4492     @static
       
  4493     **/
       
  4494     load: function (urls, options, callback) {
       
  4495         return this._load(null, urls, options, callback);
       
  4496     },
       
  4497 
       
  4498     // -- Protected Methods ----------------------------------------------------
       
  4499 
       
  4500     /**
       
  4501     Triggers an automatic purge if the purge threshold has been reached.
       
  4502 
       
  4503     @method _autoPurge
       
  4504     @param {Number} threshold Purge threshold to use, in milliseconds.
       
  4505     @protected
       
  4506     @since 3.5.0
       
  4507     @static
       
  4508     **/
       
  4509     _autoPurge: function (threshold) {
       
  4510         if (threshold && this._purgeNodes.length >= threshold) {
       
  4511             Y.log('autopurge triggered after ' + this._purgeNodes.length + ' nodes', 'info', 'get');
       
  4512             this._purge(this._purgeNodes);
       
  4513         }
       
  4514     },
       
  4515 
       
  4516     /**
       
  4517     Populates the `_env` property with information about the current
       
  4518     environment.
       
  4519 
       
  4520     @method _getEnv
       
  4521     @return {Object} Environment information.
       
  4522     @protected
       
  4523     @since 3.5.0
       
  4524     @static
       
  4525     **/
       
  4526     _getEnv: function () {
       
  4527         var doc = Y.config.doc,
       
  4528             ua  = Y.UA;
       
  4529 
       
  4530         // Note: some of these checks require browser sniffs since it's not
       
  4531         // feasible to load test files on every pageview just to perform a
       
  4532         // feature test. I'm sorry if this makes you sad.
       
  4533         return (this._env = {
       
  4534 
       
  4535             // True if this is a browser that supports disabling async mode on
       
  4536             // dynamically created script nodes. See
       
  4537             // https://developer.mozilla.org/En/HTML/Element/Script#Attributes
       
  4538 
       
  4539             // IE10 doesn't return true for the MDN feature test, so setting it explicitly,
       
  4540             // because it is async by default, and allows you to disable async by setting it to false
       
  4541             async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10),
       
  4542 
       
  4543             // True if this browser fires an event when a dynamically injected
       
  4544             // link node fails to load. This is currently true for Firefox 9+
       
  4545             // and WebKit 535.24+
       
  4546             cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0,
       
  4547 
       
  4548             // True if this browser fires an event when a dynamically injected
       
  4549             // link node finishes loading. This is currently true for IE, Opera,
       
  4550             // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
       
  4551             // DOM 0 "onload" event, but not "load". All versions of IE fire
       
  4552             // "onload".
       
  4553             // davglass: Seems that Chrome on Android needs this to be false.
       
  4554             cssLoad: (
       
  4555                     (!ua.gecko && !ua.webkit) || ua.gecko >= 9 ||
       
  4556                     ua.compareVersions(ua.webkit, 535.24) >= 0
       
  4557                 ) && !(ua.chrome && ua.chrome <= 18),
       
  4558 
       
  4559             // True if this browser preserves script execution order while
       
  4560             // loading scripts in parallel as long as the script node's `async`
       
  4561             // attribute is set to false to explicitly disable async execution.
       
  4562             preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10))
       
  4563         });
       
  4564     },
       
  4565 
       
  4566     _getTransaction: function (urls, options) {
       
  4567         var requests = [],
       
  4568             i, len, req, url;
       
  4569 
       
  4570         if (!Lang.isArray(urls)) {
       
  4571             urls = [urls];
       
  4572         }
       
  4573 
       
  4574         options = Y.merge(this.options, options);
       
  4575 
       
  4576         // Clone the attributes object so we don't end up modifying it by ref.
       
  4577         options.attributes = Y.merge(this.options.attributes,
       
  4578                 options.attributes);
       
  4579 
       
  4580         for (i = 0, len = urls.length; i < len; ++i) {
       
  4581             url = urls[i];
       
  4582             req = {attributes: {}};
       
  4583 
       
  4584             // If `url` is a string, we create a URL object for it, then mix in
       
  4585             // global options and request-specific options. If it's an object
       
  4586             // with a "url" property, we assume it's a request object containing
       
  4587             // URL-specific options.
       
  4588             if (typeof url === 'string') {
       
  4589                 req.url = url;
       
  4590             } else if (url.url) {
       
  4591                 // URL-specific options override both global defaults and
       
  4592                 // request-specific options.
       
  4593                 Y.mix(req, url, false, null, 0, true);
       
  4594                 url = url.url; // Make url a string so we can use it later.
       
  4595             } else {
       
  4596                 Y.log('URL must be a string or an object with a `url` property.', 'error', 'get');
       
  4597                 continue;
       
  4598             }
       
  4599 
       
  4600             Y.mix(req, options, false, null, 0, true);
       
  4601 
       
  4602             // If we didn't get an explicit type for this URL either in the
       
  4603             // request options or the URL-specific options, try to determine
       
  4604             // one from the file extension.
       
  4605             if (!req.type) {
       
  4606                 if (this.REGEX_CSS.test(url)) {
       
  4607                     req.type = 'css';
       
  4608                 } else {
       
  4609                     if (!this.REGEX_JS.test(url)) {
       
  4610                         Y.log("Can't guess file type from URL. Assuming JS: " + url, 'warn', 'get');
       
  4611                     }
       
  4612 
       
  4613                     req.type = 'js';
       
  4614                 }
       
  4615             }
       
  4616 
       
  4617             // Mix in type-specific default options, but don't overwrite any
       
  4618             // options that have already been set.
       
  4619             Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
       
  4620                 false, null, 0, true);
       
  4621 
       
  4622             // Give the node an id attribute if it doesn't already have one.
       
  4623             req.attributes.id || (req.attributes.id = Y.guid());
       
  4624 
       
  4625             // Backcompat for <3.5.0 behavior.
       
  4626             if (req.win) {
       
  4627                 Y.log('The `win` option is deprecated as of 3.5.0. Use `doc` instead.', 'warn', 'get');
       
  4628                 req.doc = req.win.document;
       
  4629             } else {
       
  4630                 req.win = req.doc.defaultView || req.doc.parentWindow;
       
  4631             }
       
  4632 
       
  4633             if (req.charset) {
       
  4634                 Y.log('The `charset` option is deprecated as of 3.5.0. Set `attributes.charset` instead.', 'warn', 'get');
       
  4635                 req.attributes.charset = req.charset;
       
  4636             }
       
  4637 
       
  4638             requests.push(req);
       
  4639         }
       
  4640 
       
  4641         return new Transaction(requests, options);
       
  4642     },
       
  4643 
       
  4644     _load: function (type, urls, options, callback) {
       
  4645         var transaction;
       
  4646 
       
  4647         // Allow callback as third param.
       
  4648         if (typeof options === 'function') {
       
  4649             callback = options;
       
  4650             options  = {};
       
  4651         }
       
  4652 
       
  4653         options || (options = {});
       
  4654         options.type = type;
       
  4655 
       
  4656         options._onFinish = Get._onTransactionFinish;
       
  4657 
       
  4658         if (!this._env) {
       
  4659             this._getEnv();
       
  4660         }
       
  4661 
       
  4662         transaction = this._getTransaction(urls, options);
       
  4663 
       
  4664         this._queue.push({
       
  4665             callback   : callback,
       
  4666             transaction: transaction
       
  4667         });
       
  4668 
       
  4669         this._next();
       
  4670 
       
  4671         return transaction;
       
  4672     },
       
  4673 
       
  4674     _onTransactionFinish : function() {
       
  4675         Get._pending = null;
       
  4676         Get._next();
       
  4677     },
       
  4678 
       
  4679     _next: function () {
       
  4680         var item;
       
  4681 
       
  4682         if (this._pending) {
       
  4683             return;
       
  4684         }
       
  4685 
       
  4686         item = this._queue.shift();
       
  4687 
       
  4688         if (item) {
       
  4689             this._pending = item;
       
  4690             item.transaction.execute(item.callback);
       
  4691         }
       
  4692     },
       
  4693 
       
  4694     _purge: function (nodes) {
       
  4695         var purgeNodes    = this._purgeNodes,
       
  4696             isTransaction = nodes !== purgeNodes,
       
  4697             index, node;
       
  4698 
       
  4699         while (node = nodes.pop()) { // assignment
       
  4700             // Don't purge nodes that haven't finished loading (or errored out),
       
  4701             // since this can hang the transaction.
       
  4702             if (!node._yuiget_finished) {
       
  4703                 continue;
       
  4704             }
       
  4705 
       
  4706             node.parentNode && node.parentNode.removeChild(node);
       
  4707 
       
  4708             // If this is a transaction-level purge and this node also exists in
       
  4709             // the Get-level _purgeNodes array, we need to remove it from
       
  4710             // _purgeNodes to avoid creating a memory leak. The indexOf lookup
       
  4711             // sucks, but until we get WeakMaps, this is the least troublesome
       
  4712             // way to do this (we can't just hold onto node ids because they may
       
  4713             // not be in the same document).
       
  4714             if (isTransaction) {
       
  4715                 index = Y.Array.indexOf(purgeNodes, node);
       
  4716 
       
  4717                 if (index > -1) {
       
  4718                     purgeNodes.splice(index, 1);
       
  4719                 }
       
  4720             }
       
  4721         }
       
  4722     }
       
  4723 };
       
  4724 
       
  4725 /**
       
  4726 Alias for `js()`.
       
  4727 
       
  4728 @method script
       
  4729 @static
       
  4730 **/
       
  4731 Get.script = Get.js;
       
  4732 
       
  4733 /**
       
  4734 Represents a Get transaction, which may contain requests for one or more JS or
       
  4735 CSS files.
       
  4736 
       
  4737 This class should not be instantiated manually. Instances will be created and
       
  4738 returned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
       
  4739 
       
  4740 @class Get.Transaction
       
  4741 @constructor
       
  4742 @since 3.5.0
       
  4743 **/
       
  4744 Get.Transaction = Transaction = function (requests, options) {
       
  4745     var self = this;
       
  4746 
       
  4747     self.id       = Transaction._lastId += 1;
       
  4748     self.data     = options.data;
       
  4749     self.errors   = [];
       
  4750     self.nodes    = [];
       
  4751     self.options  = options;
       
  4752     self.requests = requests;
       
  4753 
       
  4754     self._callbacks = []; // callbacks to call after execution finishes
       
  4755     self._queue     = [];
       
  4756     self._reqsWaiting   = 0;
       
  4757 
       
  4758     // Deprecated pre-3.5.0 properties.
       
  4759     self.tId = self.id; // Use `id` instead.
       
  4760     self.win = options.win || Y.config.win;
       
  4761 };
       
  4762 
       
  4763 /**
       
  4764 Arbitrary data object associated with this transaction.
       
  4765 
       
  4766 This object comes from the options passed to `Get.css()`, `Get.js()`, or
       
  4767 `Get.load()`, and will be `undefined` if no data object was specified.
       
  4768 
       
  4769 @property {Object} data
       
  4770 **/
       
  4771 
       
  4772 /**
       
  4773 Array of errors that have occurred during this transaction, if any.
       
  4774 
       
  4775 @since 3.5.0
       
  4776 @property {Object[]} errors
       
  4777 @property {String} errors.error Error message.
       
  4778 @property {Object} errors.request Request object related to the error.
       
  4779 **/
       
  4780 
       
  4781 /**
       
  4782 Numeric id for this transaction, unique among all transactions within the same
       
  4783 YUI sandbox in the current pageview.
       
  4784 
       
  4785 @property {Number} id
       
  4786 @since 3.5.0
       
  4787 **/
       
  4788 
       
  4789 /**
       
  4790 HTMLElement nodes (native ones, not YUI Node instances) that have been inserted
       
  4791 during the current transaction.
       
  4792 
       
  4793 @property {HTMLElement[]} nodes
       
  4794 **/
       
  4795 
       
  4796 /**
       
  4797 Options associated with this transaction.
       
  4798 
       
  4799 See `Get.options` for the full list of available options.
       
  4800 
       
  4801 @property {Object} options
       
  4802 @since 3.5.0
       
  4803 **/
       
  4804 
       
  4805 /**
       
  4806 Request objects contained in this transaction. Each request object represents
       
  4807 one CSS or JS URL that will be (or has been) requested and loaded into the page.
       
  4808 
       
  4809 @property {Object} requests
       
  4810 @since 3.5.0
       
  4811 **/
       
  4812 
       
  4813 /**
       
  4814 Id of the most recent transaction.
       
  4815 
       
  4816 @property _lastId
       
  4817 @type Number
       
  4818 @protected
       
  4819 @static
       
  4820 **/
       
  4821 Transaction._lastId = 0;
       
  4822 
       
  4823 Transaction.prototype = {
       
  4824     // -- Public Properties ----------------------------------------------------
       
  4825 
       
  4826     /**
       
  4827     Current state of this transaction. One of "new", "executing", or "done".
       
  4828 
       
  4829     @property _state
       
  4830     @type String
       
  4831     @protected
       
  4832     **/
       
  4833     _state: 'new', // "new", "executing", or "done"
       
  4834 
       
  4835     // -- Public Methods -------------------------------------------------------
       
  4836 
       
  4837     /**
       
  4838     Aborts this transaction.
       
  4839 
       
  4840     This will cause the transaction's `onFailure` callback to be called and
       
  4841     will prevent any new script and link nodes from being added to the document,
       
  4842     but any resources that have already been requested will continue loading
       
  4843     (there's no safe way to prevent this, unfortunately).
       
  4844 
       
  4845     @method abort
       
  4846     @param {String} [msg="Aborted."] Optional message to use in the `errors`
       
  4847         array describing why the transaction was aborted.
       
  4848     **/
       
  4849     abort: function (msg) {
       
  4850         this._pending    = null;
       
  4851         this._pendingCSS = null;
       
  4852         this._pollTimer  = clearTimeout(this._pollTimer);
       
  4853         this._queue      = [];
       
  4854         this._reqsWaiting    = 0;
       
  4855 
       
  4856         this.errors.push({error: msg || 'Aborted'});
       
  4857         this._finish();
       
  4858     },
       
  4859 
       
  4860     /**
       
  4861     Begins execting the transaction.
       
  4862 
       
  4863     There's usually no reason to call this manually, since Get will call it
       
  4864     automatically when other pending transactions have finished. If you really
       
  4865     want to execute your transaction before Get does, you can, but be aware that
       
  4866     this transaction's scripts may end up executing before the scripts in other
       
  4867     pending transactions.
       
  4868 
       
  4869     If the transaction is already executing, the specified callback (if any)
       
  4870     will be queued and called after execution finishes. If the transaction has
       
  4871     already finished, the callback will be called immediately (the transaction
       
  4872     will not be executed again).
       
  4873 
       
  4874     @method execute
       
  4875     @param {Function} callback Callback function to execute after all requests
       
  4876         in the transaction are complete, or after the transaction is aborted.
       
  4877     **/
       
  4878     execute: function (callback) {
       
  4879         var self     = this,
       
  4880             requests = self.requests,
       
  4881             state    = self._state,
       
  4882             i, len, queue, req;
       
  4883 
       
  4884         if (state === 'done') {
       
  4885             callback && callback(self.errors.length ? self.errors : null, self);
       
  4886             return;
       
  4887         } else {
       
  4888             callback && self._callbacks.push(callback);
       
  4889 
       
  4890             if (state === 'executing') {
       
  4891                 return;
       
  4892             }
       
  4893         }
       
  4894 
       
  4895         self._state = 'executing';
       
  4896         self._queue = queue = [];
       
  4897 
       
  4898         if (self.options.timeout) {
       
  4899             self._timeout = setTimeout(function () {
       
  4900                 self.abort('Timeout');
       
  4901             }, self.options.timeout);
       
  4902         }
       
  4903 
       
  4904         self._reqsWaiting = requests.length;
       
  4905 
       
  4906         for (i = 0, len = requests.length; i < len; ++i) {
       
  4907             req = requests[i];
       
  4908 
       
  4909             if (req.async || req.type === 'css') {
       
  4910                 // No need to queue CSS or fully async JS.
       
  4911                 self._insert(req);
       
  4912             } else {
       
  4913                 queue.push(req);
       
  4914             }
       
  4915         }
       
  4916 
       
  4917         self._next();
       
  4918     },
       
  4919 
       
  4920     /**
       
  4921     Manually purges any `<script>` or `<link>` nodes this transaction has
       
  4922     created.
       
  4923 
       
  4924     Be careful when purging a transaction that contains CSS requests, since
       
  4925     removing `<link>` nodes will also remove any styles they applied.
       
  4926 
       
  4927     @method purge
       
  4928     **/
       
  4929     purge: function () {
       
  4930         Get._purge(this.nodes);
       
  4931     },
       
  4932 
       
  4933     // -- Protected Methods ----------------------------------------------------
       
  4934     _createNode: function (name, attrs, doc) {
       
  4935         var node = doc.createElement(name),
       
  4936             attr, testEl;
       
  4937 
       
  4938         if (!CUSTOM_ATTRS) {
       
  4939             // IE6 and IE7 expect property names rather than attribute names for
       
  4940             // certain attributes. Rather than sniffing, we do a quick feature
       
  4941             // test the first time _createNode() runs to determine whether we
       
  4942             // need to provide a workaround.
       
  4943             testEl = doc.createElement('div');
       
  4944             testEl.setAttribute('class', 'a');
       
  4945 
       
  4946             CUSTOM_ATTRS = testEl.className === 'a' ? {} : {
       
  4947                 'for'  : 'htmlFor',
       
  4948                 'class': 'className'
       
  4949             };
       
  4950         }
       
  4951 
       
  4952         for (attr in attrs) {
       
  4953             if (attrs.hasOwnProperty(attr)) {
       
  4954                 node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
       
  4955             }
       
  4956         }
       
  4957 
       
  4958         return node;
       
  4959     },
       
  4960 
       
  4961     _finish: function () {
       
  4962         var errors  = this.errors.length ? this.errors : null,
       
  4963             options = this.options,
       
  4964             thisObj = options.context || this,
       
  4965             data, i, len;
       
  4966 
       
  4967         if (this._state === 'done') {
       
  4968             return;
       
  4969         }
       
  4970 
       
  4971         this._state = 'done';
       
  4972 
       
  4973         for (i = 0, len = this._callbacks.length; i < len; ++i) {
       
  4974             this._callbacks[i].call(thisObj, errors, this);
       
  4975         }
       
  4976 
       
  4977         data = this._getEventData();
       
  4978 
       
  4979         if (errors) {
       
  4980             if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
       
  4981                 options.onTimeout.call(thisObj, data);
       
  4982             }
       
  4983 
       
  4984             if (options.onFailure) {
       
  4985                 options.onFailure.call(thisObj, data);
       
  4986             }
       
  4987         } else if (options.onSuccess) {
       
  4988             options.onSuccess.call(thisObj, data);
       
  4989         }
       
  4990 
       
  4991         if (options.onEnd) {
       
  4992             options.onEnd.call(thisObj, data);
       
  4993         }
       
  4994 
       
  4995         if (options._onFinish) {
       
  4996             options._onFinish();
       
  4997         }
       
  4998     },
       
  4999 
       
  5000     _getEventData: function (req) {
       
  5001         if (req) {
       
  5002             // This merge is necessary for backcompat. I hate it.
       
  5003             return Y.merge(this, {
       
  5004                 abort  : this.abort, // have to copy these because the prototype isn't preserved
       
  5005                 purge  : this.purge,
       
  5006                 request: req,
       
  5007                 url    : req.url,
       
  5008                 win    : req.win
       
  5009             });
       
  5010         } else {
       
  5011             return this;
       
  5012         }
       
  5013     },
       
  5014 
       
  5015     _getInsertBefore: function (req) {
       
  5016         var doc = req.doc,
       
  5017             el  = req.insertBefore,
       
  5018             cache, docStamp;
       
  5019 
       
  5020         if (el) {
       
  5021             return typeof el === 'string' ? doc.getElementById(el) : el;
       
  5022         }
       
  5023 
       
  5024         cache    = Get._insertCache;
       
  5025         docStamp = Y.stamp(doc);
       
  5026 
       
  5027         if ((el = cache[docStamp])) { // assignment
       
  5028             return el;
       
  5029         }
       
  5030 
       
  5031         // Inserting before a <base> tag apparently works around an IE bug
       
  5032         // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
       
  5033         // bug that is, exactly. Better safe than sorry?
       
  5034         if ((el = doc.getElementsByTagName('base')[0])) { // assignment
       
  5035             return (cache[docStamp] = el);
       
  5036         }
       
  5037 
       
  5038         // Look for a <head> element.
       
  5039         el = doc.head || doc.getElementsByTagName('head')[0];
       
  5040 
       
  5041         if (el) {
       
  5042             // Create a marker node at the end of <head> to use as an insertion
       
  5043             // point. Inserting before this node will ensure that all our CSS
       
  5044             // gets inserted in the correct order, to maintain style precedence.
       
  5045             el.appendChild(doc.createTextNode(''));
       
  5046             return (cache[docStamp] = el.lastChild);
       
  5047         }
       
  5048 
       
  5049         // If all else fails, just insert before the first script node on the
       
  5050         // page, which is virtually guaranteed to exist.
       
  5051         return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
       
  5052     },
       
  5053 
       
  5054     _insert: function (req) {
       
  5055         var env          = Get._env,
       
  5056             insertBefore = this._getInsertBefore(req),
       
  5057             isScript     = req.type === 'js',
       
  5058             node         = req.node,
       
  5059             self         = this,
       
  5060             ua           = Y.UA,
       
  5061             cssTimeout, nodeType;
       
  5062 
       
  5063         if (!node) {
       
  5064             if (isScript) {
       
  5065                 nodeType = 'script';
       
  5066             } else if (!env.cssLoad && ua.gecko) {
       
  5067                 nodeType = 'style';
       
  5068             } else {
       
  5069                 nodeType = 'link';
       
  5070             }
       
  5071 
       
  5072             node = req.node = this._createNode(nodeType, req.attributes,
       
  5073                 req.doc);
       
  5074         }
       
  5075 
       
  5076         function onError() {
       
  5077             self._progress('Failed to load ' + req.url, req);
       
  5078         }
       
  5079 
       
  5080         function onLoad() {
       
  5081             if (cssTimeout) {
       
  5082                 clearTimeout(cssTimeout);
       
  5083             }
       
  5084 
       
  5085             self._progress(null, req);
       
  5086         }
       
  5087 
       
  5088         // Deal with script asynchronicity.
       
  5089         if (isScript) {
       
  5090             node.setAttribute('src', req.url);
       
  5091 
       
  5092             if (req.async) {
       
  5093                 // Explicitly indicate that we want the browser to execute this
       
  5094                 // script asynchronously. This is necessary for older browsers
       
  5095                 // like Firefox <4.
       
  5096                 node.async = true;
       
  5097             } else {
       
  5098                 if (env.async) {
       
  5099                     // This browser treats injected scripts as async by default
       
  5100                     // (standard HTML5 behavior) but asynchronous loading isn't
       
  5101                     // desired, so tell the browser not to mark this script as
       
  5102                     // async.
       
  5103                     node.async = false;
       
  5104                 }
       
  5105 
       
  5106                 // If this browser doesn't preserve script execution order based
       
  5107                 // on insertion order, we'll need to avoid inserting other
       
  5108                 // scripts until this one finishes loading.
       
  5109                 if (!env.preservesScriptOrder) {
       
  5110                     this._pending = req;
       
  5111                 }
       
  5112             }
       
  5113         } else {
       
  5114             if (!env.cssLoad && ua.gecko) {
       
  5115                 // In Firefox <9, we can import the requested URL into a <style>
       
  5116                 // node and poll for the existence of node.sheet.cssRules. This
       
  5117                 // gives us a reliable way to determine CSS load completion that
       
  5118                 // also works for cross-domain stylesheets.
       
  5119                 //
       
  5120                 // Props to Zach Leatherman for calling my attention to this
       
  5121                 // technique.
       
  5122                 node.innerHTML = (req.attributes.charset ?
       
  5123                     '@charset "' + req.attributes.charset + '";' : '') +
       
  5124                     '@import "' + req.url + '";';
       
  5125             } else {
       
  5126                 node.setAttribute('href', req.url);
       
  5127             }
       
  5128         }
       
  5129 
       
  5130         // Inject the node.
       
  5131         if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) {
       
  5132             // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode.
       
  5133             node.onreadystatechange = function () {
       
  5134                 if (/loaded|complete/.test(node.readyState)) {
       
  5135                     node.onreadystatechange = null;
       
  5136                     onLoad();
       
  5137                 }
       
  5138             };
       
  5139         } else if (!isScript && !env.cssLoad) {
       
  5140             // CSS on Firefox <9 or WebKit.
       
  5141             this._poll(req);
       
  5142         } else {
       
  5143             // Script or CSS on everything else. Using DOM 0 events because that
       
  5144             // evens the playing field with older IEs.
       
  5145 
       
  5146             if (ua.ie >= 10) {
       
  5147 
       
  5148                 // We currently need to introduce a timeout for IE10, since it
       
  5149                 // calls onerror/onload synchronously for 304s - messing up existing
       
  5150                 // program flow.
       
  5151 
       
  5152                 // Remove this block if the following bug gets fixed by GA
       
  5153                 /*jshint maxlen: 1500 */
       
  5154                 // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload
       
  5155                 node.onerror = function() { setTimeout(onError, 0); };
       
  5156                 node.onload  = function() { setTimeout(onLoad, 0); };
       
  5157             } else {
       
  5158                 node.onerror = onError;
       
  5159                 node.onload  = onLoad;
       
  5160             }
       
  5161 
       
  5162             // If this browser doesn't fire an event when CSS fails to load,
       
  5163             // fail after a timeout to avoid blocking the transaction queue.
       
  5164             if (!env.cssFail && !isScript) {
       
  5165                 cssTimeout = setTimeout(onError, req.timeout || 3000);
       
  5166             }
       
  5167         }
       
  5168 
       
  5169         this.nodes.push(node);
       
  5170         insertBefore.parentNode.insertBefore(node, insertBefore);
       
  5171     },
       
  5172 
       
  5173     _next: function () {
       
  5174         if (this._pending) {
       
  5175             return;
       
  5176         }
       
  5177 
       
  5178         // If there are requests in the queue, insert the next queued request.
       
  5179         // Otherwise, if we're waiting on already-inserted requests to finish,
       
  5180         // wait longer. If there are no queued requests and we're not waiting
       
  5181         // for anything to load, then we're done!
       
  5182         if (this._queue.length) {
       
  5183             this._insert(this._queue.shift());
       
  5184         } else if (!this._reqsWaiting) {
       
  5185             this._finish();
       
  5186         }
       
  5187     },
       
  5188 
       
  5189     _poll: function (newReq) {
       
  5190         var self       = this,
       
  5191             pendingCSS = self._pendingCSS,
       
  5192             isWebKit   = Y.UA.webkit,
       
  5193             i, hasRules, j, nodeHref, req, sheets;
       
  5194 
       
  5195         if (newReq) {
       
  5196             pendingCSS || (pendingCSS = self._pendingCSS = []);
       
  5197             pendingCSS.push(newReq);
       
  5198 
       
  5199             if (self._pollTimer) {
       
  5200                 // A poll timeout is already pending, so no need to create a
       
  5201                 // new one.
       
  5202                 return;
       
  5203             }
       
  5204         }
       
  5205 
       
  5206         self._pollTimer = null;
       
  5207 
       
  5208         // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
       
  5209         // will still be treated as a success. There's no good workaround for
       
  5210         // this.
       
  5211 
       
  5212         for (i = 0; i < pendingCSS.length; ++i) {
       
  5213             req = pendingCSS[i];
       
  5214 
       
  5215             if (isWebKit) {
       
  5216                 // Look for a stylesheet matching the pending URL.
       
  5217                 sheets   = req.doc.styleSheets;
       
  5218                 j        = sheets.length;
       
  5219                 nodeHref = req.node.href;
       
  5220 
       
  5221                 while (--j >= 0) {
       
  5222                     if (sheets[j].href === nodeHref) {
       
  5223                         pendingCSS.splice(i, 1);
       
  5224                         i -= 1;
       
  5225                         self._progress(null, req);
       
  5226                         break;
       
  5227                     }
       
  5228                 }
       
  5229             } else {
       
  5230                 // Many thanks to Zach Leatherman for calling my attention to
       
  5231                 // the @import-based cross-domain technique used here, and to
       
  5232                 // Oleg Slobodskoi for an earlier same-domain implementation.
       
  5233                 //
       
  5234                 // See Zach's blog for more details:
       
  5235                 // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
       
  5236                 try {
       
  5237                     // We don't really need to store this value since we never
       
  5238                     // use it again, but if we don't store it, Closure Compiler
       
  5239                     // assumes the code is useless and removes it.
       
  5240                     hasRules = !!req.node.sheet.cssRules;
       
  5241 
       
  5242                     // If we get here, the stylesheet has loaded.
       
  5243                     pendingCSS.splice(i, 1);
       
  5244                     i -= 1;
       
  5245                     self._progress(null, req);
       
  5246                 } catch (ex) {
       
  5247                     // An exception means the stylesheet is still loading.
       
  5248                 }
       
  5249             }
       
  5250         }
       
  5251 
       
  5252         if (pendingCSS.length) {
       
  5253             self._pollTimer = setTimeout(function () {
       
  5254                 self._poll.call(self);
       
  5255             }, self.options.pollInterval);
       
  5256         }
       
  5257     },
       
  5258 
       
  5259     _progress: function (err, req) {
       
  5260         var options = this.options;
       
  5261 
       
  5262         if (err) {
       
  5263             req.error = err;
       
  5264 
       
  5265             this.errors.push({
       
  5266                 error  : err,
       
  5267                 request: req
       
  5268             });
       
  5269 
       
  5270             Y.log(err, 'error', 'get');
       
  5271         }
       
  5272 
       
  5273         req.node._yuiget_finished = req.finished = true;
       
  5274 
       
  5275         if (options.onProgress) {
       
  5276             options.onProgress.call(options.context || this,
       
  5277                 this._getEventData(req));
       
  5278         }
       
  5279 
       
  5280         if (req.autopurge) {
       
  5281             // Pre-3.5.0 Get always excludes the most recent node from an
       
  5282             // autopurge. I find this odd, but I'm keeping that behavior for
       
  5283             // the sake of backcompat.
       
  5284             Get._autoPurge(this.options.purgethreshold);
       
  5285             Get._purgeNodes.push(req.node);
       
  5286         }
       
  5287 
       
  5288         if (this._pending === req) {
       
  5289             this._pending = null;
       
  5290         }
       
  5291 
       
  5292         this._reqsWaiting -= 1;
       
  5293 
       
  5294         this._next();
       
  5295     }
       
  5296 };
       
  5297 
       
  5298 
       
  5299 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5300 YUI.add('features', function (Y, NAME) {
       
  5301 
       
  5302 var feature_tests = {};
       
  5303 
       
  5304 /**
       
  5305 Contains the core of YUI's feature test architecture.
       
  5306 @module features
       
  5307 */
       
  5308 
       
  5309 /**
       
  5310 * Feature detection
       
  5311 * @class Features
       
  5312 * @static
       
  5313 */
       
  5314 
       
  5315 Y.mix(Y.namespace('Features'), {
       
  5316 
       
  5317     /**
       
  5318     * Object hash of all registered feature tests
       
  5319     * @property tests
       
  5320     * @type Object
       
  5321     */
       
  5322     tests: feature_tests,
       
  5323 
       
  5324     /**
       
  5325     * Add a test to the system
       
  5326     *
       
  5327     *   ```
       
  5328     *   Y.Features.add("load", "1", {});
       
  5329     *   ```
       
  5330     *
       
  5331     * @method add
       
  5332     * @param {String} cat The category, right now only 'load' is supported
       
  5333     * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
       
  5334     * @param {Object} o Object containing test properties
       
  5335     * @param {String} o.name The name of the test
       
  5336     * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
       
  5337     * @param {String} o.trigger The module that triggers this test.
       
  5338     */
       
  5339     add: function(cat, name, o) {
       
  5340         feature_tests[cat] = feature_tests[cat] || {};
       
  5341         feature_tests[cat][name] = o;
       
  5342     },
       
  5343     /**
       
  5344     * Execute all tests of a given category and return the serialized results
       
  5345     *
       
  5346     *   ```
       
  5347     *   caps=1:1;2:1;3:0
       
  5348     *   ```
       
  5349     * @method all
       
  5350     * @param {String} cat The category to execute
       
  5351     * @param {Array} args The arguments to pass to the test function
       
  5352     * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
       
  5353     */
       
  5354     all: function(cat, args) {
       
  5355         var cat_o = feature_tests[cat],
       
  5356             // results = {};
       
  5357             result = [];
       
  5358         if (cat_o) {
       
  5359             Y.Object.each(cat_o, function(v, k) {
       
  5360                 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
       
  5361             });
       
  5362         }
       
  5363 
       
  5364         return (result.length) ? result.join(';') : '';
       
  5365     },
       
  5366     /**
       
  5367     * Run a sepecific test and return a Boolean response.
       
  5368     *
       
  5369     *   ```
       
  5370     *   Y.Features.test("load", "1");
       
  5371     *   ```
       
  5372     *
       
  5373     * @method test
       
  5374     * @param {String} cat The category of the test to run
       
  5375     * @param {String} name The name of the test to run
       
  5376     * @param {Array} args The arguments to pass to the test function
       
  5377     * @return {Boolean} True or false if the test passed/failed.
       
  5378     */
       
  5379     test: function(cat, name, args) {
       
  5380         args = args || [];
       
  5381         var result, ua, test,
       
  5382             cat_o = feature_tests[cat],
       
  5383             feature = cat_o && cat_o[name];
       
  5384 
       
  5385         if (!feature) {
       
  5386             Y.log('Feature test ' + cat + ', ' + name + ' not found');
       
  5387         } else {
       
  5388 
       
  5389             result = feature.result;
       
  5390 
       
  5391             if (Y.Lang.isUndefined(result)) {
       
  5392 
       
  5393                 ua = feature.ua;
       
  5394                 if (ua) {
       
  5395                     result = (Y.UA[ua]);
       
  5396                 }
       
  5397 
       
  5398                 test = feature.test;
       
  5399                 if (test && ((!ua) || result)) {
       
  5400                     result = test.apply(Y, args);
       
  5401                 }
       
  5402 
       
  5403                 feature.result = result;
       
  5404             }
       
  5405         }
       
  5406 
       
  5407         return result;
       
  5408     }
       
  5409 });
       
  5410 
       
  5411 // Y.Features.add("load", "1", {});
       
  5412 // Y.Features.test("load", "1");
       
  5413 // caps=1:1;2:0;3:1;
       
  5414 
       
  5415 /* This file is auto-generated by (yogi loader --yes --mix --start ../) */
       
  5416 /*jshint maxlen:900, eqeqeq: false */
       
  5417 var add = Y.Features.add;
       
  5418 // app-transitions-native
       
  5419 add('load', '0', {
       
  5420     "name": "app-transitions-native",
       
  5421     "test": function (Y) {
       
  5422     var doc  = Y.config.doc,
       
  5423         node = doc ? doc.documentElement : null;
       
  5424 
       
  5425     if (node && node.style) {
       
  5426         return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  5427     }
       
  5428 
       
  5429     return false;
       
  5430 },
       
  5431     "trigger": "app-transitions"
       
  5432 });
       
  5433 // autocomplete-list-keys
       
  5434 add('load', '1', {
       
  5435     "name": "autocomplete-list-keys",
       
  5436     "test": function (Y) {
       
  5437     // Only add keyboard support to autocomplete-list if this doesn't appear to
       
  5438     // be an iOS or Android-based mobile device.
       
  5439     //
       
  5440     // There's currently no feasible way to actually detect whether a device has
       
  5441     // a hardware keyboard, so this sniff will have to do. It can easily be
       
  5442     // overridden by manually loading the autocomplete-list-keys module.
       
  5443     //
       
  5444     // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
       
  5445     // doesn't fire the keyboard events used by AutoCompleteList, so there's
       
  5446     // no point loading the -keys module even when a bluetooth keyboard may be
       
  5447     // available.
       
  5448     return !(Y.UA.ios || Y.UA.android);
       
  5449 },
       
  5450     "trigger": "autocomplete-list"
       
  5451 });
       
  5452 // dd-gestures
       
  5453 add('load', '2', {
       
  5454     "name": "dd-gestures",
       
  5455     "trigger": "dd-drag",
       
  5456     "ua": "touchEnabled"
       
  5457 });
       
  5458 // dom-style-ie
       
  5459 add('load', '3', {
       
  5460     "name": "dom-style-ie",
       
  5461     "test": function (Y) {
       
  5462 
       
  5463     var testFeature = Y.Features.test,
       
  5464         addFeature = Y.Features.add,
       
  5465         WINDOW = Y.config.win,
       
  5466         DOCUMENT = Y.config.doc,
       
  5467         DOCUMENT_ELEMENT = 'documentElement',
       
  5468         ret = false;
       
  5469 
       
  5470     addFeature('style', 'computedStyle', {
       
  5471         test: function() {
       
  5472             return WINDOW && 'getComputedStyle' in WINDOW;
       
  5473         }
       
  5474     });
       
  5475 
       
  5476     addFeature('style', 'opacity', {
       
  5477         test: function() {
       
  5478             return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
       
  5479         }
       
  5480     });
       
  5481 
       
  5482     ret =  (!testFeature('style', 'opacity') &&
       
  5483             !testFeature('style', 'computedStyle'));
       
  5484 
       
  5485     return ret;
       
  5486 },
       
  5487     "trigger": "dom-style"
       
  5488 });
       
  5489 // editor-para-ie
       
  5490 add('load', '4', {
       
  5491     "name": "editor-para-ie",
       
  5492     "trigger": "editor-para",
       
  5493     "ua": "ie",
       
  5494     "when": "instead"
       
  5495 });
       
  5496 // event-base-ie
       
  5497 add('load', '5', {
       
  5498     "name": "event-base-ie",
       
  5499     "test": function(Y) {
       
  5500     var imp = Y.config.doc && Y.config.doc.implementation;
       
  5501     return (imp && (!imp.hasFeature('Events', '2.0')));
       
  5502 },
       
  5503     "trigger": "node-base"
       
  5504 });
       
  5505 // graphics-canvas
       
  5506 add('load', '6', {
       
  5507     "name": "graphics-canvas",
       
  5508     "test": function(Y) {
       
  5509     var DOCUMENT = Y.config.doc,
       
  5510         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  5511 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5512         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5513     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  5514 },
       
  5515     "trigger": "graphics"
       
  5516 });
       
  5517 // graphics-canvas-default
       
  5518 add('load', '7', {
       
  5519     "name": "graphics-canvas-default",
       
  5520     "test": function(Y) {
       
  5521     var DOCUMENT = Y.config.doc,
       
  5522         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  5523 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5524         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5525     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  5526 },
       
  5527     "trigger": "graphics"
       
  5528 });
       
  5529 // graphics-svg
       
  5530 add('load', '8', {
       
  5531     "name": "graphics-svg",
       
  5532     "test": function(Y) {
       
  5533     var DOCUMENT = Y.config.doc,
       
  5534         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  5535 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5536         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5537     
       
  5538     return svg && (useSVG || !canvas);
       
  5539 },
       
  5540     "trigger": "graphics"
       
  5541 });
       
  5542 // graphics-svg-default
       
  5543 add('load', '9', {
       
  5544     "name": "graphics-svg-default",
       
  5545     "test": function(Y) {
       
  5546     var DOCUMENT = Y.config.doc,
       
  5547         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  5548 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  5549         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  5550     
       
  5551     return svg && (useSVG || !canvas);
       
  5552 },
       
  5553     "trigger": "graphics"
       
  5554 });
       
  5555 // graphics-vml
       
  5556 add('load', '10', {
       
  5557     "name": "graphics-vml",
       
  5558     "test": function(Y) {
       
  5559     var DOCUMENT = Y.config.doc,
       
  5560 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  5561     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  5562 },
       
  5563     "trigger": "graphics"
       
  5564 });
       
  5565 // graphics-vml-default
       
  5566 add('load', '11', {
       
  5567     "name": "graphics-vml-default",
       
  5568     "test": function(Y) {
       
  5569     var DOCUMENT = Y.config.doc,
       
  5570 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  5571     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  5572 },
       
  5573     "trigger": "graphics"
       
  5574 });
       
  5575 // history-hash-ie
       
  5576 add('load', '12', {
       
  5577     "name": "history-hash-ie",
       
  5578     "test": function (Y) {
       
  5579     var docMode = Y.config.doc && Y.config.doc.documentMode;
       
  5580 
       
  5581     return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
       
  5582             !docMode || docMode < 8);
       
  5583 },
       
  5584     "trigger": "history-hash"
       
  5585 });
       
  5586 // io-nodejs
       
  5587 add('load', '13', {
       
  5588     "name": "io-nodejs",
       
  5589     "trigger": "io-base",
       
  5590     "ua": "nodejs"
       
  5591 });
       
  5592 // json-parse-shim
       
  5593 add('load', '14', {
       
  5594     "name": "json-parse-shim",
       
  5595     "test": function (Y) {
       
  5596     var _JSON = Y.config.global.JSON,
       
  5597         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  5598         nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
       
  5599 
       
  5600     function workingNative( k, v ) {
       
  5601         return k === "ok" ? true : v;
       
  5602     }
       
  5603     
       
  5604     // Double check basic functionality.  This is mainly to catch early broken
       
  5605     // implementations of the JSON API in Firefox 3.1 beta1 and beta2
       
  5606     if ( nativeSupport ) {
       
  5607         try {
       
  5608             nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
       
  5609         }
       
  5610         catch ( e ) {
       
  5611             nativeSupport = false;
       
  5612         }
       
  5613     }
       
  5614 
       
  5615     return !nativeSupport;
       
  5616 },
       
  5617     "trigger": "json-parse"
       
  5618 });
       
  5619 // json-stringify-shim
       
  5620 add('load', '15', {
       
  5621     "name": "json-stringify-shim",
       
  5622     "test": function (Y) {
       
  5623     var _JSON = Y.config.global.JSON,
       
  5624         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  5625         nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
       
  5626 
       
  5627     // Double check basic native functionality.  This is primarily to catch broken
       
  5628     // early JSON API implementations in Firefox 3.1 beta1 and beta2.
       
  5629     if ( nativeSupport ) {
       
  5630         try {
       
  5631             nativeSupport = ( '0' === Native.stringify(0) );
       
  5632         } catch ( e ) {
       
  5633             nativeSupport = false;
       
  5634         }
       
  5635     }
       
  5636 
       
  5637 
       
  5638     return !nativeSupport;
       
  5639 },
       
  5640     "trigger": "json-stringify"
       
  5641 });
       
  5642 // scrollview-base-ie
       
  5643 add('load', '16', {
       
  5644     "name": "scrollview-base-ie",
       
  5645     "trigger": "scrollview-base",
       
  5646     "ua": "ie"
       
  5647 });
       
  5648 // selector-css2
       
  5649 add('load', '17', {
       
  5650     "name": "selector-css2",
       
  5651     "test": function (Y) {
       
  5652     var DOCUMENT = Y.config.doc,
       
  5653         ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
       
  5654 
       
  5655     return ret;
       
  5656 },
       
  5657     "trigger": "selector"
       
  5658 });
       
  5659 // transition-timer
       
  5660 add('load', '18', {
       
  5661     "name": "transition-timer",
       
  5662     "test": function (Y) {
       
  5663     var DOCUMENT = Y.config.doc,
       
  5664         node = (DOCUMENT) ? DOCUMENT.documentElement: null,
       
  5665         ret = true;
       
  5666 
       
  5667     if (node && node.style) {
       
  5668         ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  5669     }
       
  5670 
       
  5671     return ret;
       
  5672 },
       
  5673     "trigger": "transition"
       
  5674 });
       
  5675 // widget-base-ie
       
  5676 add('load', '19', {
       
  5677     "name": "widget-base-ie",
       
  5678     "trigger": "widget-base",
       
  5679     "ua": "ie"
       
  5680 });
       
  5681 // yql-jsonp
       
  5682 add('load', '20', {
       
  5683     "name": "yql-jsonp",
       
  5684     "test": function (Y) {
       
  5685     /* Only load the JSONP module when not in nodejs or winjs
       
  5686     TODO Make the winjs module a CORS module
       
  5687     */
       
  5688     return (!Y.UA.nodejs && !Y.UA.winjs);
       
  5689 },
       
  5690     "trigger": "yql",
       
  5691     "when": "after"
       
  5692 });
       
  5693 // yql-nodejs
       
  5694 add('load', '21', {
       
  5695     "name": "yql-nodejs",
       
  5696     "trigger": "yql",
       
  5697     "ua": "nodejs",
       
  5698     "when": "after"
       
  5699 });
       
  5700 // yql-winjs
       
  5701 add('load', '22', {
       
  5702     "name": "yql-winjs",
       
  5703     "trigger": "yql",
       
  5704     "ua": "winjs",
       
  5705     "when": "after"
       
  5706 });
       
  5707 
       
  5708 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5709 YUI.add('intl-base', function (Y, NAME) {
       
  5710 
       
  5711 /**
       
  5712  * The Intl utility provides a central location for managing sets of
       
  5713  * localized resources (strings and formatting patterns).
       
  5714  *
       
  5715  * @class Intl
       
  5716  * @uses EventTarget
       
  5717  * @static
       
  5718  */
       
  5719 
       
  5720 var SPLIT_REGEX = /[, ]/;
       
  5721 
       
  5722 Y.mix(Y.namespace('Intl'), {
       
  5723 
       
  5724  /**
       
  5725     * Returns the language among those available that
       
  5726     * best matches the preferred language list, using the Lookup
       
  5727     * algorithm of BCP 47.
       
  5728     * If none of the available languages meets the user's preferences,
       
  5729     * then "" is returned.
       
  5730     * Extended language ranges are not supported.
       
  5731     *
       
  5732     * @method lookupBestLang
       
  5733     * @param {String[] | String} preferredLanguages The list of preferred
       
  5734     * languages in descending preference order, represented as BCP 47
       
  5735     * language tags. A string array or a comma-separated list.
       
  5736     * @param {String[]} availableLanguages The list of languages
       
  5737     * that the application supports, represented as BCP 47 language
       
  5738     * tags.
       
  5739     *
       
  5740     * @return {String} The available language that best matches the
       
  5741     * preferred language list, or "".
       
  5742     * @since 3.1.0
       
  5743     */
       
  5744     lookupBestLang: function(preferredLanguages, availableLanguages) {
       
  5745 
       
  5746         var i, language, result, index;
       
  5747 
       
  5748         // check whether the list of available languages contains language;
       
  5749         // if so return it
       
  5750         function scan(language) {
       
  5751             var i;
       
  5752             for (i = 0; i < availableLanguages.length; i += 1) {
       
  5753                 if (language.toLowerCase() ===
       
  5754                             availableLanguages[i].toLowerCase()) {
       
  5755                     return availableLanguages[i];
       
  5756                 }
       
  5757             }
       
  5758         }
       
  5759 
       
  5760         if (Y.Lang.isString(preferredLanguages)) {
       
  5761             preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
       
  5762         }
       
  5763 
       
  5764         for (i = 0; i < preferredLanguages.length; i += 1) {
       
  5765             language = preferredLanguages[i];
       
  5766             if (!language || language === '*') {
       
  5767                 continue;
       
  5768             }
       
  5769             // check the fallback sequence for one language
       
  5770             while (language.length > 0) {
       
  5771                 result = scan(language);
       
  5772                 if (result) {
       
  5773                     return result;
       
  5774                 } else {
       
  5775                     index = language.lastIndexOf('-');
       
  5776                     if (index >= 0) {
       
  5777                         language = language.substring(0, index);
       
  5778                         // one-character subtags get cut along with the
       
  5779                         // following subtag
       
  5780                         if (index >= 2 && language.charAt(index - 2) === '-') {
       
  5781                             language = language.substring(0, index - 2);
       
  5782                         }
       
  5783                     } else {
       
  5784                         // nothing available for this language
       
  5785                         break;
       
  5786                     }
       
  5787                 }
       
  5788             }
       
  5789         }
       
  5790 
       
  5791         return '';
       
  5792     }
       
  5793 });
       
  5794 
       
  5795 
       
  5796 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5797 YUI.add('yui-log', function (Y, NAME) {
       
  5798 
       
  5799 /**
       
  5800  * Provides console log capability and exposes a custom event for
       
  5801  * console implementations. This module is a `core` YUI module,
       
  5802  * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
       
  5803  *
       
  5804  * @module yui
       
  5805  * @submodule yui-log
       
  5806  */
       
  5807 
       
  5808 var INSTANCE = Y,
       
  5809     LOGEVENT = 'yui:log',
       
  5810     UNDEFINED = 'undefined',
       
  5811     LEVELS = { debug: 1,
       
  5812                info: 2,
       
  5813                warn: 4,
       
  5814                error: 8 };
       
  5815 
       
  5816 /**
       
  5817  * If the 'debug' config is true, a 'yui:log' event will be
       
  5818  * dispatched, which the Console widget and anything else
       
  5819  * can consume.  If the 'useBrowserConsole' config is true, it will
       
  5820  * write to the browser console if available.  YUI-specific log
       
  5821  * messages will only be present in the -debug versions of the
       
  5822  * JS files.  The build system is supposed to remove log statements
       
  5823  * from the raw and minified versions of the files.
       
  5824  *
       
  5825  * @method log
       
  5826  * @for YUI
       
  5827  * @param  {String}  msg  The message to log.
       
  5828  * @param  {String}  cat  The log category for the message.  Default
       
  5829  *                        categories are "info", "warn", "error", time".
       
  5830  *                        Custom categories can be used as well. (opt).
       
  5831  * @param  {String}  src  The source of the the message (opt).
       
  5832  * @param  {boolean} silent If true, the log event won't fire.
       
  5833  * @return {YUI}      YUI instance.
       
  5834  */
       
  5835 INSTANCE.log = function(msg, cat, src, silent) {
       
  5836     var bail, excl, incl, m, f, minlevel,
       
  5837         Y = INSTANCE,
       
  5838         c = Y.config,
       
  5839         publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
       
  5840     // suppress log message if the config is off or the event stack
       
  5841     // or the event call stack contains a consumer of the yui:log event
       
  5842     if (c.debug) {
       
  5843         // apply source filters
       
  5844         src = src || "";
       
  5845         if (typeof src !== "undefined") {
       
  5846             excl = c.logExclude;
       
  5847             incl = c.logInclude;
       
  5848             if (incl && !(src in incl)) {
       
  5849                 bail = 1;
       
  5850             } else if (incl && (src in incl)) {
       
  5851                 bail = !incl[src];
       
  5852             } else if (excl && (src in excl)) {
       
  5853                 bail = excl[src];
       
  5854             }
       
  5855 
       
  5856             // Determine the current minlevel as defined in configuration
       
  5857             Y.config.logLevel = Y.config.logLevel || 'debug';
       
  5858             minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
       
  5859 
       
  5860             if (cat in LEVELS && LEVELS[cat] < minlevel) {
       
  5861                 // Skip this message if the we don't meet the defined minlevel
       
  5862                 bail = 1;
       
  5863             }
       
  5864         }
       
  5865         if (!bail) {
       
  5866             if (c.useBrowserConsole) {
       
  5867                 m = (src) ? src + ': ' + msg : msg;
       
  5868                 if (Y.Lang.isFunction(c.logFn)) {
       
  5869                     c.logFn.call(Y, msg, cat, src);
       
  5870                 } else if (typeof console !== UNDEFINED && console.log) {
       
  5871                     f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
       
  5872                     console[f](m);
       
  5873                 } else if (typeof opera !== UNDEFINED) {
       
  5874                     opera.postError(m);
       
  5875                 }
       
  5876             }
       
  5877 
       
  5878             if (publisher && !silent) {
       
  5879 
       
  5880                 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
       
  5881                     publisher.publish(LOGEVENT, {
       
  5882                         broadcast: 2
       
  5883                     });
       
  5884                 }
       
  5885 
       
  5886                 publisher.fire(LOGEVENT, {
       
  5887                     msg: msg,
       
  5888                     cat: cat,
       
  5889                     src: src
       
  5890                 });
       
  5891             }
       
  5892         }
       
  5893     }
       
  5894 
       
  5895     return Y;
       
  5896 };
       
  5897 
       
  5898 /**
       
  5899  * Write a system message.  This message will be preserved in the
       
  5900  * minified and raw versions of the YUI files, unlike log statements.
       
  5901  * @method message
       
  5902  * @for YUI
       
  5903  * @param  {String}  msg  The message to log.
       
  5904  * @param  {String}  cat  The log category for the message.  Default
       
  5905  *                        categories are "info", "warn", "error", time".
       
  5906  *                        Custom categories can be used as well. (opt).
       
  5907  * @param  {String}  src  The source of the the message (opt).
       
  5908  * @param  {boolean} silent If true, the log event won't fire.
       
  5909  * @return {YUI}      YUI instance.
       
  5910  */
       
  5911 INSTANCE.message = function() {
       
  5912     return INSTANCE.log.apply(INSTANCE, arguments);
       
  5913 };
       
  5914 
       
  5915 
       
  5916 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5917 YUI.add('yui-later', function (Y, NAME) {
       
  5918 
       
  5919 /**
       
  5920  * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module,
       
  5921  * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
       
  5922  *
       
  5923  * @module yui
       
  5924  * @submodule yui-later
       
  5925  */
       
  5926 
       
  5927 var NO_ARGS = [];
       
  5928 
       
  5929 /**
       
  5930  * Executes the supplied function in the context of the supplied
       
  5931  * object 'when' milliseconds later.  Executes the function a
       
  5932  * single time unless periodic is set to true.
       
  5933  * @for YUI
       
  5934  * @method later
       
  5935  * @param when {int} the number of milliseconds to wait until the fn
       
  5936  * is executed.
       
  5937  * @param o the context object.
       
  5938  * @param fn {Function|String} the function to execute or the name of
       
  5939  * the method in the 'o' object to execute.
       
  5940  * @param data [Array] data that is provided to the function.  This
       
  5941  * accepts either a single item or an array.  If an array is provided,
       
  5942  * the function is executed with one parameter for each array item.
       
  5943  * If you need to pass a single array parameter, it needs to be wrapped
       
  5944  * in an array [myarray].
       
  5945  *
       
  5946  * Note: native methods in IE may not have the call and apply methods.
       
  5947  * In this case, it will work, but you are limited to four arguments.
       
  5948  *
       
  5949  * @param periodic {boolean} if true, executes continuously at supplied
       
  5950  * interval until canceled.
       
  5951  * @return {object} a timer object. Call the cancel() method on this
       
  5952  * object to stop the timer.
       
  5953  */
       
  5954 Y.later = function(when, o, fn, data, periodic) {
       
  5955     when = when || 0;
       
  5956     data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
       
  5957     o = o || Y.config.win || Y;
       
  5958 
       
  5959     var cancelled = false,
       
  5960         method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
       
  5961         wrapper = function() {
       
  5962             // IE 8- may execute a setInterval callback one last time
       
  5963             // after clearInterval was called, so in order to preserve
       
  5964             // the cancel() === no more runny-run, we have to jump through
       
  5965             // an extra hoop.
       
  5966             if (!cancelled) {
       
  5967                 if (!method.apply) {
       
  5968                     method(data[0], data[1], data[2], data[3]);
       
  5969                 } else {
       
  5970                     method.apply(o, data || NO_ARGS);
       
  5971                 }
       
  5972             }
       
  5973         },
       
  5974         id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
       
  5975 
       
  5976     return {
       
  5977         id: id,
       
  5978         interval: periodic,
       
  5979         cancel: function() {
       
  5980             cancelled = true;
       
  5981             if (this.interval) {
       
  5982                 clearInterval(id);
       
  5983             } else {
       
  5984                 clearTimeout(id);
       
  5985             }
       
  5986         }
       
  5987     };
       
  5988 };
       
  5989 
       
  5990 Y.Lang.later = Y.later;
       
  5991 
       
  5992 
       
  5993 
       
  5994 }, '@VERSION@', {"requires": ["yui-base"]});
       
  5995 YUI.add('yui', function (Y, NAME) {}, '@VERSION@', {"use": ["get", "features", "intl-base", "yui-log", "yui-later"]});
       
  5996 YUI.add('oop', function (Y, NAME) {
       
  5997 
       
  5998 /**
       
  5999 Adds object inheritance and manipulation utilities to the YUI instance. This
       
  6000 module is required by most YUI components.
       
  6001 
       
  6002 @module oop
       
  6003 **/
       
  6004 
       
  6005 var L            = Y.Lang,
       
  6006     A            = Y.Array,
       
  6007     OP           = Object.prototype,
       
  6008     CLONE_MARKER = '_~yuim~_',
       
  6009 
       
  6010     hasOwn   = OP.hasOwnProperty,
       
  6011     toString = OP.toString;
       
  6012 
       
  6013 function dispatch(o, f, c, proto, action) {
       
  6014     if (o && o[action] && o !== Y) {
       
  6015         return o[action].call(o, f, c);
       
  6016     } else {
       
  6017         switch (A.test(o)) {
       
  6018             case 1:
       
  6019                 return A[action](o, f, c);
       
  6020             case 2:
       
  6021                 return A[action](Y.Array(o, 0, true), f, c);
       
  6022             default:
       
  6023                 return Y.Object[action](o, f, c, proto);
       
  6024         }
       
  6025     }
       
  6026 }
       
  6027 
       
  6028 /**
       
  6029 Augments the _receiver_ with prototype properties from the _supplier_. The
       
  6030 receiver may be a constructor function or an object. The supplier must be a
       
  6031 constructor function.
       
  6032 
       
  6033 If the _receiver_ is an object, then the _supplier_ constructor will be called
       
  6034 immediately after _receiver_ is augmented, with _receiver_ as the `this` object.
       
  6035 
       
  6036 If the _receiver_ is a constructor function, then all prototype methods of
       
  6037 _supplier_ that are copied to _receiver_ will be sequestered, and the
       
  6038 _supplier_ constructor will not be called immediately. The first time any
       
  6039 sequestered method is called on the _receiver_'s prototype, all sequestered
       
  6040 methods will be immediately copied to the _receiver_'s prototype, the
       
  6041 _supplier_'s constructor will be executed, and finally the newly unsequestered
       
  6042 method that was called will be executed.
       
  6043 
       
  6044 This sequestering logic sounds like a bunch of complicated voodoo, but it makes
       
  6045 it cheap to perform frequent augmentation by ensuring that suppliers'
       
  6046 constructors are only called if a supplied method is actually used. If none of
       
  6047 the supplied methods is ever used, then there's no need to take the performance
       
  6048 hit of calling the _supplier_'s constructor.
       
  6049 
       
  6050 @method augment
       
  6051 @param {Function|Object} receiver Object or function to be augmented.
       
  6052 @param {Function} supplier Function that supplies the prototype properties with
       
  6053   which to augment the _receiver_.
       
  6054 @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
       
  6055   will be overwritten if found on the supplier's prototype.
       
  6056 @param {String[]} [whitelist] An array of property names. If specified,
       
  6057   only the whitelisted prototype properties will be applied to the receiver, and
       
  6058   all others will be ignored.
       
  6059 @param {Array|any} [args] Argument or array of arguments to pass to the
       
  6060   supplier's constructor when initializing.
       
  6061 @return {Function} Augmented object.
       
  6062 @for YUI
       
  6063 **/
       
  6064 Y.augment = function (receiver, supplier, overwrite, whitelist, args) {
       
  6065     var rProto    = receiver.prototype,
       
  6066         sequester = rProto && supplier,
       
  6067         sProto    = supplier.prototype,
       
  6068         to        = rProto || receiver,
       
  6069 
       
  6070         copy,
       
  6071         newPrototype,
       
  6072         replacements,
       
  6073         sequestered,
       
  6074         unsequester;
       
  6075 
       
  6076     args = args ? Y.Array(args) : [];
       
  6077 
       
  6078     if (sequester) {
       
  6079         newPrototype = {};
       
  6080         replacements = {};
       
  6081         sequestered  = {};
       
  6082 
       
  6083         copy = function (value, key) {
       
  6084             if (overwrite || !(key in rProto)) {
       
  6085                 if (toString.call(value) === '[object Function]') {
       
  6086                     sequestered[key] = value;
       
  6087 
       
  6088                     newPrototype[key] = replacements[key] = function () {
       
  6089                         return unsequester(this, value, arguments);
       
  6090                     };
       
  6091                 } else {
       
  6092                     newPrototype[key] = value;
       
  6093                 }
       
  6094             }
       
  6095         };
       
  6096 
       
  6097         unsequester = function (instance, fn, fnArgs) {
       
  6098             // Unsequester all sequestered functions.
       
  6099             for (var key in sequestered) {
       
  6100                 if (hasOwn.call(sequestered, key)
       
  6101                         && instance[key] === replacements[key]) {
       
  6102 
       
  6103                     instance[key] = sequestered[key];
       
  6104                 }
       
  6105             }
       
  6106 
       
  6107             // Execute the supplier constructor.
       
  6108             supplier.apply(instance, args);
       
  6109 
       
  6110             // Finally, execute the original sequestered function.
       
  6111             return fn.apply(instance, fnArgs);
       
  6112         };
       
  6113 
       
  6114         if (whitelist) {
       
  6115             Y.Array.each(whitelist, function (name) {
       
  6116                 if (name in sProto) {
       
  6117                     copy(sProto[name], name);
       
  6118                 }
       
  6119             });
       
  6120         } else {
       
  6121             Y.Object.each(sProto, copy, null, true);
       
  6122         }
       
  6123     }
       
  6124 
       
  6125     Y.mix(to, newPrototype || sProto, overwrite, whitelist);
       
  6126 
       
  6127     if (!sequester) {
       
  6128         supplier.apply(to, args);
       
  6129     }
       
  6130 
       
  6131     return receiver;
       
  6132 };
       
  6133 
       
  6134 /**
       
  6135  * Copies object properties from the supplier to the receiver. If the target has
       
  6136  * the property, and the property is an object, the target object will be
       
  6137  * augmented with the supplier's value.
       
  6138  *
       
  6139  * @method aggregate
       
  6140  * @param {Object} receiver Object to receive the augmentation.
       
  6141  * @param {Object} supplier Object that supplies the properties with which to
       
  6142  *     augment the receiver.
       
  6143  * @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
       
  6144  *     will be overwritten if found on the supplier.
       
  6145  * @param {String[]} [whitelist] Whitelist. If supplied, only properties in this
       
  6146  *     list will be applied to the receiver.
       
  6147  * @return {Object} Augmented object.
       
  6148  */
       
  6149 Y.aggregate = function(r, s, ov, wl) {
       
  6150     return Y.mix(r, s, ov, wl, 0, true);
       
  6151 };
       
  6152 
       
  6153 /**
       
  6154  * Utility to set up the prototype, constructor and superclass properties to
       
  6155  * support an inheritance strategy that can chain constructors and methods.
       
  6156  * Static members will not be inherited.
       
  6157  *
       
  6158  * @method extend
       
  6159  * @param {function} r   the object to modify.
       
  6160  * @param {function} s the object to inherit.
       
  6161  * @param {object} px prototype properties to add/override.
       
  6162  * @param {object} sx static properties to add/override.
       
  6163  * @return {object} the extended object.
       
  6164  */
       
  6165 Y.extend = function(r, s, px, sx) {
       
  6166     if (!s || !r) {
       
  6167         Y.error('extend failed, verify dependencies');
       
  6168     }
       
  6169 
       
  6170     var sp = s.prototype, rp = Y.Object(sp);
       
  6171     r.prototype = rp;
       
  6172 
       
  6173     rp.constructor = r;
       
  6174     r.superclass = sp;
       
  6175 
       
  6176     // assign constructor property
       
  6177     if (s != Object && sp.constructor == OP.constructor) {
       
  6178         sp.constructor = s;
       
  6179     }
       
  6180 
       
  6181     // add prototype overrides
       
  6182     if (px) {
       
  6183         Y.mix(rp, px, true);
       
  6184     }
       
  6185 
       
  6186     // add object overrides
       
  6187     if (sx) {
       
  6188         Y.mix(r, sx, true);
       
  6189     }
       
  6190 
       
  6191     return r;
       
  6192 };
       
  6193 
       
  6194 /**
       
  6195  * Executes the supplied function for each item in
       
  6196  * a collection.  Supports arrays, objects, and
       
  6197  * NodeLists
       
  6198  * @method each
       
  6199  * @param {object} o the object to iterate.
       
  6200  * @param {function} f the function to execute.  This function
       
  6201  * receives the value, key, and object as parameters.
       
  6202  * @param {object} c the execution context for the function.
       
  6203  * @param {boolean} proto if true, prototype properties are
       
  6204  * iterated on objects.
       
  6205  * @return {YUI} the YUI instance.
       
  6206  */
       
  6207 Y.each = function(o, f, c, proto) {
       
  6208     return dispatch(o, f, c, proto, 'each');
       
  6209 };
       
  6210 
       
  6211 /**
       
  6212  * Executes the supplied function for each item in
       
  6213  * a collection.  The operation stops if the function
       
  6214  * returns true. Supports arrays, objects, and
       
  6215  * NodeLists.
       
  6216  * @method some
       
  6217  * @param {object} o the object to iterate.
       
  6218  * @param {function} f the function to execute.  This function
       
  6219  * receives the value, key, and object as parameters.
       
  6220  * @param {object} c the execution context for the function.
       
  6221  * @param {boolean} proto if true, prototype properties are
       
  6222  * iterated on objects.
       
  6223  * @return {boolean} true if the function ever returns true,
       
  6224  * false otherwise.
       
  6225  */
       
  6226 Y.some = function(o, f, c, proto) {
       
  6227     return dispatch(o, f, c, proto, 'some');
       
  6228 };
       
  6229 
       
  6230 /**
       
  6231 Deep object/array copy. Function clones are actually wrappers around the
       
  6232 original function. Array-like objects are treated as arrays. Primitives are
       
  6233 returned untouched. Optionally, a function can be provided to handle other data
       
  6234 types, filter keys, validate values, etc.
       
  6235 
       
  6236 **Note:** Cloning a non-trivial object is a reasonably heavy operation, due to
       
  6237 the need to recursively iterate down non-primitive properties. Clone should be
       
  6238 used only when a deep clone down to leaf level properties is explicitly
       
  6239 required. This method will also
       
  6240 
       
  6241 In many cases (for example, when trying to isolate objects used as hashes for
       
  6242 configuration properties), a shallow copy, using `Y.merge()` is normally
       
  6243 sufficient. If more than one level of isolation is required, `Y.merge()` can be
       
  6244 used selectively at each level which needs to be isolated from the original
       
  6245 without going all the way to leaf properties.
       
  6246 
       
  6247 @method clone
       
  6248 @param {object} o what to clone.
       
  6249 @param {boolean} safe if true, objects will not have prototype items from the
       
  6250     source. If false, they will. In this case, the original is initially
       
  6251     protected, but the clone is not completely immune from changes to the source
       
  6252     object prototype. Also, cloned prototype items that are deleted from the
       
  6253     clone will result in the value of the source prototype being exposed. If
       
  6254     operating on a non-safe clone, items should be nulled out rather than
       
  6255     deleted.
       
  6256 @param {function} f optional function to apply to each item in a collection; it
       
  6257     will be executed prior to applying the value to the new object.
       
  6258     Return false to prevent the copy.
       
  6259 @param {object} c optional execution context for f.
       
  6260 @param {object} owner Owner object passed when clone is iterating an object.
       
  6261     Used to set up context for cloned functions.
       
  6262 @param {object} cloned hash of previously cloned objects to avoid multiple
       
  6263     clones.
       
  6264 @return {Array|Object} the cloned object.
       
  6265 **/
       
  6266 Y.clone = function(o, safe, f, c, owner, cloned) {
       
  6267     var o2, marked, stamp;
       
  6268 
       
  6269     // Does not attempt to clone:
       
  6270     //
       
  6271     // * Non-typeof-object values, "primitive" values don't need cloning.
       
  6272     //
       
  6273     // * YUI instances, cloning complex object like YUI instances is not
       
  6274     //   advised, this is like cloning the world.
       
  6275     //
       
  6276     // * DOM nodes (#2528250), common host objects like DOM nodes cannot be
       
  6277     //   "subclassed" in Firefox and old versions of IE. Trying to use
       
  6278     //   `Object.create()` or `Y.extend()` on a DOM node will throw an error in
       
  6279     //   these browsers.
       
  6280     //
       
  6281     // Instad, the passed-in `o` will be return as-is when it matches one of the
       
  6282     // above criteria.
       
  6283     if (!L.isObject(o) ||
       
  6284             Y.instanceOf(o, YUI) ||
       
  6285             (o.addEventListener || o.attachEvent)) {
       
  6286 
       
  6287         return o;
       
  6288     }
       
  6289 
       
  6290     marked = cloned || {};
       
  6291 
       
  6292     switch (L.type(o)) {
       
  6293         case 'date':
       
  6294             return new Date(o);
       
  6295         case 'regexp':
       
  6296             // if we do this we need to set the flags too
       
  6297             // return new RegExp(o.source);
       
  6298             return o;
       
  6299         case 'function':
       
  6300             // o2 = Y.bind(o, owner);
       
  6301             // break;
       
  6302             return o;
       
  6303         case 'array':
       
  6304             o2 = [];
       
  6305             break;
       
  6306         default:
       
  6307 
       
  6308             // #2528250 only one clone of a given object should be created.
       
  6309             if (o[CLONE_MARKER]) {
       
  6310                 return marked[o[CLONE_MARKER]];
       
  6311             }
       
  6312 
       
  6313             stamp = Y.guid();
       
  6314 
       
  6315             o2 = (safe) ? {} : Y.Object(o);
       
  6316 
       
  6317             o[CLONE_MARKER] = stamp;
       
  6318             marked[stamp] = o;
       
  6319     }
       
  6320 
       
  6321     Y.each(o, function(v, k) {
       
  6322         if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
       
  6323             if (k !== CLONE_MARKER) {
       
  6324                 if (k == 'prototype') {
       
  6325                     // skip the prototype
       
  6326                 // } else if (o[k] === o) {
       
  6327                 //     this[k] = this;
       
  6328                 } else {
       
  6329                     this[k] =
       
  6330                         Y.clone(v, safe, f, c, owner || o, marked);
       
  6331                 }
       
  6332             }
       
  6333         }
       
  6334     }, o2);
       
  6335 
       
  6336     if (!cloned) {
       
  6337         Y.Object.each(marked, function(v, k) {
       
  6338             if (v[CLONE_MARKER]) {
       
  6339                 try {
       
  6340                     delete v[CLONE_MARKER];
       
  6341                 } catch (e) {
       
  6342                     v[CLONE_MARKER] = null;
       
  6343                 }
       
  6344             }
       
  6345         }, this);
       
  6346         marked = null;
       
  6347     }
       
  6348 
       
  6349     return o2;
       
  6350 };
       
  6351 
       
  6352 /**
       
  6353  * Returns a function that will execute the supplied function in the
       
  6354  * supplied object's context, optionally adding any additional
       
  6355  * supplied parameters to the beginning of the arguments collection the
       
  6356  * supplied to the function.
       
  6357  *
       
  6358  * @method bind
       
  6359  * @param {Function|String} f the function to bind, or a function name
       
  6360  * to execute on the context object.
       
  6361  * @param {object} c the execution context.
       
  6362  * @param {any} args* 0..n arguments to include before the arguments the
       
  6363  * function is executed with.
       
  6364  * @return {function} the wrapped function.
       
  6365  */
       
  6366 Y.bind = function(f, c) {
       
  6367     var xargs = arguments.length > 2 ?
       
  6368             Y.Array(arguments, 2, true) : null;
       
  6369     return function() {
       
  6370         var fn = L.isString(f) ? c[f] : f,
       
  6371             args = (xargs) ?
       
  6372                 xargs.concat(Y.Array(arguments, 0, true)) : arguments;
       
  6373         return fn.apply(c || fn, args);
       
  6374     };
       
  6375 };
       
  6376 
       
  6377 /**
       
  6378  * Returns a function that will execute the supplied function in the
       
  6379  * supplied object's context, optionally adding any additional
       
  6380  * supplied parameters to the end of the arguments the function
       
  6381  * is executed with.
       
  6382  *
       
  6383  * @method rbind
       
  6384  * @param {Function|String} f the function to bind, or a function name
       
  6385  * to execute on the context object.
       
  6386  * @param {object} c the execution context.
       
  6387  * @param {any} args* 0..n arguments to append to the end of
       
  6388  * arguments collection supplied to the function.
       
  6389  * @return {function} the wrapped function.
       
  6390  */
       
  6391 Y.rbind = function(f, c) {
       
  6392     var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
       
  6393     return function() {
       
  6394         var fn = L.isString(f) ? c[f] : f,
       
  6395             args = (xargs) ?
       
  6396                 Y.Array(arguments, 0, true).concat(xargs) : arguments;
       
  6397         return fn.apply(c || fn, args);
       
  6398     };
       
  6399 };
       
  6400 
       
  6401 
       
  6402 }, '@VERSION@', {"requires": ["yui-base"]});
       
  6403 YUI.add('features', function (Y, NAME) {
       
  6404 
       
  6405 var feature_tests = {};
       
  6406 
       
  6407 /**
       
  6408 Contains the core of YUI's feature test architecture.
       
  6409 @module features
       
  6410 */
       
  6411 
       
  6412 /**
       
  6413 * Feature detection
       
  6414 * @class Features
       
  6415 * @static
       
  6416 */
       
  6417 
       
  6418 Y.mix(Y.namespace('Features'), {
       
  6419 
       
  6420     /**
       
  6421     * Object hash of all registered feature tests
       
  6422     * @property tests
       
  6423     * @type Object
       
  6424     */
       
  6425     tests: feature_tests,
       
  6426 
       
  6427     /**
       
  6428     * Add a test to the system
       
  6429     *
       
  6430     *   ```
       
  6431     *   Y.Features.add("load", "1", {});
       
  6432     *   ```
       
  6433     *
       
  6434     * @method add
       
  6435     * @param {String} cat The category, right now only 'load' is supported
       
  6436     * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
       
  6437     * @param {Object} o Object containing test properties
       
  6438     * @param {String} o.name The name of the test
       
  6439     * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
       
  6440     * @param {String} o.trigger The module that triggers this test.
       
  6441     */
       
  6442     add: function(cat, name, o) {
       
  6443         feature_tests[cat] = feature_tests[cat] || {};
       
  6444         feature_tests[cat][name] = o;
       
  6445     },
       
  6446     /**
       
  6447     * Execute all tests of a given category and return the serialized results
       
  6448     *
       
  6449     *   ```
       
  6450     *   caps=1:1;2:1;3:0
       
  6451     *   ```
       
  6452     * @method all
       
  6453     * @param {String} cat The category to execute
       
  6454     * @param {Array} args The arguments to pass to the test function
       
  6455     * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
       
  6456     */
       
  6457     all: function(cat, args) {
       
  6458         var cat_o = feature_tests[cat],
       
  6459             // results = {};
       
  6460             result = [];
       
  6461         if (cat_o) {
       
  6462             Y.Object.each(cat_o, function(v, k) {
       
  6463                 result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
       
  6464             });
       
  6465         }
       
  6466 
       
  6467         return (result.length) ? result.join(';') : '';
       
  6468     },
       
  6469     /**
       
  6470     * Run a sepecific test and return a Boolean response.
       
  6471     *
       
  6472     *   ```
       
  6473     *   Y.Features.test("load", "1");
       
  6474     *   ```
       
  6475     *
       
  6476     * @method test
       
  6477     * @param {String} cat The category of the test to run
       
  6478     * @param {String} name The name of the test to run
       
  6479     * @param {Array} args The arguments to pass to the test function
       
  6480     * @return {Boolean} True or false if the test passed/failed.
       
  6481     */
       
  6482     test: function(cat, name, args) {
       
  6483         args = args || [];
       
  6484         var result, ua, test,
       
  6485             cat_o = feature_tests[cat],
       
  6486             feature = cat_o && cat_o[name];
       
  6487 
       
  6488         if (!feature) {
       
  6489             Y.log('Feature test ' + cat + ', ' + name + ' not found');
       
  6490         } else {
       
  6491 
       
  6492             result = feature.result;
       
  6493 
       
  6494             if (Y.Lang.isUndefined(result)) {
       
  6495 
       
  6496                 ua = feature.ua;
       
  6497                 if (ua) {
       
  6498                     result = (Y.UA[ua]);
       
  6499                 }
       
  6500 
       
  6501                 test = feature.test;
       
  6502                 if (test && ((!ua) || result)) {
       
  6503                     result = test.apply(Y, args);
       
  6504                 }
       
  6505 
       
  6506                 feature.result = result;
       
  6507             }
       
  6508         }
       
  6509 
       
  6510         return result;
       
  6511     }
       
  6512 });
       
  6513 
       
  6514 // Y.Features.add("load", "1", {});
       
  6515 // Y.Features.test("load", "1");
       
  6516 // caps=1:1;2:0;3:1;
       
  6517 
       
  6518 /* This file is auto-generated by (yogi loader --yes --mix --start ../) */
       
  6519 /*jshint maxlen:900, eqeqeq: false */
       
  6520 var add = Y.Features.add;
       
  6521 // app-transitions-native
       
  6522 add('load', '0', {
       
  6523     "name": "app-transitions-native",
       
  6524     "test": function (Y) {
       
  6525     var doc  = Y.config.doc,
       
  6526         node = doc ? doc.documentElement : null;
       
  6527 
       
  6528     if (node && node.style) {
       
  6529         return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  6530     }
       
  6531 
       
  6532     return false;
       
  6533 },
       
  6534     "trigger": "app-transitions"
       
  6535 });
       
  6536 // autocomplete-list-keys
       
  6537 add('load', '1', {
       
  6538     "name": "autocomplete-list-keys",
       
  6539     "test": function (Y) {
       
  6540     // Only add keyboard support to autocomplete-list if this doesn't appear to
       
  6541     // be an iOS or Android-based mobile device.
       
  6542     //
       
  6543     // There's currently no feasible way to actually detect whether a device has
       
  6544     // a hardware keyboard, so this sniff will have to do. It can easily be
       
  6545     // overridden by manually loading the autocomplete-list-keys module.
       
  6546     //
       
  6547     // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
       
  6548     // doesn't fire the keyboard events used by AutoCompleteList, so there's
       
  6549     // no point loading the -keys module even when a bluetooth keyboard may be
       
  6550     // available.
       
  6551     return !(Y.UA.ios || Y.UA.android);
       
  6552 },
       
  6553     "trigger": "autocomplete-list"
       
  6554 });
       
  6555 // dd-gestures
       
  6556 add('load', '2', {
       
  6557     "name": "dd-gestures",
       
  6558     "trigger": "dd-drag",
       
  6559     "ua": "touchEnabled"
       
  6560 });
       
  6561 // dom-style-ie
       
  6562 add('load', '3', {
       
  6563     "name": "dom-style-ie",
       
  6564     "test": function (Y) {
       
  6565 
       
  6566     var testFeature = Y.Features.test,
       
  6567         addFeature = Y.Features.add,
       
  6568         WINDOW = Y.config.win,
       
  6569         DOCUMENT = Y.config.doc,
       
  6570         DOCUMENT_ELEMENT = 'documentElement',
       
  6571         ret = false;
       
  6572 
       
  6573     addFeature('style', 'computedStyle', {
       
  6574         test: function() {
       
  6575             return WINDOW && 'getComputedStyle' in WINDOW;
       
  6576         }
       
  6577     });
       
  6578 
       
  6579     addFeature('style', 'opacity', {
       
  6580         test: function() {
       
  6581             return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
       
  6582         }
       
  6583     });
       
  6584 
       
  6585     ret =  (!testFeature('style', 'opacity') &&
       
  6586             !testFeature('style', 'computedStyle'));
       
  6587 
       
  6588     return ret;
       
  6589 },
       
  6590     "trigger": "dom-style"
       
  6591 });
       
  6592 // editor-para-ie
       
  6593 add('load', '4', {
       
  6594     "name": "editor-para-ie",
       
  6595     "trigger": "editor-para",
       
  6596     "ua": "ie",
       
  6597     "when": "instead"
       
  6598 });
       
  6599 // event-base-ie
       
  6600 add('load', '5', {
       
  6601     "name": "event-base-ie",
       
  6602     "test": function(Y) {
       
  6603     var imp = Y.config.doc && Y.config.doc.implementation;
       
  6604     return (imp && (!imp.hasFeature('Events', '2.0')));
       
  6605 },
       
  6606     "trigger": "node-base"
       
  6607 });
       
  6608 // graphics-canvas
       
  6609 add('load', '6', {
       
  6610     "name": "graphics-canvas",
       
  6611     "test": function(Y) {
       
  6612     var DOCUMENT = Y.config.doc,
       
  6613         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  6614 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6615         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6616     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  6617 },
       
  6618     "trigger": "graphics"
       
  6619 });
       
  6620 // graphics-canvas-default
       
  6621 add('load', '7', {
       
  6622     "name": "graphics-canvas-default",
       
  6623     "test": function(Y) {
       
  6624     var DOCUMENT = Y.config.doc,
       
  6625         useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
       
  6626 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6627         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6628     return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
       
  6629 },
       
  6630     "trigger": "graphics"
       
  6631 });
       
  6632 // graphics-svg
       
  6633 add('load', '8', {
       
  6634     "name": "graphics-svg",
       
  6635     "test": function(Y) {
       
  6636     var DOCUMENT = Y.config.doc,
       
  6637         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  6638 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6639         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6640     
       
  6641     return svg && (useSVG || !canvas);
       
  6642 },
       
  6643     "trigger": "graphics"
       
  6644 });
       
  6645 // graphics-svg-default
       
  6646 add('load', '9', {
       
  6647     "name": "graphics-svg-default",
       
  6648     "test": function(Y) {
       
  6649     var DOCUMENT = Y.config.doc,
       
  6650         useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
       
  6651 		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
       
  6652         svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
       
  6653     
       
  6654     return svg && (useSVG || !canvas);
       
  6655 },
       
  6656     "trigger": "graphics"
       
  6657 });
       
  6658 // graphics-vml
       
  6659 add('load', '10', {
       
  6660     "name": "graphics-vml",
       
  6661     "test": function(Y) {
       
  6662     var DOCUMENT = Y.config.doc,
       
  6663 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  6664     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  6665 },
       
  6666     "trigger": "graphics"
       
  6667 });
       
  6668 // graphics-vml-default
       
  6669 add('load', '11', {
       
  6670     "name": "graphics-vml-default",
       
  6671     "test": function(Y) {
       
  6672     var DOCUMENT = Y.config.doc,
       
  6673 		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
       
  6674     return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
       
  6675 },
       
  6676     "trigger": "graphics"
       
  6677 });
       
  6678 // history-hash-ie
       
  6679 add('load', '12', {
       
  6680     "name": "history-hash-ie",
       
  6681     "test": function (Y) {
       
  6682     var docMode = Y.config.doc && Y.config.doc.documentMode;
       
  6683 
       
  6684     return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
       
  6685             !docMode || docMode < 8);
       
  6686 },
       
  6687     "trigger": "history-hash"
       
  6688 });
       
  6689 // io-nodejs
       
  6690 add('load', '13', {
       
  6691     "name": "io-nodejs",
       
  6692     "trigger": "io-base",
       
  6693     "ua": "nodejs"
       
  6694 });
       
  6695 // json-parse-shim
       
  6696 add('load', '14', {
       
  6697     "name": "json-parse-shim",
       
  6698     "test": function (Y) {
       
  6699     var _JSON = Y.config.global.JSON,
       
  6700         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  6701         nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
       
  6702 
       
  6703     function workingNative( k, v ) {
       
  6704         return k === "ok" ? true : v;
       
  6705     }
       
  6706     
       
  6707     // Double check basic functionality.  This is mainly to catch early broken
       
  6708     // implementations of the JSON API in Firefox 3.1 beta1 and beta2
       
  6709     if ( nativeSupport ) {
       
  6710         try {
       
  6711             nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
       
  6712         }
       
  6713         catch ( e ) {
       
  6714             nativeSupport = false;
       
  6715         }
       
  6716     }
       
  6717 
       
  6718     return !nativeSupport;
       
  6719 },
       
  6720     "trigger": "json-parse"
       
  6721 });
       
  6722 // json-stringify-shim
       
  6723 add('load', '15', {
       
  6724     "name": "json-stringify-shim",
       
  6725     "test": function (Y) {
       
  6726     var _JSON = Y.config.global.JSON,
       
  6727         Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
       
  6728         nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
       
  6729 
       
  6730     // Double check basic native functionality.  This is primarily to catch broken
       
  6731     // early JSON API implementations in Firefox 3.1 beta1 and beta2.
       
  6732     if ( nativeSupport ) {
       
  6733         try {
       
  6734             nativeSupport = ( '0' === Native.stringify(0) );
       
  6735         } catch ( e ) {
       
  6736             nativeSupport = false;
       
  6737         }
       
  6738     }
       
  6739 
       
  6740 
       
  6741     return !nativeSupport;
       
  6742 },
       
  6743     "trigger": "json-stringify"
       
  6744 });
       
  6745 // scrollview-base-ie
       
  6746 add('load', '16', {
       
  6747     "name": "scrollview-base-ie",
       
  6748     "trigger": "scrollview-base",
       
  6749     "ua": "ie"
       
  6750 });
       
  6751 // selector-css2
       
  6752 add('load', '17', {
       
  6753     "name": "selector-css2",
       
  6754     "test": function (Y) {
       
  6755     var DOCUMENT = Y.config.doc,
       
  6756         ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
       
  6757 
       
  6758     return ret;
       
  6759 },
       
  6760     "trigger": "selector"
       
  6761 });
       
  6762 // transition-timer
       
  6763 add('load', '18', {
       
  6764     "name": "transition-timer",
       
  6765     "test": function (Y) {
       
  6766     var DOCUMENT = Y.config.doc,
       
  6767         node = (DOCUMENT) ? DOCUMENT.documentElement: null,
       
  6768         ret = true;
       
  6769 
       
  6770     if (node && node.style) {
       
  6771         ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
       
  6772     }
       
  6773 
       
  6774     return ret;
       
  6775 },
       
  6776     "trigger": "transition"
       
  6777 });
       
  6778 // widget-base-ie
       
  6779 add('load', '19', {
       
  6780     "name": "widget-base-ie",
       
  6781     "trigger": "widget-base",
       
  6782     "ua": "ie"
       
  6783 });
       
  6784 // yql-jsonp
       
  6785 add('load', '20', {
       
  6786     "name": "yql-jsonp",
       
  6787     "test": function (Y) {
       
  6788     /* Only load the JSONP module when not in nodejs or winjs
       
  6789     TODO Make the winjs module a CORS module
       
  6790     */
       
  6791     return (!Y.UA.nodejs && !Y.UA.winjs);
       
  6792 },
       
  6793     "trigger": "yql",
       
  6794     "when": "after"
       
  6795 });
       
  6796 // yql-nodejs
       
  6797 add('load', '21', {
       
  6798     "name": "yql-nodejs",
       
  6799     "trigger": "yql",
       
  6800     "ua": "nodejs",
       
  6801     "when": "after"
       
  6802 });
       
  6803 // yql-winjs
       
  6804 add('load', '22', {
       
  6805     "name": "yql-winjs",
       
  6806     "trigger": "yql",
       
  6807     "ua": "winjs",
       
  6808     "when": "after"
       
  6809 });
       
  6810 
       
  6811 }, '@VERSION@', {"requires": ["yui-base"]});
       
  6812 YUI.add('dom-core', function (Y, NAME) {
       
  6813 
       
  6814 var NODE_TYPE = 'nodeType',
       
  6815     OWNER_DOCUMENT = 'ownerDocument',
       
  6816     DOCUMENT_ELEMENT = 'documentElement',
       
  6817     DEFAULT_VIEW = 'defaultView',
       
  6818     PARENT_WINDOW = 'parentWindow',
       
  6819     TAG_NAME = 'tagName',
       
  6820     PARENT_NODE = 'parentNode',
       
  6821     PREVIOUS_SIBLING = 'previousSibling',
       
  6822     NEXT_SIBLING = 'nextSibling',
       
  6823     CONTAINS = 'contains',
       
  6824     COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
       
  6825     EMPTY_ARRAY = [],
       
  6826     
       
  6827     // IE < 8 throws on node.contains(textNode)
       
  6828     supportsContainsTextNode = (function() {
       
  6829         var node = Y.config.doc.createElement('div'),
       
  6830             textNode = node.appendChild(Y.config.doc.createTextNode('')),
       
  6831             result = false;
       
  6832         
       
  6833         try {
       
  6834             result = node.contains(textNode);
       
  6835         } catch(e) {}
       
  6836 
       
  6837         return result;
       
  6838     })(),
       
  6839 
       
  6840 /** 
       
  6841  * The DOM utility provides a cross-browser abtraction layer
       
  6842  * normalizing DOM tasks, and adds extra helper functionality
       
  6843  * for other common tasks. 
       
  6844  * @module dom
       
  6845  * @main dom
       
  6846  * @submodule dom-base
       
  6847  * @for DOM
       
  6848  *
       
  6849  */
       
  6850 
       
  6851 /**
       
  6852  * Provides DOM helper methods.
       
  6853  * @class DOM
       
  6854  *
       
  6855  */
       
  6856     
       
  6857 Y_DOM = {
       
  6858     /**
       
  6859      * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
       
  6860      * @method byId         
       
  6861      * @param {String} id the id attribute 
       
  6862      * @param {Object} doc optional The document to search. Defaults to current document 
       
  6863      * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. 
       
  6864      */
       
  6865     byId: function(id, doc) {
       
  6866         // handle dupe IDs and IE name collision
       
  6867         return Y_DOM.allById(id, doc)[0] || null;
       
  6868     },
       
  6869 
       
  6870     getId: function(node) {
       
  6871         var id;
       
  6872         // HTMLElement returned from FORM when INPUT name === "id"
       
  6873         // IE < 8: HTMLCollection returned when INPUT id === "id"
       
  6874         // via both getAttribute and form.id 
       
  6875         if (node.id && !node.id.tagName && !node.id.item) {
       
  6876             id = node.id;
       
  6877         } else if (node.attributes && node.attributes.id) {
       
  6878             id = node.attributes.id.value;
       
  6879         }
       
  6880 
       
  6881         return id;
       
  6882     },
       
  6883 
       
  6884     setId: function(node, id) {
       
  6885         if (node.setAttribute) {
       
  6886             node.setAttribute('id', id);
       
  6887         } else {
       
  6888             node.id = id;
       
  6889         }
       
  6890     },
       
  6891 
       
  6892     /*
       
  6893      * Finds the ancestor of the element.
       
  6894      * @method ancestor
       
  6895      * @param {HTMLElement} element The html element.
       
  6896      * @param {Function} fn optional An optional boolean test to apply.
       
  6897      * The optional function is passed the current DOM node being tested as its only argument.
       
  6898      * If no function is given, the parentNode is returned.
       
  6899      * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
       
  6900      * @return {HTMLElement | null} The matching DOM node or null if none found. 
       
  6901      */
       
  6902     ancestor: function(element, fn, testSelf, stopFn) {
       
  6903         var ret = null;
       
  6904         if (testSelf) {
       
  6905             ret = (!fn || fn(element)) ? element : null;
       
  6906 
       
  6907         }
       
  6908         return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null, stopFn);
       
  6909     },
       
  6910 
       
  6911     /*
       
  6912      * Finds the ancestors of the element.
       
  6913      * @method ancestors
       
  6914      * @param {HTMLElement} element The html element.
       
  6915      * @param {Function} fn optional An optional boolean test to apply.
       
  6916      * The optional function is passed the current DOM node being tested as its only argument.
       
  6917      * If no function is given, all ancestors are returned.
       
  6918      * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
       
  6919      * @return {Array} An array containing all matching DOM nodes.
       
  6920      */
       
  6921     ancestors: function(element, fn, testSelf, stopFn) {
       
  6922         var ancestor = element,
       
  6923             ret = [];
       
  6924 
       
  6925         while ((ancestor = Y_DOM.ancestor(ancestor, fn, testSelf, stopFn))) {
       
  6926             testSelf = false;
       
  6927             if (ancestor) {
       
  6928                 ret.unshift(ancestor);
       
  6929 
       
  6930                 if (stopFn && stopFn(ancestor)) {
       
  6931                     return ret;
       
  6932                 }
       
  6933             }
       
  6934         }
       
  6935 
       
  6936         return ret;
       
  6937     },
       
  6938 
       
  6939     /**
       
  6940      * Searches the element by the given axis for the first matching element.
       
  6941      * @method elementByAxis
       
  6942      * @param {HTMLElement} element The html element.
       
  6943      * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
       
  6944      * @param {Function} fn optional An optional boolean test to apply.
       
  6945      * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
       
  6946      * The optional function is passed the current HTMLElement being tested as its only argument.
       
  6947      * If no function is given, the first element is returned.
       
  6948      * @return {HTMLElement | null} The matching element or null if none found.
       
  6949      */
       
  6950     elementByAxis: function(element, axis, fn, all, stopAt) {
       
  6951         while (element && (element = element[axis])) { // NOTE: assignment
       
  6952                 if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
       
  6953                     return element;
       
  6954                 }
       
  6955 
       
  6956                 if (stopAt && stopAt(element)) {
       
  6957                     return null;
       
  6958                 }
       
  6959         }
       
  6960         return null;
       
  6961     },
       
  6962 
       
  6963     /**
       
  6964      * Determines whether or not one HTMLElement is or contains another HTMLElement.
       
  6965      * @method contains
       
  6966      * @param {HTMLElement} element The containing html element.
       
  6967      * @param {HTMLElement} needle The html element that may be contained.
       
  6968      * @return {Boolean} Whether or not the element is or contains the needle.
       
  6969      */
       
  6970     contains: function(element, needle) {
       
  6971         var ret = false;
       
  6972 
       
  6973         if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
       
  6974             ret = false;
       
  6975         } else if (element[CONTAINS] &&
       
  6976                 // IE < 8 throws on node.contains(textNode) so fall back to brute.
       
  6977                 // Falling back for other nodeTypes as well.
       
  6978                 (needle[NODE_TYPE] === 1 || supportsContainsTextNode)) {
       
  6979                 ret = element[CONTAINS](needle);
       
  6980         } else if (element[COMPARE_DOCUMENT_POSITION]) {
       
  6981             // Match contains behavior (node.contains(node) === true).
       
  6982             // Needed for Firefox < 4.
       
  6983             if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) { 
       
  6984                 ret = true;
       
  6985             }
       
  6986         } else {
       
  6987             ret = Y_DOM._bruteContains(element, needle);
       
  6988         }
       
  6989 
       
  6990         return ret;
       
  6991     },
       
  6992 
       
  6993     /**
       
  6994      * Determines whether or not the HTMLElement is part of the document.
       
  6995      * @method inDoc
       
  6996      * @param {HTMLElement} element The containing html element.
       
  6997      * @param {HTMLElement} doc optional The document to check.
       
  6998      * @return {Boolean} Whether or not the element is attached to the document. 
       
  6999      */
       
  7000     inDoc: function(element, doc) {
       
  7001         var ret = false,
       
  7002             rootNode;
       
  7003 
       
  7004         if (element && element.nodeType) {
       
  7005             (doc) || (doc = element[OWNER_DOCUMENT]);
       
  7006 
       
  7007             rootNode = doc[DOCUMENT_ELEMENT];
       
  7008 
       
  7009             // contains only works with HTML_ELEMENT
       
  7010             if (rootNode && rootNode.contains && element.tagName) {
       
  7011                 ret = rootNode.contains(element);
       
  7012             } else {
       
  7013                 ret = Y_DOM.contains(rootNode, element);
       
  7014             }
       
  7015         }
       
  7016 
       
  7017         return ret;
       
  7018 
       
  7019     },
       
  7020 
       
  7021    allById: function(id, root) {
       
  7022         root = root || Y.config.doc;
       
  7023         var nodes = [],
       
  7024             ret = [],
       
  7025             i,
       
  7026             node;
       
  7027 
       
  7028         if (root.querySelectorAll) {
       
  7029             ret = root.querySelectorAll('[id="' + id + '"]');
       
  7030         } else if (root.all) {
       
  7031             nodes = root.all(id);
       
  7032 
       
  7033             if (nodes) {
       
  7034                 // root.all may return HTMLElement or HTMLCollection.
       
  7035                 // some elements are also HTMLCollection (FORM, SELECT).
       
  7036                 if (nodes.nodeName) {
       
  7037                     if (nodes.id === id) { // avoid false positive on name
       
  7038                         ret.push(nodes);
       
  7039                         nodes = EMPTY_ARRAY; // done, no need to filter
       
  7040                     } else { //  prep for filtering
       
  7041                         nodes = [nodes];
       
  7042                     }
       
  7043                 }
       
  7044 
       
  7045                 if (nodes.length) {
       
  7046                     // filter out matches on node.name
       
  7047                     // and element.id as reference to element with id === 'id'
       
  7048                     for (i = 0; node = nodes[i++];) {
       
  7049                         if (node.id === id  || 
       
  7050                                 (node.attributes && node.attributes.id &&
       
  7051                                 node.attributes.id.value === id)) { 
       
  7052                             ret.push(node);
       
  7053                         }
       
  7054                     }
       
  7055                 }
       
  7056             }
       
  7057         } else {
       
  7058             ret = [Y_DOM._getDoc(root).getElementById(id)];
       
  7059         }
       
  7060     
       
  7061         return ret;
       
  7062    },
       
  7063 
       
  7064 
       
  7065     isWindow: function(obj) {
       
  7066         return !!(obj && obj.scrollTo && obj.document);
       
  7067     },
       
  7068 
       
  7069     _removeChildNodes: function(node) {
       
  7070         while (node.firstChild) {
       
  7071             node.removeChild(node.firstChild);
       
  7072         }
       
  7073     },
       
  7074 
       
  7075     siblings: function(node, fn) {
       
  7076         var nodes = [],
       
  7077             sibling = node;
       
  7078 
       
  7079         while ((sibling = sibling[PREVIOUS_SIBLING])) {
       
  7080             if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
       
  7081                 nodes.unshift(sibling);
       
  7082             }
       
  7083         }
       
  7084 
       
  7085         sibling = node;
       
  7086         while ((sibling = sibling[NEXT_SIBLING])) {
       
  7087             if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
       
  7088                 nodes.push(sibling);
       
  7089             }
       
  7090         }
       
  7091 
       
  7092         return nodes;
       
  7093     },
       
  7094 
       
  7095     /**
       
  7096      * Brute force version of contains.
       
  7097      * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
       
  7098      * @method _bruteContains
       
  7099      * @private
       
  7100      * @param {HTMLElement} element The containing html element.
       
  7101      * @param {HTMLElement} needle The html element that may be contained.
       
  7102      * @return {Boolean} Whether or not the element is or contains the needle.
       
  7103      */
       
  7104     _bruteContains: function(element, needle) {
       
  7105         while (needle) {
       
  7106             if (element === needle) {
       
  7107                 return true;
       
  7108             }
       
  7109             needle = needle.parentNode;
       
  7110         }
       
  7111         return false;
       
  7112     },
       
  7113 
       
  7114 // TODO: move to Lang?
       
  7115     /**
       
  7116      * Memoizes dynamic regular expressions to boost runtime performance. 
       
  7117      * @method _getRegExp
       
  7118      * @private
       
  7119      * @param {String} str The string to convert to a regular expression.
       
  7120      * @param {String} flags optional An optinal string of flags.
       
  7121      * @return {RegExp} An instance of RegExp
       
  7122      */
       
  7123     _getRegExp: function(str, flags) {
       
  7124         flags = flags || '';
       
  7125         Y_DOM._regexCache = Y_DOM._regexCache || {};
       
  7126         if (!Y_DOM._regexCache[str + flags]) {
       
  7127             Y_DOM._regexCache[str + flags] = new RegExp(str, flags);
       
  7128         }
       
  7129         return Y_DOM._regexCache[str + flags];
       
  7130     },
       
  7131 
       
  7132 // TODO: make getDoc/Win true privates?
       
  7133     /**
       
  7134      * returns the appropriate document.
       
  7135      * @method _getDoc
       
  7136      * @private
       
  7137      * @param {HTMLElement} element optional Target element.
       
  7138      * @return {Object} The document for the given element or the default document. 
       
  7139      */
       
  7140     _getDoc: function(element) {
       
  7141         var doc = Y.config.doc;
       
  7142         if (element) {
       
  7143             doc = (element[NODE_TYPE] === 9) ? element : // element === document
       
  7144                 element[OWNER_DOCUMENT] || // element === DOM node
       
  7145                 element.document || // element === window
       
  7146                 Y.config.doc; // default
       
  7147         }
       
  7148 
       
  7149         return doc;
       
  7150     },
       
  7151 
       
  7152     /**
       
  7153      * returns the appropriate window.
       
  7154      * @method _getWin
       
  7155      * @private
       
  7156      * @param {HTMLElement} element optional Target element.
       
  7157      * @return {Object} The window for the given element or the default window. 
       
  7158      */
       
  7159     _getWin: function(element) {
       
  7160         var doc = Y_DOM._getDoc(element);
       
  7161         return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
       
  7162     },
       
  7163 
       
  7164     _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
       
  7165         fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
       
  7166         var result,
       
  7167             i = 0,
       
  7168             node,
       
  7169             ret;
       
  7170 
       
  7171         if (fn && nodes) {
       
  7172             while ((node = nodes[i++])) {
       
  7173                 result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
       
  7174                 if (typeof result !== 'undefined') {
       
  7175                     (ret) || (ret = []);
       
  7176                     ret.push(result);
       
  7177                 }
       
  7178             }
       
  7179         }
       
  7180 
       
  7181         return (typeof ret !== 'undefined') ? ret : nodes;
       
  7182     },
       
  7183 
       
  7184     generateID: function(el) {
       
  7185         var id = el.id;
       
  7186 
       
  7187         if (!id) {
       
  7188             id = Y.stamp(el);
       
  7189             el.id = id; 
       
  7190         }   
       
  7191 
       
  7192         return id; 
       
  7193     }
       
  7194 };
       
  7195 
       
  7196 
       
  7197 Y.DOM = Y_DOM;
       
  7198 
       
  7199 
       
  7200 }, '@VERSION@', {"requires": ["oop", "features"]});
       
  7201 YUI.add('dom-base', function (Y, NAME) {
       
  7202 
       
  7203 /**
       
  7204 * @for DOM
       
  7205 * @module dom
       
  7206 */
       
  7207 var documentElement = Y.config.doc.documentElement,
       
  7208     Y_DOM = Y.DOM,
       
  7209     TAG_NAME = 'tagName',
       
  7210     OWNER_DOCUMENT = 'ownerDocument',
       
  7211     EMPTY_STRING = '',
       
  7212     addFeature = Y.Features.add,
       
  7213     testFeature = Y.Features.test;
       
  7214 
       
  7215 Y.mix(Y_DOM, {
       
  7216     /**
       
  7217      * Returns the text content of the HTMLElement. 
       
  7218      * @method getText         
       
  7219      * @param {HTMLElement} element The html element. 
       
  7220      * @return {String} The text content of the element (includes text of any descending elements).
       
  7221      */
       
  7222     getText: (documentElement.textContent !== undefined) ?
       
  7223         function(element) {
       
  7224             var ret = '';
       
  7225             if (element) {
       
  7226                 ret = element.textContent;
       
  7227             }
       
  7228             return ret || '';
       
  7229         } : function(element) {
       
  7230             var ret = '';
       
  7231             if (element) {
       
  7232                 ret = element.innerText || element.nodeValue; // might be a textNode
       
  7233             }
       
  7234             return ret || '';
       
  7235         },
       
  7236 
       
  7237     /**
       
  7238      * Sets the text content of the HTMLElement. 
       
  7239      * @method setText         
       
  7240      * @param {HTMLElement} element The html element. 
       
  7241      * @param {String} content The content to add. 
       
  7242      */
       
  7243     setText: (documentElement.textContent !== undefined) ?
       
  7244         function(element, content) {
       
  7245             if (element) {
       
  7246                 element.textContent = content;
       
  7247             }
       
  7248         } : function(element, content) {
       
  7249             if ('innerText' in element) {
       
  7250                 element.innerText = content;
       
  7251             } else if ('nodeValue' in element) {
       
  7252                 element.nodeValue = content;
       
  7253             }
       
  7254     },
       
  7255 
       
  7256     CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
       
  7257         'for': 'htmlFor',
       
  7258         'class': 'className'
       
  7259     } : { // w3c
       
  7260         'htmlFor': 'for',
       
  7261         'className': 'class'
       
  7262     },
       
  7263 
       
  7264     /**
       
  7265      * Provides a normalized attribute interface. 
       
  7266      * @method setAttribute
       
  7267      * @param {HTMLElement} el The target element for the attribute.
       
  7268      * @param {String} attr The attribute to set.
       
  7269      * @param {String} val The value of the attribute.
       
  7270      */
       
  7271     setAttribute: function(el, attr, val, ieAttr) {
       
  7272         if (el && attr && el.setAttribute) {
       
  7273             attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
       
  7274             el.setAttribute(attr, val, ieAttr);
       
  7275         }
       
  7276         else { Y.log('bad input to setAttribute', 'warn', 'dom'); }
       
  7277     },
       
  7278 
       
  7279 
       
  7280     /**
       
  7281      * Provides a normalized attribute interface. 
       
  7282      * @method getAttribute
       
  7283      * @param {HTMLElement} el The target element for the attribute.
       
  7284      * @param {String} attr The attribute to get.
       
  7285      * @return {String} The current value of the attribute. 
       
  7286      */
       
  7287     getAttribute: function(el, attr, ieAttr) {
       
  7288         ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
       
  7289         var ret = '';
       
  7290         if (el && attr && el.getAttribute) {
       
  7291             attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
       
  7292             ret = el.getAttribute(attr, ieAttr);
       
  7293 
       
  7294             if (ret === null) {
       
  7295                 ret = ''; // per DOM spec
       
  7296             }
       
  7297         }
       
  7298         else { Y.log('bad input to getAttribute', 'warn', 'dom'); }
       
  7299         return ret;
       
  7300     },
       
  7301 
       
  7302     VALUE_SETTERS: {},
       
  7303 
       
  7304     VALUE_GETTERS: {},
       
  7305 
       
  7306     getValue: function(node) {
       
  7307         var ret = '', // TODO: return null?
       
  7308             getter;
       
  7309 
       
  7310         if (node && node[TAG_NAME]) {
       
  7311             getter = Y_DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
       
  7312 
       
  7313             if (getter) {
       
  7314                 ret = getter(node);
       
  7315             } else {
       
  7316                 ret = node.value;
       
  7317             }
       
  7318         }
       
  7319 
       
  7320         // workaround for IE8 JSON stringify bug
       
  7321         // which converts empty string values to null
       
  7322         if (ret === EMPTY_STRING) {
       
  7323             ret = EMPTY_STRING; // for real
       
  7324         }
       
  7325 
       
  7326         return (typeof ret === 'string') ? ret : '';
       
  7327     },
       
  7328 
       
  7329     setValue: function(node, val) {
       
  7330         var setter;
       
  7331 
       
  7332         if (node && node[TAG_NAME]) {
       
  7333             setter = Y_DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
       
  7334 
       
  7335             if (setter) {
       
  7336                 setter(node, val);
       
  7337             } else {
       
  7338                 node.value = val;
       
  7339             }
       
  7340         }
       
  7341     },
       
  7342 
       
  7343     creators: {}
       
  7344 });
       
  7345 
       
  7346 addFeature('value-set', 'select', {
       
  7347     test: function() {
       
  7348         var node = Y.config.doc.createElement('select');
       
  7349         node.innerHTML = '<option>1</option><option>2</option>';
       
  7350         node.value = '2';
       
  7351         return (node.value && node.value === '2');
       
  7352     }
       
  7353 });
       
  7354 
       
  7355 if (!testFeature('value-set', 'select')) {
       
  7356     Y_DOM.VALUE_SETTERS.select = function(node, val) {
       
  7357         for (var i = 0, options = node.getElementsByTagName('option'), option;
       
  7358                 option = options[i++];) {
       
  7359             if (Y_DOM.getValue(option) === val) {
       
  7360                 option.selected = true;
       
  7361                 //Y_DOM.setAttribute(option, 'selected', 'selected');
       
  7362                 break;
       
  7363             }
       
  7364         }
       
  7365     };
       
  7366 }
       
  7367 
       
  7368 Y.mix(Y_DOM.VALUE_GETTERS, {
       
  7369     button: function(node) {
       
  7370         return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
       
  7371     }
       
  7372 });
       
  7373 
       
  7374 Y.mix(Y_DOM.VALUE_SETTERS, {
       
  7375     // IE: node.value changes the button text, which should be handled via innerHTML
       
  7376     button: function(node, val) {
       
  7377         var attr = node.attributes.value;
       
  7378         if (!attr) {
       
  7379             attr = node[OWNER_DOCUMENT].createAttribute('value');
       
  7380             node.setAttributeNode(attr);
       
  7381         }
       
  7382 
       
  7383         attr.value = val;
       
  7384     }
       
  7385 });
       
  7386 
       
  7387 
       
  7388 Y.mix(Y_DOM.VALUE_GETTERS, {
       
  7389     option: function(node) {
       
  7390         var attrs = node.attributes;
       
  7391         return (attrs.value && attrs.value.specified) ? node.value : node.text;
       
  7392     },
       
  7393 
       
  7394     select: function(node) {
       
  7395         var val = node.value,
       
  7396             options = node.options;
       
  7397 
       
  7398         if (options && options.length) {
       
  7399             // TODO: implement multipe select
       
  7400             if (node.multiple) {
       
  7401                 Y.log('multiple select normalization not implemented', 'warn', 'DOM');
       
  7402             } else if (node.selectedIndex > -1) {
       
  7403                 val = Y_DOM.getValue(options[node.selectedIndex]);
       
  7404             }
       
  7405         }
       
  7406 
       
  7407         return val;
       
  7408     }
       
  7409 });
       
  7410 var addClass, hasClass, removeClass;
       
  7411 
       
  7412 Y.mix(Y.DOM, {
       
  7413     /**
       
  7414      * Determines whether a DOM element has the given className.
       
  7415      * @method hasClass
       
  7416      * @for DOM
       
  7417      * @param {HTMLElement} element The DOM element. 
       
  7418      * @param {String} className the class name to search for
       
  7419      * @return {Boolean} Whether or not the element has the given class. 
       
  7420      */
       
  7421     hasClass: function(node, className) {
       
  7422         var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
       
  7423         return re.test(node.className);
       
  7424     },
       
  7425 
       
  7426     /**
       
  7427      * Adds a class name to a given DOM element.
       
  7428      * @method addClass         
       
  7429      * @for DOM
       
  7430      * @param {HTMLElement} element The DOM element. 
       
  7431      * @param {String} className the class name to add to the class attribute
       
  7432      */
       
  7433     addClass: function(node, className) {
       
  7434         if (!Y.DOM.hasClass(node, className)) { // skip if already present 
       
  7435             node.className = Y.Lang.trim([node.className, className].join(' '));
       
  7436         }
       
  7437     },
       
  7438 
       
  7439     /**
       
  7440      * Removes a class name from a given element.
       
  7441      * @method removeClass         
       
  7442      * @for DOM
       
  7443      * @param {HTMLElement} element The DOM element. 
       
  7444      * @param {String} className the class name to remove from the class attribute
       
  7445      */
       
  7446     removeClass: function(node, className) {
       
  7447         if (className && hasClass(node, className)) {
       
  7448             node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
       
  7449                             className + '(?:\\s+|$)'), ' '));
       
  7450 
       
  7451             if ( hasClass(node, className) ) { // in case of multiple adjacent
       
  7452                 removeClass(node, className);
       
  7453             }
       
  7454         }                 
       
  7455     },
       
  7456 
       
  7457     /**
       
  7458      * Replace a class with another class for a given element.
       
  7459      * If no oldClassName is present, the newClassName is simply added.
       
  7460      * @method replaceClass  
       
  7461      * @for DOM
       
  7462      * @param {HTMLElement} element The DOM element 
       
  7463      * @param {String} oldClassName the class name to be replaced
       
  7464      * @param {String} newClassName the class name that will be replacing the old class name
       
  7465      */
       
  7466     replaceClass: function(node, oldC, newC) {
       
  7467         //Y.log('replaceClass replacing ' + oldC + ' with ' + newC, 'info', 'Node');
       
  7468         removeClass(node, oldC); // remove first in case oldC === newC
       
  7469         addClass(node, newC);
       
  7470     },
       
  7471 
       
  7472     /**
       
  7473      * If the className exists on the node it is removed, if it doesn't exist it is added.
       
  7474      * @method toggleClass  
       
  7475      * @for DOM
       
  7476      * @param {HTMLElement} element The DOM element
       
  7477      * @param {String} className the class name to be toggled
       
  7478      * @param {Boolean} addClass optional boolean to indicate whether class
       
  7479      * should be added or removed regardless of current state
       
  7480      */
       
  7481     toggleClass: function(node, className, force) {
       
  7482         var add = (force !== undefined) ? force :
       
  7483                 !(hasClass(node, className));
       
  7484 
       
  7485         if (add) {
       
  7486             addClass(node, className);
       
  7487         } else {
       
  7488             removeClass(node, className);
       
  7489         }
       
  7490     }
       
  7491 });
       
  7492 
       
  7493 hasClass = Y.DOM.hasClass;
       
  7494 removeClass = Y.DOM.removeClass;
       
  7495 addClass = Y.DOM.addClass;
       
  7496 
       
  7497 var re_tag = /<([a-z]+)/i,
       
  7498 
       
  7499     Y_DOM = Y.DOM,
       
  7500 
       
  7501     addFeature = Y.Features.add,
       
  7502     testFeature = Y.Features.test,
       
  7503 
       
  7504     creators = {},
       
  7505 
       
  7506     createFromDIV = function(html, tag) {
       
  7507         var div = Y.config.doc.createElement('div'),
       
  7508             ret = true;
       
  7509 
       
  7510         div.innerHTML = html;
       
  7511         if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
       
  7512             ret = false;
       
  7513         }
       
  7514 
       
  7515         return ret;
       
  7516     },
       
  7517 
       
  7518     re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,
       
  7519 
       
  7520     TABLE_OPEN = '<table>',
       
  7521     TABLE_CLOSE = '</table>';
       
  7522 
       
  7523 Y.mix(Y.DOM, {
       
  7524     _fragClones: {},
       
  7525 
       
  7526     _create: function(html, doc, tag) {
       
  7527         tag = tag || 'div';
       
  7528 
       
  7529         var frag = Y_DOM._fragClones[tag];
       
  7530         if (frag) {
       
  7531             frag = frag.cloneNode(false);
       
  7532         } else {
       
  7533             frag = Y_DOM._fragClones[tag] = doc.createElement(tag);
       
  7534         }
       
  7535         frag.innerHTML = html;
       
  7536         return frag;
       
  7537     },
       
  7538 
       
  7539     _children: function(node, tag) {
       
  7540             var i = 0,
       
  7541             children = node.children,
       
  7542             childNodes,
       
  7543             hasComments,
       
  7544             child;
       
  7545 
       
  7546         if (children && children.tags) { // use tags filter when possible
       
  7547             if (tag) {
       
  7548                 children = node.children.tags(tag);
       
  7549             } else { // IE leaks comments into children
       
  7550                 hasComments = children.tags('!').length;
       
  7551             }
       
  7552         }
       
  7553         
       
  7554         if (!children || (!children.tags && tag) || hasComments) {
       
  7555             childNodes = children || node.childNodes;
       
  7556             children = [];
       
  7557             while ((child = childNodes[i++])) {
       
  7558                 if (child.nodeType === 1) {
       
  7559                     if (!tag || tag === child.tagName) {
       
  7560                         children.push(child);
       
  7561                     }
       
  7562                 }
       
  7563             }
       
  7564         }
       
  7565 
       
  7566         return children || [];
       
  7567     },
       
  7568 
       
  7569     /**
       
  7570      * Creates a new dom node using the provided markup string. 
       
  7571      * @method create
       
  7572      * @param {String} html The markup used to create the element
       
  7573      * @param {HTMLDocument} doc An optional document context 
       
  7574      * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 
       
  7575      * when creating one node, and a documentFragment when creating
       
  7576      * multiple nodes.
       
  7577      */
       
  7578     create: function(html, doc) {
       
  7579         if (typeof html === 'string') {
       
  7580             html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML
       
  7581 
       
  7582         }
       
  7583 
       
  7584         doc = doc || Y.config.doc;
       
  7585         var m = re_tag.exec(html),
       
  7586             create = Y_DOM._create,
       
  7587             custom = creators,
       
  7588             ret = null,
       
  7589             creator,
       
  7590             tag, nodes;
       
  7591 
       
  7592         if (html != undefined) { // not undefined or null
       
  7593             if (m && m[1]) {
       
  7594                 creator = custom[m[1].toLowerCase()];
       
  7595                 if (typeof creator === 'function') {
       
  7596                     create = creator; 
       
  7597                 } else {
       
  7598                     tag = creator;
       
  7599                 }
       
  7600             }
       
  7601 
       
  7602             nodes = create(html, doc, tag).childNodes;
       
  7603 
       
  7604             if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment"
       
  7605                 ret = nodes[0].parentNode.removeChild(nodes[0]);
       
  7606             } else if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { // using dummy node to preserve some attributes (e.g. OPTION not selected)
       
  7607                 if (nodes.length === 2) {
       
  7608                     ret = nodes[0].nextSibling;
       
  7609                 } else {
       
  7610                     nodes[0].parentNode.removeChild(nodes[0]); 
       
  7611                     ret = Y_DOM._nl2frag(nodes, doc);
       
  7612                 }
       
  7613             } else { // return multiple nodes as a fragment
       
  7614                  ret = Y_DOM._nl2frag(nodes, doc);
       
  7615             }
       
  7616 
       
  7617         }
       
  7618 
       
  7619         return ret;
       
  7620     },
       
  7621 
       
  7622     _nl2frag: function(nodes, doc) {
       
  7623         var ret = null,
       
  7624             i, len;
       
  7625 
       
  7626         if (nodes && (nodes.push || nodes.item) && nodes[0]) {
       
  7627             doc = doc || nodes[0].ownerDocument; 
       
  7628             ret = doc.createDocumentFragment();
       
  7629 
       
  7630             if (nodes.item) { // convert live list to static array
       
  7631                 nodes = Y.Array(nodes, 0, true);
       
  7632             }
       
  7633 
       
  7634             for (i = 0, len = nodes.length; i < len; i++) {
       
  7635                 ret.appendChild(nodes[i]); 
       
  7636             }
       
  7637         } // else inline with log for minification
       
  7638         return ret;
       
  7639     },
       
  7640 
       
  7641     /**
       
  7642      * Inserts content in a node at the given location 
       
  7643      * @method addHTML
       
  7644      * @param {HTMLElement} node The node to insert into
       
  7645      * @param {HTMLElement | Array | HTMLCollection} content The content to be inserted 
       
  7646      * @param {HTMLElement} where Where to insert the content
       
  7647      * If no "where" is given, content is appended to the node
       
  7648      * Possible values for "where"
       
  7649      * <dl>
       
  7650      * <dt>HTMLElement</dt>
       
  7651      * <dd>The element to insert before</dd>
       
  7652      * <dt>"replace"</dt>
       
  7653      * <dd>Replaces the existing HTML</dd>
       
  7654      * <dt>"before"</dt>
       
  7655      * <dd>Inserts before the existing HTML</dd>
       
  7656      * <dt>"before"</dt>
       
  7657      * <dd>Inserts content before the node</dd>
       
  7658      * <dt>"after"</dt>
       
  7659      * <dd>Inserts content after the node</dd>
       
  7660      * </dl>
       
  7661      */
       
  7662     addHTML: function(node, content, where) {
       
  7663         var nodeParent = node.parentNode,
       
  7664             i = 0,
       
  7665             item,
       
  7666             ret = content,
       
  7667             newNode;
       
  7668             
       
  7669 
       
  7670         if (content != undefined) { // not null or undefined (maybe 0)
       
  7671             if (content.nodeType) { // DOM node, just add it
       
  7672                 newNode = content;
       
  7673             } else if (typeof content == 'string' || typeof content == 'number') {
       
  7674                 ret = newNode = Y_DOM.create(content);
       
  7675             } else if (content[0] && content[0].nodeType) { // array or collection 
       
  7676                 newNode = Y.config.doc.createDocumentFragment();
       
  7677                 while ((item = content[i++])) {
       
  7678                     newNode.appendChild(item); // append to fragment for insertion
       
  7679                 }
       
  7680             }
       
  7681         }
       
  7682 
       
  7683         if (where) {
       
  7684             if (newNode && where.parentNode) { // insert regardless of relationship to node
       
  7685                 where.parentNode.insertBefore(newNode, where);
       
  7686             } else {
       
  7687                 switch (where) {
       
  7688                     case 'replace':
       
  7689                         while (node.firstChild) {
       
  7690                             node.removeChild(node.firstChild);
       
  7691                         }
       
  7692                         if (newNode) { // allow empty content to clear node
       
  7693                             node.appendChild(newNode);
       
  7694                         }
       
  7695                         break;
       
  7696                     case 'before':
       
  7697                         if (newNode) {
       
  7698                             nodeParent.insertBefore(newNode, node);
       
  7699                         }
       
  7700                         break;
       
  7701                     case 'after':
       
  7702                         if (newNode) {
       
  7703                             if (node.nextSibling) { // IE errors if refNode is null
       
  7704                                 nodeParent.insertBefore(newNode, node.nextSibling);
       
  7705                             } else {
       
  7706                                 nodeParent.appendChild(newNode);
       
  7707                             }
       
  7708                         }
       
  7709                         break;
       
  7710                     default:
       
  7711                         if (newNode) {
       
  7712                             node.appendChild(newNode);
       
  7713                         }
       
  7714                 }
       
  7715             }
       
  7716         } else if (newNode) {
       
  7717             node.appendChild(newNode);
       
  7718         }
       
  7719 
       
  7720         return ret;
       
  7721     },
       
  7722 
       
  7723     wrap: function(node, html) {
       
  7724         var parent = (html && html.nodeType) ? html : Y.DOM.create(html),
       
  7725             nodes = parent.getElementsByTagName('*');
       
  7726 
       
  7727         if (nodes.length) {
       
  7728             parent = nodes[nodes.length - 1];
       
  7729         }
       
  7730 
       
  7731         if (node.parentNode) { 
       
  7732             node.parentNode.replaceChild(parent, node);
       
  7733         }
       
  7734         parent.appendChild(node);
       
  7735     },
       
  7736 
       
  7737     unwrap: function(node) {
       
  7738         var parent = node.parentNode,
       
  7739             lastChild = parent.lastChild,
       
  7740             next = node,
       
  7741             grandparent;
       
  7742 
       
  7743         if (parent) {
       
  7744             grandparent = parent.parentNode;
       
  7745             if (grandparent) {
       
  7746                 node = parent.firstChild;
       
  7747                 while (node !== lastChild) {
       
  7748                     next = node.nextSibling;
       
  7749                     grandparent.insertBefore(node, parent);
       
  7750                     node = next;
       
  7751                 }
       
  7752                 grandparent.replaceChild(lastChild, parent);
       
  7753             } else {
       
  7754                 parent.removeChild(node);
       
  7755             }
       
  7756         }
       
  7757     }
       
  7758 });
       
  7759 
       
  7760 addFeature('innerhtml', 'table', {
       
  7761     test: function() {
       
  7762         var node = Y.config.doc.createElement('table');
       
  7763         try {
       
  7764             node.innerHTML = '<tbody></tbody>';
       
  7765         } catch(e) {
       
  7766             return false;
       
  7767         }
       
  7768         return (node.firstChild && node.firstChild.nodeName === 'TBODY');
       
  7769     }
       
  7770 });
       
  7771 
       
  7772 addFeature('innerhtml-div', 'tr', {
       
  7773     test: function() {
       
  7774         return createFromDIV('<tr></tr>', 'tr');
       
  7775     }
       
  7776 });
       
  7777 
       
  7778 addFeature('innerhtml-div', 'script', {
       
  7779     test: function() {
       
  7780         return createFromDIV('<script></script>', 'script');
       
  7781     }
       
  7782 });
       
  7783 
       
  7784 if (!testFeature('innerhtml', 'table')) {
       
  7785     // TODO: thead/tfoot with nested tbody
       
  7786         // IE adds TBODY when creating TABLE elements (which may share this impl)
       
  7787     creators.tbody = function(html, doc) {
       
  7788         var frag = Y_DOM.create(TABLE_OPEN + html + TABLE_CLOSE, doc),
       
  7789             tb = Y.DOM._children(frag, 'tbody')[0];
       
  7790 
       
  7791         if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
       
  7792             tb.parentNode.removeChild(tb); // strip extraneous tbody
       
  7793         }
       
  7794         return frag;
       
  7795     };
       
  7796 }
       
  7797 
       
  7798 if (!testFeature('innerhtml-div', 'script')) {
       
  7799     creators.script = function(html, doc) {
       
  7800         var frag = doc.createElement('div');
       
  7801 
       
  7802         frag.innerHTML = '-' + html;
       
  7803         frag.removeChild(frag.firstChild);
       
  7804         return frag;
       
  7805     };
       
  7806 
       
  7807     creators.link = creators.style = creators.script;
       
  7808 }
       
  7809 
       
  7810 if (!testFeature('innerhtml-div', 'tr')) {
       
  7811     Y.mix(creators, {
       
  7812         option: function(html, doc) {
       
  7813             return Y_DOM.create('<select><option class="yui3-big-dummy" selected></option>' + html + '</select>', doc);
       
  7814         },
       
  7815 
       
  7816         tr: function(html, doc) {
       
  7817             return Y_DOM.create('<tbody>' + html + '</tbody>', doc);
       
  7818         },
       
  7819 
       
  7820         td: function(html, doc) {
       
  7821             return Y_DOM.create('<tr>' + html + '</tr>', doc);
       
  7822         }, 
       
  7823 
       
  7824         col: function(html, doc) {
       
  7825             return Y_DOM.create('<colgroup>' + html + '</colgroup>', doc);
       
  7826         }, 
       
  7827 
       
  7828         tbody: 'table'
       
  7829     });
       
  7830 
       
  7831     Y.mix(creators, {
       
  7832         legend: 'fieldset',
       
  7833         th: creators.td,
       
  7834         thead: creators.tbody,
       
  7835         tfoot: creators.tbody,
       
  7836         caption: creators.tbody,
       
  7837         colgroup: creators.tbody,
       
  7838         optgroup: creators.option
       
  7839     });
       
  7840 }
       
  7841 
       
  7842 Y_DOM.creators = creators;
       
  7843 Y.mix(Y.DOM, {
       
  7844     /**
       
  7845      * Sets the width of the element to the given size, regardless
       
  7846      * of box model, border, padding, etc.
       
  7847      * @method setWidth
       
  7848      * @param {HTMLElement} element The DOM element. 
       
  7849      * @param {String|Number} size The pixel height to size to
       
  7850      */
       
  7851 
       
  7852     setWidth: function(node, size) {
       
  7853         Y.DOM._setSize(node, 'width', size);
       
  7854     },
       
  7855 
       
  7856     /**
       
  7857      * Sets the height of the element to the given size, regardless
       
  7858      * of box model, border, padding, etc.
       
  7859      * @method setHeight
       
  7860      * @param {HTMLElement} element The DOM element. 
       
  7861      * @param {String|Number} size The pixel height to size to
       
  7862      */
       
  7863 
       
  7864     setHeight: function(node, size) {
       
  7865         Y.DOM._setSize(node, 'height', size);
       
  7866     },
       
  7867 
       
  7868     _setSize: function(node, prop, val) {
       
  7869         val = (val > 0) ? val : 0;
       
  7870         var size = 0;
       
  7871 
       
  7872         node.style[prop] = val + 'px';
       
  7873         size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
       
  7874 
       
  7875         if (size > val) {
       
  7876             val = val - (size - val);
       
  7877 
       
  7878             if (val < 0) {
       
  7879                 val = 0;
       
  7880             }
       
  7881 
       
  7882             node.style[prop] = val + 'px';
       
  7883         }
       
  7884     }
       
  7885 });
       
  7886 
       
  7887 
       
  7888 }, '@VERSION@', {"requires": ["dom-core"]});
       
  7889 YUI.add('color-base', function (Y, NAME) {
       
  7890 
       
  7891 /**
       
  7892 Color provides static methods for color conversion.
       
  7893 
       
  7894     Y.Color.toRGB('f00'); // rgb(255, 0, 0)
       
  7895 
       
  7896     Y.Color.toHex('rgb(255, 255, 0)'); // #ffff00
       
  7897 
       
  7898 @module color
       
  7899 @submodule color-base
       
  7900 @class Color
       
  7901 @since 3.8.0
       
  7902 **/
       
  7903 
       
  7904 var REGEX_HEX = /^#?([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})(\ufffe)?/,
       
  7905     REGEX_HEX3 = /^#?([\da-fA-F]{1})([\da-fA-F]{1})([\da-fA-F]{1})(\ufffe)?/,
       
  7906     REGEX_RGB = /rgba?\(([\d]{1,3}), ?([\d]{1,3}), ?([\d]{1,3}),? ?([.\d]*)?\)/,
       
  7907     TYPES = { 'HEX': 'hex', 'RGB': 'rgb', 'RGBA': 'rgba' },
       
  7908     CONVERTS = { 'hex': 'toHex', 'rgb': 'toRGB', 'rgba': 'toRGBA' };
       
  7909 
       
  7910 
       
  7911 Y.Color = {
       
  7912     /**
       
  7913     @static
       
  7914     @property KEYWORDS
       
  7915     @type Object
       
  7916     @since 3.8.0
       
  7917     **/
       
  7918     KEYWORDS: {
       
  7919         'black': '000', 'silver': 'c0c0c0', 'gray': '808080', 'white': 'fff',
       
  7920         'maroon': '800000', 'red': 'f00', 'purple': '800080', 'fuchsia': 'f0f',
       
  7921         'green': '008000', 'lime': '0f0', 'olive': '808000', 'yellow': 'ff0',
       
  7922         'navy': '000080', 'blue': '00f', 'teal': '008080', 'aqua': '0ff'
       
  7923     },
       
  7924 
       
  7925     /**
       
  7926         NOTE: `(\ufffe)?` is added to the Regular Expression to carve out a
       
  7927         place for the alpha channel that is returned from toArray
       
  7928         without compromising any usage of the Regular Expression
       
  7929 
       
  7930     @static
       
  7931     @property REGEX_HEX
       
  7932     @type RegExp
       
  7933     @default /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})(\ufffe)?/
       
  7934     @since 3.8.0
       
  7935     **/
       
  7936     REGEX_HEX: REGEX_HEX,
       
  7937 
       
  7938     /**
       
  7939         NOTE: `(\ufffe)?` is added to the Regular Expression to carve out a
       
  7940         place for the alpha channel that is returned from toArray
       
  7941         without compromising any usage of the Regular Expression
       
  7942 
       
  7943     @static
       
  7944     @property REGEX_HEX3
       
  7945     @type RegExp
       
  7946     @default /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})(\ufffe)?/
       
  7947     @since 3.8.0
       
  7948     **/
       
  7949     REGEX_HEX3: REGEX_HEX3,
       
  7950 
       
  7951     /**
       
  7952     @static
       
  7953     @property REGEX_RGB
       
  7954     @type RegExp
       
  7955     @default /rgba?\(([0-9]{1,3}), ?([0-9]{1,3}), ?([0-9]{1,3}),? ?([.0-9]{1,3})?\)/
       
  7956     @since 3.8.0
       
  7957     **/
       
  7958     REGEX_RGB: REGEX_RGB,
       
  7959 
       
  7960     re_RGB: REGEX_RGB,
       
  7961 
       
  7962     re_hex: REGEX_HEX,
       
  7963 
       
  7964     re_hex3: REGEX_HEX3,
       
  7965 
       
  7966     /**
       
  7967     @static
       
  7968     @property STR_HEX
       
  7969     @type String
       
  7970     @default #{*}{*}{*}
       
  7971     @since 3.8.0
       
  7972     **/
       
  7973     STR_HEX: '#{*}{*}{*}',
       
  7974 
       
  7975     /**
       
  7976     @static
       
  7977     @property STR_RGB
       
  7978     @type String
       
  7979     @default rgb({*}, {*}, {*})
       
  7980     @since 3.8.0
       
  7981     **/
       
  7982     STR_RGB: 'rgb({*}, {*}, {*})',
       
  7983 
       
  7984     /**
       
  7985     @static
       
  7986     @property STR_RGBA
       
  7987     @type String
       
  7988     @default rgba({*}, {*}, {*}, {*})
       
  7989     @since 3.8.0
       
  7990     **/
       
  7991     STR_RGBA: 'rgba({*}, {*}, {*}, {*})',
       
  7992 
       
  7993     /**
       
  7994     @static
       
  7995     @property TYPES
       
  7996     @type Object
       
  7997     @default {'rgb':'rgb', 'rgba':'rgba'}
       
  7998     @since 3.8.0
       
  7999     **/
       
  8000     TYPES: TYPES,
       
  8001 
       
  8002     /**
       
  8003     @static
       
  8004     @property CONVERTS
       
  8005     @type Object
       
  8006     @default {}
       
  8007     @since 3.8.0
       
  8008     **/
       
  8009     CONVERTS: CONVERTS,
       
  8010 
       
  8011     /**
       
  8012      Converts the provided string to the provided type.
       
  8013      You can use the `Y.Color.TYPES` to get a valid `to` type.
       
  8014      If the color cannot be converted, the original color will be returned.
       
  8015 
       
  8016      @public
       
  8017      @method convert
       
  8018      @param {String} str
       
  8019      @param {String} to
       
  8020      @return {String}
       
  8021      @since 3.8.0
       
  8022      **/
       
  8023     convert: function (str, to) {
       
  8024         var convert = Y.Color.CONVERTS[to.toLowerCase()],
       
  8025             clr = str;
       
  8026 
       
  8027         if (convert && Y.Color[convert]) {
       
  8028             clr = Y.Color[convert](str);
       
  8029         }
       
  8030 
       
  8031         return clr;
       
  8032     },
       
  8033 
       
  8034     /**
       
  8035     Converts provided color value to a hex value string
       
  8036 
       
  8037     @public
       
  8038     @method toHex
       
  8039     @param {String} str Hex or RGB value string
       
  8040     @return {String} returns array of values or CSS string if options.css is true
       
  8041     @since 3.8.0
       
  8042     **/
       
  8043     toHex: function (str) {
       
  8044         var clr = Y.Color._convertTo(str, 'hex'),
       
  8045             isTransparent = clr.toLowerCase() === 'transparent';
       
  8046 
       
  8047         if (clr.charAt(0) !== '#' && !isTransparent) {
       
  8048             clr = '#' + clr;
       
  8049         }
       
  8050 
       
  8051         return isTransparent ? clr.toLowerCase() : clr.toUpperCase();
       
  8052     },
       
  8053 
       
  8054     /**
       
  8055     Converts provided color value to an RGB value string
       
  8056     @public
       
  8057     @method toRGB
       
  8058     @param {String} str Hex or RGB value string
       
  8059     @return {String}
       
  8060     @since 3.8.0
       
  8061     **/
       
  8062     toRGB: function (str) {
       
  8063         var clr = Y.Color._convertTo(str, 'rgb');
       
  8064         return clr.toLowerCase();
       
  8065     },
       
  8066 
       
  8067     /**
       
  8068     Converts provided color value to an RGB value string
       
  8069     @public
       
  8070     @method toRGBA
       
  8071     @param {String} str Hex or RGB value string
       
  8072     @return {String}
       
  8073     @since 3.8.0
       
  8074     **/
       
  8075     toRGBA: function (str) {
       
  8076         var clr = Y.Color._convertTo(str, 'rgba' );
       
  8077         return clr.toLowerCase();
       
  8078     },
       
  8079 
       
  8080     /**
       
  8081     Converts the provided color string to an array of values where the
       
  8082         last value is the alpha value. Will return an empty array if
       
  8083         the provided string is not able to be parsed.
       
  8084 
       
  8085         NOTE: `(\ufffe)?` is added to `HEX` and `HEX3` Regular Expressions to
       
  8086         carve out a place for the alpha channel that is returned from
       
  8087         toArray without compromising any usage of the Regular Expression
       
  8088 
       
  8089         Y.Color.toArray('fff');              // ['ff', 'ff', 'ff', 1]
       
  8090         Y.Color.toArray('rgb(0, 0, 0)');     // ['0', '0', '0', 1]
       
  8091         Y.Color.toArray('rgba(0, 0, 0, 0)'); // ['0', '0', '0', 1]
       
  8092 
       
  8093 
       
  8094 
       
  8095     @public
       
  8096     @method toArray
       
  8097     @param {String} str
       
  8098     @return {Array}
       
  8099     @since 3.8.0
       
  8100     **/
       
  8101     toArray: function(str) {
       
  8102         // parse with regex and return "matches" array
       
  8103         var type = Y.Color.findType(str).toUpperCase(),
       
  8104             regex,
       
  8105             arr,
       
  8106             length,
       
  8107             lastItem;
       
  8108 
       
  8109         if (type === 'HEX' && str.length < 5) {
       
  8110             type = 'HEX3';
       
  8111         }
       
  8112 
       
  8113         if (type.charAt(type.length - 1) === 'A') {
       
  8114             type = type.slice(0, -1);
       
  8115         }
       
  8116 
       
  8117         regex = Y.Color['REGEX_' + type];
       
  8118 
       
  8119         if (regex) {
       
  8120             arr = regex.exec(str) || [];
       
  8121             length = arr.length;
       
  8122 
       
  8123             if (length) {
       
  8124 
       
  8125                 arr.shift();
       
  8126                 length--;
       
  8127 
       
  8128                 if (type === 'HEX3') {
       
  8129                     arr[0] += arr[0];
       
  8130                     arr[1] += arr[1];
       
  8131                     arr[2] += arr[2];
       
  8132                 }
       
  8133 
       
  8134                 lastItem = arr[length - 1];
       
  8135                 if (!lastItem) {
       
  8136                     arr[length - 1] = 1;
       
  8137                 }
       
  8138             }
       
  8139         }
       
  8140 
       
  8141         return arr;
       
  8142 
       
  8143     },
       
  8144 
       
  8145     /**
       
  8146     Converts the array of values to a string based on the provided template.
       
  8147     @public
       
  8148     @method fromArray
       
  8149     @param {Array} arr
       
  8150     @param {String} template
       
  8151     @return {String}
       
  8152     @since 3.8.0
       
  8153     **/
       
  8154     fromArray: function(arr, template) {
       
  8155         arr = arr.concat();
       
  8156 
       
  8157         if (typeof template === 'undefined') {
       
  8158             return arr.join(', ');
       
  8159         }
       
  8160 
       
  8161         var replace = '{*}';
       
  8162 
       
  8163         template = Y.Color['STR_' + template.toUpperCase()];
       
  8164 
       
  8165         if (arr.length === 3 && template.match(/\{\*\}/g).length === 4) {
       
  8166             arr.push(1);
       
  8167         }
       
  8168 
       
  8169         while ( template.indexOf(replace) >= 0 && arr.length > 0) {
       
  8170             template = template.replace(replace, arr.shift());
       
  8171         }
       
  8172 
       
  8173         return template;
       
  8174     },
       
  8175 
       
  8176     /**
       
  8177     Finds the value type based on the str value provided.
       
  8178     @public
       
  8179     @method findType
       
  8180     @param {String} str
       
  8181     @return {String}
       
  8182     @since 3.8.0
       
  8183     **/
       
  8184     findType: function (str) {
       
  8185         if (Y.Color.KEYWORDS[str]) {
       
  8186             return 'keyword';
       
  8187         }
       
  8188 
       
  8189         var index = str.indexOf('('),
       
  8190             key;
       
  8191 
       
  8192         if (index > 0) {
       
  8193             key = str.substr(0, index);
       
  8194         }
       
  8195 
       
  8196         if (key && Y.Color.TYPES[key.toUpperCase()]) {
       
  8197             return Y.Color.TYPES[key.toUpperCase()];
       
  8198         }
       
  8199 
       
  8200         return 'hex';
       
  8201 
       
  8202     }, // return 'keyword', 'hex', 'rgb'
       
  8203 
       
  8204     /**
       
  8205     Retrives the alpha channel from the provided string. If no alpha
       
  8206         channel is present, `1` will be returned.
       
  8207     @protected
       
  8208     @method _getAlpha
       
  8209     @param {String} clr
       
  8210     @return {Number}
       
  8211     @since 3.8.0
       
  8212     **/
       
  8213     _getAlpha: function (clr) {
       
  8214         var alpha,
       
  8215             arr = Y.Color.toArray(clr);
       
  8216 
       
  8217         if (arr.length > 3) {
       
  8218             alpha = arr.pop();
       
  8219         }
       
  8220 
       
  8221         return +alpha || 1;
       
  8222     },
       
  8223 
       
  8224     /**
       
  8225     Returns the hex value string if found in the KEYWORDS object
       
  8226     @protected
       
  8227     @method _keywordToHex
       
  8228     @param {String} clr
       
  8229     @return {String}
       
  8230     @since 3.8.0
       
  8231     **/
       
  8232     _keywordToHex: function (clr) {
       
  8233         var keyword = Y.Color.KEYWORDS[clr];
       
  8234 
       
  8235         if (keyword) {
       
  8236             return keyword;
       
  8237         }
       
  8238     },
       
  8239 
       
  8240     /**
       
  8241     Converts the provided color string to the value type provided as `to`
       
  8242     @protected
       
  8243     @method _convertTo
       
  8244     @param {String} clr
       
  8245     @param {String} to
       
  8246     @return {String}
       
  8247     @since 3.8.0
       
  8248     **/
       
  8249     _convertTo: function(clr, to) {
       
  8250 
       
  8251         if (clr === 'transparent') {
       
  8252             return clr;
       
  8253         }
       
  8254 
       
  8255         var from = Y.Color.findType(clr),
       
  8256             originalTo = to,
       
  8257             needsAlpha,
       
  8258             alpha,
       
  8259             method,
       
  8260             ucTo;
       
  8261 
       
  8262         if (from === 'keyword') {
       
  8263             clr = Y.Color._keywordToHex(clr);
       
  8264             from = 'hex';
       
  8265         }
       
  8266 
       
  8267         if (from === 'hex' && clr.length < 5) {
       
  8268             if (clr.charAt(0) === '#') {
       
  8269                 clr = clr.substr(1);
       
  8270             }
       
  8271 
       
  8272             clr = '#' + clr.charAt(0) + clr.charAt(0) +
       
  8273                         clr.charAt(1) + clr.charAt(1) +
       
  8274                         clr.charAt(2) + clr.charAt(2);
       
  8275         }
       
  8276 
       
  8277         if (from === to) {
       
  8278             return clr;
       
  8279         }
       
  8280 
       
  8281         if (from.charAt(from.length - 1) === 'a') {
       
  8282             from = from.slice(0, -1);
       
  8283         }
       
  8284 
       
  8285         needsAlpha = (to.charAt(to.length - 1) === 'a');
       
  8286         if (needsAlpha) {
       
  8287             to = to.slice(0, -1);
       
  8288             alpha = Y.Color._getAlpha(clr);
       
  8289         }
       
  8290 
       
  8291         ucTo = to.charAt(0).toUpperCase() + to.substr(1).toLowerCase();
       
  8292         method = Y.Color['_' + from + 'To' + ucTo ];
       
  8293 
       
  8294         // check to see if need conversion to rgb first
       
  8295         // check to see if there is a direct conversion method
       
  8296         // convertions are: hex <-> rgb <-> hsl
       
  8297         if (!method) {
       
  8298             if (from !== 'rgb' && to !== 'rgb') {
       
  8299                 clr = Y.Color['_' + from + 'ToRgb'](clr);
       
  8300                 from = 'rgb';
       
  8301                 method = Y.Color['_' + from + 'To' + ucTo ];
       
  8302             }
       
  8303         }
       
  8304 
       
  8305         if (method) {
       
  8306             clr = ((method)(clr, needsAlpha));
       
  8307         }
       
  8308 
       
  8309         // process clr from arrays to strings after conversions if alpha is needed
       
  8310         if (needsAlpha) {
       
  8311             if (!Y.Lang.isArray(clr)) {
       
  8312                 clr = Y.Color.toArray(clr);
       
  8313             }
       
  8314             clr.push(alpha);
       
  8315             clr = Y.Color.fromArray(clr, originalTo.toUpperCase());
       
  8316         }
       
  8317 
       
  8318         return clr;
       
  8319     },
       
  8320 
       
  8321     /**
       
  8322     Processes the hex string into r, g, b values. Will return values as
       
  8323         an array, or as an rgb string.
       
  8324     @protected
       
  8325     @method _hexToRgb
       
  8326     @param {String} str
       
  8327     @param {Boolean} [toArray]
       
  8328     @return {String|Array}
       
  8329     @since 3.8.0
       
  8330     **/
       
  8331     _hexToRgb: function (str, toArray) {
       
  8332         var r, g, b;
       
  8333 
       
  8334         /*jshint bitwise:false*/
       
  8335         if (str.charAt(0) === '#') {
       
  8336             str = str.substr(1);
       
  8337         }
       
  8338 
       
  8339         str = parseInt(str, 16);
       
  8340 
       
  8341         r = str >> 16;
       
  8342         g = str >> 8 & 0xFF;
       
  8343         b = str & 0xFF;
       
  8344 
       
  8345         if (toArray) {
       
  8346             return [r, g, b];
       
  8347         }
       
  8348 
       
  8349         return 'rgb(' + r + ', ' + g + ', ' + b + ')';
       
  8350     },
       
  8351 
       
  8352     /**
       
  8353     Processes the rgb string into r, g, b values. Will return values as
       
  8354         an array, or as a hex string.
       
  8355     @protected
       
  8356     @method _rgbToHex
       
  8357     @param {String} str
       
  8358     @param {Boolean} [toArray]
       
  8359     @return {String|Array}
       
  8360     @since 3.8.0
       
  8361     **/
       
  8362     _rgbToHex: function (str) {
       
  8363         /*jshint bitwise:false*/
       
  8364         var rgb = Y.Color.toArray(str),
       
  8365             hex = rgb[2] | (rgb[1] << 8) | (rgb[0] << 16);
       
  8366 
       
  8367         hex = (+hex).toString(16);
       
  8368 
       
  8369         while (hex.length < 6) {
       
  8370             hex = '0' + hex;
       
  8371         }
       
  8372 
       
  8373         return '#' + hex;
       
  8374     }
       
  8375 
       
  8376 };
       
  8377 
       
  8378 
       
  8379 
       
  8380 }, '@VERSION@', {"requires": ["yui-base"]});
       
  8381 YUI.add('dom-style', function (Y, NAME) {
       
  8382 
       
  8383 (function(Y) {
       
  8384 /** 
       
  8385  * Add style management functionality to DOM.
       
  8386  * @module dom
       
  8387  * @submodule dom-style
       
  8388  * @for DOM
       
  8389  */
       
  8390 
       
  8391 var DOCUMENT_ELEMENT = 'documentElement',
       
  8392     DEFAULT_VIEW = 'defaultView',
       
  8393     OWNER_DOCUMENT = 'ownerDocument',
       
  8394     STYLE = 'style',
       
  8395     FLOAT = 'float',
       
  8396     CSS_FLOAT = 'cssFloat',
       
  8397     STYLE_FLOAT = 'styleFloat',
       
  8398     TRANSPARENT = 'transparent',
       
  8399     GET_COMPUTED_STYLE = 'getComputedStyle',
       
  8400     GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
       
  8401 
       
  8402     WINDOW = Y.config.win,
       
  8403     DOCUMENT = Y.config.doc,
       
  8404     UNDEFINED = undefined,
       
  8405 
       
  8406     Y_DOM = Y.DOM,
       
  8407 
       
  8408     TRANSFORM = 'transform',
       
  8409     TRANSFORMORIGIN = 'transformOrigin',
       
  8410     VENDOR_TRANSFORM = [
       
  8411         'WebkitTransform',
       
  8412         'MozTransform',
       
  8413         'OTransform',
       
  8414         'msTransform'
       
  8415     ],
       
  8416 
       
  8417     re_color = /color$/i,
       
  8418     re_unit = /width|height|top|left|right|bottom|margin|padding/i;
       
  8419 
       
  8420 Y.Array.each(VENDOR_TRANSFORM, function(val) {
       
  8421     if (val in DOCUMENT[DOCUMENT_ELEMENT].style) {
       
  8422         TRANSFORM = val;
       
  8423         TRANSFORMORIGIN = val + "Origin";
       
  8424     }
       
  8425 });
       
  8426 
       
  8427 Y.mix(Y_DOM, {
       
  8428     DEFAULT_UNIT: 'px',
       
  8429 
       
  8430     CUSTOM_STYLES: {
       
  8431     },
       
  8432 
       
  8433 
       
  8434     /**
       
  8435      * Sets a style property for a given element.
       
  8436      * @method setStyle
       
  8437      * @param {HTMLElement} An HTMLElement to apply the style to.
       
  8438      * @param {String} att The style property to set. 
       
  8439      * @param {String|Number} val The value. 
       
  8440      */
       
  8441     setStyle: function(node, att, val, style) {
       
  8442         style = style || node.style;
       
  8443         var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES;
       
  8444 
       
  8445         if (style) {
       
  8446             if (val === null || val === '') { // normalize unsetting
       
  8447                 val = '';
       
  8448             } else if (!isNaN(new Number(val)) && re_unit.test(att)) { // number values may need a unit
       
  8449                 val += Y_DOM.DEFAULT_UNIT;
       
  8450             }
       
  8451 
       
  8452             if (att in CUSTOM_STYLES) {
       
  8453                 if (CUSTOM_STYLES[att].set) {
       
  8454                     CUSTOM_STYLES[att].set(node, val, style);
       
  8455                     return; // NOTE: return
       
  8456                 } else if (typeof CUSTOM_STYLES[att] === 'string') {
       
  8457                     att = CUSTOM_STYLES[att];
       
  8458                 }
       
  8459             } else if (att === '') { // unset inline styles
       
  8460                 att = 'cssText';
       
  8461                 val = '';
       
  8462             }
       
  8463             style[att] = val; 
       
  8464         }
       
  8465     },
       
  8466 
       
  8467     /**
       
  8468      * Returns the current style value for the given property.
       
  8469      * @method getStyle
       
  8470      * @param {HTMLElement} An HTMLElement to get the style from.
       
  8471      * @param {String} att The style property to get. 
       
  8472      */
       
  8473     getStyle: function(node, att, style) {
       
  8474         style = style || node.style;
       
  8475         var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES,
       
  8476             val = '';
       
  8477 
       
  8478         if (style) {
       
  8479             if (att in CUSTOM_STYLES) {
       
  8480                 if (CUSTOM_STYLES[att].get) {
       
  8481                     return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
       
  8482                 } else if (typeof CUSTOM_STYLES[att] === 'string') {
       
  8483                     att = CUSTOM_STYLES[att];
       
  8484                 }
       
  8485             }
       
  8486             val = style[att];
       
  8487             if (val === '') { // TODO: is empty string sufficient?
       
  8488                 val = Y_DOM[GET_COMPUTED_STYLE](node, att);
       
  8489             }
       
  8490         }
       
  8491 
       
  8492         return val;
       
  8493     },
       
  8494 
       
  8495     /**
       
  8496      * Sets multiple style properties.
       
  8497      * @method setStyles
       
  8498      * @param {HTMLElement} node An HTMLElement to apply the styles to. 
       
  8499      * @param {Object} hash An object literal of property:value pairs. 
       
  8500      */
       
  8501     setStyles: function(node, hash) {
       
  8502         var style = node.style;
       
  8503         Y.each(hash, function(v, n) {
       
  8504             Y_DOM.setStyle(node, n, v, style);
       
  8505         }, Y_DOM);
       
  8506     },
       
  8507 
       
  8508     /**
       
  8509      * Returns the computed style for the given node.
       
  8510      * @method getComputedStyle
       
  8511      * @param {HTMLElement} An HTMLElement to get the style from.
       
  8512      * @param {String} att The style property to get. 
       
  8513      * @return {String} The computed value of the style property. 
       
  8514      */
       
  8515     getComputedStyle: function(node, att) {
       
  8516         var val = '',
       
  8517             doc = node[OWNER_DOCUMENT],
       
  8518             computed;
       
  8519 
       
  8520         if (node[STYLE] && doc[DEFAULT_VIEW] && doc[DEFAULT_VIEW][GET_COMPUTED_STYLE]) {
       
  8521             computed = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, null);
       
  8522             if (computed) { // FF may be null in some cases (ticket #2530548)
       
  8523                 val = computed[att];
       
  8524             }
       
  8525         }
       
  8526         return val;
       
  8527     }
       
  8528 });
       
  8529 
       
  8530 // normalize reserved word float alternatives ("cssFloat" or "styleFloat")
       
  8531 if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
       
  8532     Y_DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
       
  8533 } else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
       
  8534     Y_DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
       
  8535 }
       
  8536 
       
  8537 // fix opera computedStyle default color unit (convert to rgb)
       
  8538 if (Y.UA.opera) {
       
  8539     Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
       
  8540         var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
       
  8541             val = view[GET_COMPUTED_STYLE](node, '')[att];
       
  8542 
       
  8543         if (re_color.test(att)) {
       
  8544             val = Y.Color.toRGB(val);
       
  8545         }
       
  8546 
       
  8547         return val;
       
  8548     };
       
  8549 
       
  8550 }
       
  8551 
       
  8552 // safari converts transparent to rgba(), others use "transparent"
       
  8553 if (Y.UA.webkit) {
       
  8554     Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
       
  8555         var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
       
  8556             val = view[GET_COMPUTED_STYLE](node, '')[att];
       
  8557 
       
  8558         if (val === 'rgba(0, 0, 0, 0)') {
       
  8559             val = TRANSPARENT; 
       
  8560         }
       
  8561 
       
  8562         return val;
       
  8563     };
       
  8564 
       
  8565 }
       
  8566 
       
  8567 Y.DOM._getAttrOffset = function(node, attr) {
       
  8568     var val = Y.DOM[GET_COMPUTED_STYLE](node, attr),
       
  8569         offsetParent = node.offsetParent,
       
  8570         position,
       
  8571         parentOffset,
       
  8572         offset;
       
  8573 
       
  8574     if (val === 'auto') {
       
  8575         position = Y.DOM.getStyle(node, 'position');
       
  8576         if (position === 'static' || position === 'relative') {
       
  8577             val = 0;    
       
  8578         } else if (offsetParent && offsetParent[GET_BOUNDING_CLIENT_RECT]) {
       
  8579             parentOffset = offsetParent[GET_BOUNDING_CLIENT_RECT]()[attr];
       
  8580             offset = node[GET_BOUNDING_CLIENT_RECT]()[attr];
       
  8581             if (attr === 'left' || attr === 'top') {
       
  8582                 val = offset - parentOffset;
       
  8583             } else {
       
  8584                 val = parentOffset - node[GET_BOUNDING_CLIENT_RECT]()[attr];
       
  8585             }
       
  8586         }
       
  8587     }
       
  8588 
       
  8589     return val;
       
  8590 };
       
  8591 
       
  8592 Y.DOM._getOffset = function(node) {
       
  8593     var pos,
       
  8594         xy = null;
       
  8595 
       
  8596     if (node) {
       
  8597         pos = Y_DOM.getStyle(node, 'position');
       
  8598         xy = [
       
  8599             parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'left'), 10),
       
  8600             parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'top'), 10)
       
  8601         ];
       
  8602 
       
  8603         if ( isNaN(xy[0]) ) { // in case of 'auto'
       
  8604             xy[0] = parseInt(Y_DOM.getStyle(node, 'left'), 10); // try inline
       
  8605             if ( isNaN(xy[0]) ) { // default to offset value
       
  8606                 xy[0] = (pos === 'relative') ? 0 : node.offsetLeft || 0;
       
  8607             }
       
  8608         } 
       
  8609 
       
  8610         if ( isNaN(xy[1]) ) { // in case of 'auto'
       
  8611             xy[1] = parseInt(Y_DOM.getStyle(node, 'top'), 10); // try inline
       
  8612             if ( isNaN(xy[1]) ) { // default to offset value
       
  8613                 xy[1] = (pos === 'relative') ? 0 : node.offsetTop || 0;
       
  8614             }
       
  8615         } 
       
  8616     }
       
  8617 
       
  8618     return xy;
       
  8619 
       
  8620 };
       
  8621 
       
  8622 Y_DOM.CUSTOM_STYLES.transform = {
       
  8623     set: function(node, val, style) {
       
  8624         style[TRANSFORM] = val;
       
  8625     },
       
  8626 
       
  8627     get: function(node, style) {
       
  8628         return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORM);
       
  8629     }
       
  8630 };
       
  8631 
       
  8632 Y_DOM.CUSTOM_STYLES.transformOrigin = {
       
  8633     set: function(node, val, style) {
       
  8634         style[TRANSFORMORIGIN] = val;
       
  8635     },
       
  8636 
       
  8637     get: function(node, style) {
       
  8638         return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORMORIGIN);
       
  8639     }
       
  8640 };
       
  8641 
       
  8642 
       
  8643 })(Y);
       
  8644 
       
  8645 
       
  8646 }, '@VERSION@', {"requires": ["dom-base", "color-base"]});
       
  8647 YUI.add('dom-style-ie', function (Y, NAME) {
       
  8648 
       
  8649 (function(Y) {
       
  8650 var HAS_LAYOUT = 'hasLayout',
       
  8651     PX = 'px',
       
  8652     FILTER = 'filter',
       
  8653     FILTERS = 'filters',
       
  8654     OPACITY = 'opacity',
       
  8655     AUTO = 'auto',
       
  8656 
       
  8657     BORDER_WIDTH = 'borderWidth',
       
  8658     BORDER_TOP_WIDTH = 'borderTopWidth',
       
  8659     BORDER_RIGHT_WIDTH = 'borderRightWidth',
       
  8660     BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
       
  8661     BORDER_LEFT_WIDTH = 'borderLeftWidth',
       
  8662     WIDTH = 'width',
       
  8663     HEIGHT = 'height',
       
  8664     TRANSPARENT = 'transparent',
       
  8665     VISIBLE = 'visible',
       
  8666     GET_COMPUTED_STYLE = 'getComputedStyle',
       
  8667     UNDEFINED = undefined,
       
  8668     documentElement = Y.config.doc.documentElement,
       
  8669 
       
  8670     testFeature = Y.Features.test,
       
  8671     addFeature = Y.Features.add,
       
  8672 
       
  8673     // TODO: unit-less lineHeight (e.g. 1.22)
       
  8674     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,
       
  8675 
       
  8676     isIE8 = (Y.UA.ie >= 8),
       
  8677 
       
  8678     _getStyleObj = function(node) {
       
  8679         return node.currentStyle || node.style;
       
  8680     },
       
  8681 
       
  8682     ComputedStyle = {
       
  8683         CUSTOM_STYLES: {},
       
  8684 
       
  8685         get: function(el, property) {
       
  8686             var value = '',
       
  8687                 current;
       
  8688 
       
  8689             if (el) {
       
  8690                     current = _getStyleObj(el)[property];
       
  8691 
       
  8692                 if (property === OPACITY && Y.DOM.CUSTOM_STYLES[OPACITY]) {
       
  8693                     value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);        
       
  8694                 } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
       
  8695                     value = current;
       
  8696                 } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
       
  8697                     value = Y.DOM.IE.COMPUTED[property](el, property);
       
  8698                 } else if (re_unit.test(current)) { // convert to pixel
       
  8699                     value = ComputedStyle.getPixel(el, property) + PX;
       
  8700                 } else {
       
  8701                     value = current;
       
  8702                 }
       
  8703             }
       
  8704 
       
  8705             return value;
       
  8706         },
       
  8707 
       
  8708         sizeOffsets: {
       
  8709             width: ['Left', 'Right'],
       
  8710             height: ['Top', 'Bottom'],
       
  8711             top: ['Top'],
       
  8712             bottom: ['Bottom']
       
  8713         },
       
  8714 
       
  8715         getOffset: function(el, prop) {
       
  8716             var current = _getStyleObj(el)[prop],                     // value of "width", "top", etc.
       
  8717                 capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
       
  8718                 offset = 'offset' + capped,                             // "offsetWidth", "offsetTop", etc.
       
  8719                 pixel = 'pixel' + capped,                               // "pixelWidth", "pixelTop", etc.
       
  8720                 sizeOffsets = ComputedStyle.sizeOffsets[prop], 
       
  8721                 mode = el.ownerDocument.compatMode,
       
  8722                 value = '';
       
  8723 
       
  8724             // IE pixelWidth incorrect for percent
       
  8725             // manually compute by subtracting padding and border from offset size
       
  8726             // NOTE: clientWidth/Height (size minus border) is 0 when current === AUTO so offsetHeight is used
       
  8727             // reverting to auto from auto causes position stacking issues (old impl)
       
  8728             if (current === AUTO || current.indexOf('%') > -1) {
       
  8729                 value = el['offset' + capped];
       
  8730 
       
  8731                 if (mode !== 'BackCompat') {
       
  8732                     if (sizeOffsets[0]) {
       
  8733                         value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[0]);
       
  8734                         value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[0] + 'Width', 1);
       
  8735                     }
       
  8736 
       
  8737                     if (sizeOffsets[1]) {
       
  8738                         value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[1]);
       
  8739                         value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[1] + 'Width', 1);
       
  8740                     }
       
  8741                 }
       
  8742 
       
  8743             } else { // use style.pixelWidth, etc. to convert to pixels
       
  8744                 // need to map style.width to currentStyle (no currentStyle.pixelWidth)
       
  8745                 if (!el.style[pixel] && !el.style[prop]) {
       
  8746                     el.style[prop] = current;
       
  8747                 }
       
  8748                 value = el.style[pixel];
       
  8749                 
       
  8750             }
       
  8751             return value + PX;
       
  8752         },
       
  8753 
       
  8754         borderMap: {
       
  8755             thin: (isIE8) ? '1px' : '2px',
       
  8756             medium: (isIE8) ? '3px': '4px', 
       
  8757             thick: (isIE8) ? '5px' : '6px'
       
  8758         },
       
  8759 
       
  8760         getBorderWidth: function(el, property, omitUnit) {
       
  8761             var unit = omitUnit ? '' : PX,
       
  8762                 current = el.currentStyle[property];
       
  8763 
       
  8764             if (current.indexOf(PX) < 0) { // look up keywords if a border exists
       
  8765                 if (ComputedStyle.borderMap[current] &&
       
  8766                         el.currentStyle.borderStyle !== 'none') {
       
  8767                     current = ComputedStyle.borderMap[current];
       
  8768                 } else { // otherwise no border (default is "medium")
       
  8769                     current = 0;
       
  8770                 }
       
  8771             }
       
  8772             return (omitUnit) ? parseFloat(current) : current;
       
  8773         },
       
  8774 
       
  8775         getPixel: function(node, att) {
       
  8776             // use pixelRight to convert to px
       
  8777             var val = null,
       
  8778                 style = _getStyleObj(node),
       
  8779                 styleRight = style.right,
       
  8780                 current = style[att];
       
  8781 
       
  8782             node.style.right = current;
       
  8783             val = node.style.pixelRight;
       
  8784             node.style.right = styleRight; // revert
       
  8785 
       
  8786             return val;
       
  8787         },
       
  8788 
       
  8789         getMargin: function(node, att) {
       
  8790             var val,
       
  8791                 style = _getStyleObj(node);
       
  8792 
       
  8793             if (style[att] == AUTO) {
       
  8794                 val = 0;
       
  8795             } else {
       
  8796                 val = ComputedStyle.getPixel(node, att);
       
  8797             }
       
  8798             return val + PX;
       
  8799         },
       
  8800 
       
  8801         getVisibility: function(node, att) {
       
  8802             var current;
       
  8803             while ( (current = node.currentStyle) && current[att] == 'inherit') { // NOTE: assignment in test
       
  8804                 node = node.parentNode;
       
  8805             }
       
  8806             return (current) ? current[att] : VISIBLE;
       
  8807         },
       
  8808 
       
  8809         getColor: function(node, att) {
       
  8810             var current = _getStyleObj(node)[att];
       
  8811 
       
  8812             if (!current || current === TRANSPARENT) {
       
  8813                 Y.DOM.elementByAxis(node, 'parentNode', null, function(parent) {
       
  8814                     current = _getStyleObj(parent)[att];
       
  8815                     if (current && current !== TRANSPARENT) {
       
  8816                         node = parent;
       
  8817                         return true;
       
  8818                     }
       
  8819                 });
       
  8820             }
       
  8821 
       
  8822             return Y.Color.toRGB(current);
       
  8823         },
       
  8824 
       
  8825         getBorderColor: function(node, att) {
       
  8826             var current = _getStyleObj(node),
       
  8827                 val = current[att] || current.color;
       
  8828             return Y.Color.toRGB(Y.Color.toHex(val));
       
  8829         }
       
  8830     },
       
  8831 
       
  8832     //fontSize: getPixelFont,
       
  8833     IEComputed = {};
       
  8834 
       
  8835 addFeature('style', 'computedStyle', {
       
  8836     test: function() {
       
  8837         return 'getComputedStyle' in Y.config.win;
       
  8838     }
       
  8839 });
       
  8840 
       
  8841 addFeature('style', 'opacity', {
       
  8842     test: function() {
       
  8843         return 'opacity' in documentElement.style;
       
  8844     }
       
  8845 });
       
  8846 
       
  8847 addFeature('style', 'filter', {
       
  8848     test: function() {
       
  8849         return 'filters' in documentElement;
       
  8850     }
       
  8851 });
       
  8852 
       
  8853 // use alpha filter for IE opacity
       
  8854 if (!testFeature('style', 'opacity') && testFeature('style', 'filter')) {
       
  8855     Y.DOM.CUSTOM_STYLES[OPACITY] = {
       
  8856         get: function(node) {
       
  8857             var val = 100;
       
  8858             try { // will error if no DXImageTransform
       
  8859                 val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
       
  8860 
       
  8861             } catch(e) {
       
  8862                 try { // make sure its in the document
       
  8863                     val = node[FILTERS]('alpha')[OPACITY];
       
  8864                 } catch(err) {
       
  8865                     Y.log('getStyle: IE opacity filter not found; returning 1', 'warn', 'dom-style');
       
  8866                 }
       
  8867             }
       
  8868             return val / 100;
       
  8869         },
       
  8870 
       
  8871         set: function(node, val, style) {
       
  8872             var current,
       
  8873                 styleObj = _getStyleObj(node),
       
  8874                 currentFilter = styleObj[FILTER];
       
  8875 
       
  8876             style = style || node.style;
       
  8877             if (val === '') { // normalize inline style behavior
       
  8878                 current = (OPACITY in styleObj) ? styleObj[OPACITY] : 1; // revert to original opacity
       
  8879                 val = current;
       
  8880             }
       
  8881 
       
  8882             if (typeof currentFilter == 'string') { // in case not appended
       
  8883                 style[FILTER] = currentFilter.replace(/alpha([^)]*\))/gi, '') +
       
  8884                         ((val < 1) ? 'alpha(' + OPACITY + '=' + val * 100 + ')' : '');
       
  8885 
       
  8886                 if (!style[FILTER]) {
       
  8887                     style.removeAttribute(FILTER);
       
  8888                 }
       
  8889 
       
  8890                 if (!styleObj[HAS_LAYOUT]) {
       
  8891                     style.zoom = 1; // needs layout 
       
  8892                 }
       
  8893             }
       
  8894         }
       
  8895     };
       
  8896 }
       
  8897 
       
  8898 try {
       
  8899     Y.config.doc.createElement('div').style.height = '-1px';
       
  8900 } catch(e) { // IE throws error on invalid style set; trap common cases
       
  8901     Y.DOM.CUSTOM_STYLES.height = {
       
  8902         set: function(node, val, style) {
       
  8903             var floatVal = parseFloat(val);
       
  8904             if (floatVal >= 0 || val === 'auto' || val === '') {
       
  8905                 style.height = val;
       
  8906             } else {
       
  8907                 Y.log('invalid style value for height: ' + val, 'warn', 'dom-style');
       
  8908             }
       
  8909         }
       
  8910     };
       
  8911 
       
  8912     Y.DOM.CUSTOM_STYLES.width = {
       
  8913         set: function(node, val, style) {
       
  8914             var floatVal = parseFloat(val);
       
  8915             if (floatVal >= 0 || val === 'auto' || val === '') {
       
  8916                 style.width = val;
       
  8917             } else {
       
  8918                 Y.log('invalid style value for width: ' + val, 'warn', 'dom-style');
       
  8919             }
       
  8920         }
       
  8921     };
       
  8922 }
       
  8923 
       
  8924 if (!testFeature('style', 'computedStyle')) {
       
  8925     // TODO: top, right, bottom, left
       
  8926     IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
       
  8927 
       
  8928     IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
       
  8929 
       
  8930     IEComputed[BORDER_WIDTH] = IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
       
  8931             IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
       
  8932             ComputedStyle.getBorderWidth;
       
  8933 
       
  8934     IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
       
  8935             IEComputed.marginLeft = ComputedStyle.getMargin;
       
  8936 
       
  8937     IEComputed.visibility = ComputedStyle.getVisibility;
       
  8938     IEComputed.borderColor = IEComputed.borderTopColor =
       
  8939             IEComputed.borderRightColor = IEComputed.borderBottomColor =
       
  8940             IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
       
  8941 
       
  8942     Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get; 
       
  8943 
       
  8944     Y.namespace('DOM.IE');
       
  8945     Y.DOM.IE.COMPUTED = IEComputed;
       
  8946     Y.DOM.IE.ComputedStyle = ComputedStyle;
       
  8947 }
       
  8948 
       
  8949 })(Y);
       
  8950 
       
  8951 
       
  8952 }, '@VERSION@', {"requires": ["dom-style"]});
       
  8953 YUI.add('dom-screen', function (Y, NAME) {
       
  8954 
       
  8955 (function(Y) {
       
  8956 
       
  8957 /**
       
  8958  * Adds position and region management functionality to DOM.
       
  8959  * @module dom
       
  8960  * @submodule dom-screen
       
  8961  * @for DOM
       
  8962  */
       
  8963 
       
  8964 var DOCUMENT_ELEMENT = 'documentElement',
       
  8965     COMPAT_MODE = 'compatMode',
       
  8966     POSITION = 'position',
       
  8967     FIXED = 'fixed',
       
  8968     RELATIVE = 'relative',
       
  8969     LEFT = 'left',
       
  8970     TOP = 'top',
       
  8971     _BACK_COMPAT = 'BackCompat',
       
  8972     MEDIUM = 'medium',
       
  8973     BORDER_LEFT_WIDTH = 'borderLeftWidth',
       
  8974     BORDER_TOP_WIDTH = 'borderTopWidth',
       
  8975     GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
       
  8976     GET_COMPUTED_STYLE = 'getComputedStyle',
       
  8977 
       
  8978     Y_DOM = Y.DOM,
       
  8979 
       
  8980     // TODO: how about thead/tbody/tfoot/tr?
       
  8981     // TODO: does caption matter?
       
  8982     RE_TABLE = /^t(?:able|d|h)$/i,
       
  8983 
       
  8984     SCROLL_NODE;
       
  8985 
       
  8986 if (Y.UA.ie) {
       
  8987     if (Y.config.doc[COMPAT_MODE] !== 'BackCompat') {
       
  8988         SCROLL_NODE = DOCUMENT_ELEMENT; 
       
  8989     } else {
       
  8990         SCROLL_NODE = 'body';
       
  8991     }
       
  8992 }
       
  8993 
       
  8994 Y.mix(Y_DOM, {
       
  8995     /**
       
  8996      * Returns the inner height of the viewport (exludes scrollbar). 
       
  8997      * @method winHeight
       
  8998      * @return {Number} The current height of the viewport.
       
  8999      */
       
  9000     winHeight: function(node) {
       
  9001         var h = Y_DOM._getWinSize(node).height;
       
  9002         Y.log('winHeight returning ' + h, 'info', 'dom-screen');
       
  9003         return h;
       
  9004     },
       
  9005 
       
  9006     /**
       
  9007      * Returns the inner width of the viewport (exludes scrollbar). 
       
  9008      * @method winWidth
       
  9009      * @return {Number} The current width of the viewport.
       
  9010      */
       
  9011     winWidth: function(node) {
       
  9012         var w = Y_DOM._getWinSize(node).width;
       
  9013         Y.log('winWidth returning ' + w, 'info', 'dom-screen');
       
  9014         return w;
       
  9015     },
       
  9016 
       
  9017     /**
       
  9018      * Document height 
       
  9019      * @method docHeight
       
  9020      * @return {Number} The current height of the document.
       
  9021      */
       
  9022     docHeight:  function(node) {
       
  9023         var h = Y_DOM._getDocSize(node).height;
       
  9024         Y.log('docHeight returning ' + h, 'info', 'dom-screen');
       
  9025         return Math.max(h, Y_DOM._getWinSize(node).height);
       
  9026     },
       
  9027 
       
  9028     /**
       
  9029      * Document width 
       
  9030      * @method docWidth
       
  9031      * @return {Number} The current width of the document.
       
  9032      */
       
  9033     docWidth:  function(node) {
       
  9034         var w = Y_DOM._getDocSize(node).width;
       
  9035         Y.log('docWidth returning ' + w, 'info', 'dom-screen');
       
  9036         return Math.max(w, Y_DOM._getWinSize(node).width);
       
  9037     },
       
  9038 
       
  9039     /**
       
  9040      * Amount page has been scroll horizontally 
       
  9041      * @method docScrollX
       
  9042      * @return {Number} The current amount the screen is scrolled horizontally.
       
  9043      */
       
  9044     docScrollX: function(node, doc) {
       
  9045         doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
       
  9046         var dv = doc.defaultView,
       
  9047             pageOffset = (dv) ? dv.pageXOffset : 0;
       
  9048         return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, pageOffset);
       
  9049     },
       
  9050 
       
  9051     /**
       
  9052      * Amount page has been scroll vertically 
       
  9053      * @method docScrollY
       
  9054      * @return {Number} The current amount the screen is scrolled vertically.
       
  9055      */
       
  9056     docScrollY:  function(node, doc) {
       
  9057         doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
       
  9058         var dv = doc.defaultView,
       
  9059             pageOffset = (dv) ? dv.pageYOffset : 0;
       
  9060         return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, pageOffset);
       
  9061     },
       
  9062 
       
  9063     /**
       
  9064      * Gets the current position of an element based on page coordinates. 
       
  9065      * Element must be part of the DOM tree to have page coordinates
       
  9066      * (display:none or elements not appended return false).
       
  9067      * @method getXY
       
  9068      * @param element The target element
       
  9069      * @return {Array} The XY position of the element
       
  9070 
       
  9071      TODO: test inDocument/display?
       
  9072      */
       
  9073     getXY: function() {
       
  9074         if (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
       
  9075             return function(node) {
       
  9076                 var xy = null,
       
  9077                     scrollLeft,
       
  9078                     scrollTop,
       
  9079                     mode,
       
  9080                     box,
       
  9081                     offX,
       
  9082                     offY,
       
  9083                     doc,
       
  9084                     win,
       
  9085                     inDoc,
       
  9086                     rootNode;
       
  9087 
       
  9088                 if (node && node.tagName) {
       
  9089                     doc = node.ownerDocument;
       
  9090                     mode = doc[COMPAT_MODE];
       
  9091 
       
  9092                     if (mode !== _BACK_COMPAT) {
       
  9093                         rootNode = doc[DOCUMENT_ELEMENT];
       
  9094                     } else {
       
  9095                         rootNode = doc.body;
       
  9096                     }
       
  9097 
       
  9098                     // inline inDoc check for perf
       
  9099                     if (rootNode.contains) {
       
  9100                         inDoc = rootNode.contains(node); 
       
  9101                     } else {
       
  9102                         inDoc = Y.DOM.contains(rootNode, node);
       
  9103                     }
       
  9104 
       
  9105                     if (inDoc) {
       
  9106                         win = doc.defaultView;
       
  9107 
       
  9108                         // inline scroll calc for perf
       
  9109                         if (win && 'pageXOffset' in win) {
       
  9110                             scrollLeft = win.pageXOffset;
       
  9111                             scrollTop = win.pageYOffset;
       
  9112                         } else {
       
  9113                             scrollLeft = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc);
       
  9114                             scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop : Y_DOM.docScrollY(node, doc);
       
  9115                         }
       
  9116 
       
  9117                         if (Y.UA.ie) { // IE < 8, quirks, or compatMode
       
  9118                             if (!doc.documentMode || doc.documentMode < 8 || mode === _BACK_COMPAT) {
       
  9119                                 offX = rootNode.clientLeft;
       
  9120                                 offY = rootNode.clientTop;
       
  9121                             }
       
  9122                         }
       
  9123                         box = node[GET_BOUNDING_CLIENT_RECT]();
       
  9124                         xy = [box.left, box.top];
       
  9125 
       
  9126                         if (offX || offY) {
       
  9127                                 xy[0] -= offX;
       
  9128                                 xy[1] -= offY;
       
  9129                             
       
  9130                         }
       
  9131                         if ((scrollTop || scrollLeft)) {
       
  9132                             if (!Y.UA.ios || (Y.UA.ios >= 4.2)) {
       
  9133                                 xy[0] += scrollLeft;
       
  9134                                 xy[1] += scrollTop;
       
  9135                             }
       
  9136                             
       
  9137                         }
       
  9138                     } else {
       
  9139                         xy = Y_DOM._getOffset(node);       
       
  9140                     }
       
  9141                 }
       
  9142                 return xy;                   
       
  9143             };
       
  9144         } else {
       
  9145             return function(node) { // manually calculate by crawling up offsetParents
       
  9146                 //Calculate the Top and Left border sizes (assumes pixels)
       
  9147                 var xy = null,
       
  9148                     doc,
       
  9149                     parentNode,
       
  9150                     bCheck,
       
  9151                     scrollTop,
       
  9152                     scrollLeft;
       
  9153 
       
  9154                 if (node) {
       
  9155                     if (Y_DOM.inDoc(node)) {
       
  9156                         xy = [node.offsetLeft, node.offsetTop];
       
  9157                         doc = node.ownerDocument;
       
  9158                         parentNode = node;
       
  9159                         // TODO: refactor with !! or just falsey
       
  9160                         bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
       
  9161 
       
  9162                         // TODO: worth refactoring for TOP/LEFT only?
       
  9163                         while ((parentNode = parentNode.offsetParent)) {
       
  9164                             xy[0] += parentNode.offsetLeft;
       
  9165                             xy[1] += parentNode.offsetTop;
       
  9166                             if (bCheck) {
       
  9167                                 xy = Y_DOM._calcBorders(parentNode, xy);
       
  9168                             }
       
  9169                         }
       
  9170 
       
  9171                         // account for any scrolled ancestors
       
  9172                         if (Y_DOM.getStyle(node, POSITION) != FIXED) {
       
  9173                             parentNode = node;
       
  9174 
       
  9175                             while ((parentNode = parentNode.parentNode)) {
       
  9176                                 scrollTop = parentNode.scrollTop;
       
  9177                                 scrollLeft = parentNode.scrollLeft;
       
  9178 
       
  9179                                 //Firefox does something funky with borders when overflow is not visible.
       
  9180                                 if (Y.UA.gecko && (Y_DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
       
  9181                                         xy = Y_DOM._calcBorders(parentNode, xy);
       
  9182                                 }
       
  9183                                 
       
  9184 
       
  9185                                 if (scrollTop || scrollLeft) {
       
  9186                                     xy[0] -= scrollLeft;
       
  9187                                     xy[1] -= scrollTop;
       
  9188                                 }
       
  9189                             }
       
  9190                             xy[0] += Y_DOM.docScrollX(node, doc);
       
  9191                             xy[1] += Y_DOM.docScrollY(node, doc);
       
  9192 
       
  9193                         } else {
       
  9194                             //Fix FIXED position -- add scrollbars
       
  9195                             xy[0] += Y_DOM.docScrollX(node, doc);
       
  9196                             xy[1] += Y_DOM.docScrollY(node, doc);
       
  9197                         }
       
  9198                     } else {
       
  9199                         xy = Y_DOM._getOffset(node);
       
  9200                     }
       
  9201                 }
       
  9202 
       
  9203                 return xy;                
       
  9204             };
       
  9205         }
       
  9206     }(),// NOTE: Executing for loadtime branching
       
  9207 
       
  9208     /**
       
  9209     Gets the width of vertical scrollbars on overflowed containers in the body
       
  9210     content.
       
  9211 
       
  9212     @method getScrollbarWidth
       
  9213     @return {Number} Pixel width of a scrollbar in the current browser
       
  9214     **/
       
  9215     getScrollbarWidth: Y.cached(function () {
       
  9216         var doc      = Y.config.doc,
       
  9217             testNode = doc.createElement('div'),
       
  9218             body     = doc.getElementsByTagName('body')[0],
       
  9219             // 0.1 because cached doesn't support falsy refetch values
       
  9220             width    = 0.1;
       
  9221             
       
  9222         if (body) {
       
  9223             testNode.style.cssText = "position:absolute;visibility:hidden;overflow:scroll;width:20px;";
       
  9224             testNode.appendChild(doc.createElement('p')).style.height = '1px';
       
  9225             body.insertBefore(testNode, body.firstChild);
       
  9226             width = testNode.offsetWidth - testNode.clientWidth;
       
  9227 
       
  9228             body.removeChild(testNode);
       
  9229         }
       
  9230 
       
  9231         return width;
       
  9232     }, null, 0.1),
       
  9233 
       
  9234     /**
       
  9235      * Gets the current X position of an element based on page coordinates. 
       
  9236      * Element must be part of the DOM tree to have page coordinates
       
  9237      * (display:none or elements not appended return false).
       
  9238      * @method getX
       
  9239      * @param element The target element
       
  9240      * @return {Number} The X position of the element
       
  9241      */
       
  9242 
       
  9243     getX: function(node) {
       
  9244         return Y_DOM.getXY(node)[0];
       
  9245     },
       
  9246 
       
  9247     /**
       
  9248      * Gets the current Y position of an element based on page coordinates. 
       
  9249      * Element must be part of the DOM tree to have page coordinates
       
  9250      * (display:none or elements not appended return false).
       
  9251      * @method getY
       
  9252      * @param element The target element
       
  9253      * @return {Number} The Y position of the element
       
  9254      */
       
  9255 
       
  9256     getY: function(node) {
       
  9257         return Y_DOM.getXY(node)[1];
       
  9258     },
       
  9259 
       
  9260     /**
       
  9261      * Set the position of an html element in page coordinates.
       
  9262      * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
       
  9263      * @method setXY
       
  9264      * @param element The target element
       
  9265      * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
       
  9266      * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
       
  9267      */
       
  9268     setXY: function(node, xy, noRetry) {
       
  9269         var setStyle = Y_DOM.setStyle,
       
  9270             pos,
       
  9271             delta,
       
  9272             newXY,
       
  9273             currentXY;
       
  9274 
       
  9275         if (node && xy) {
       
  9276             pos = Y_DOM.getStyle(node, POSITION);
       
  9277 
       
  9278             delta = Y_DOM._getOffset(node);       
       
  9279             if (pos == 'static') { // default to relative
       
  9280                 pos = RELATIVE;
       
  9281                 setStyle(node, POSITION, pos);
       
  9282             }
       
  9283             currentXY = Y_DOM.getXY(node);
       
  9284 
       
  9285             if (xy[0] !== null) {
       
  9286                 setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
       
  9287             }
       
  9288 
       
  9289             if (xy[1] !== null) {
       
  9290                 setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
       
  9291             }
       
  9292 
       
  9293             if (!noRetry) {
       
  9294                 newXY = Y_DOM.getXY(node);
       
  9295                 if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) {
       
  9296                     Y_DOM.setXY(node, xy, true); 
       
  9297                 }
       
  9298             }
       
  9299           
       
  9300             Y.log('setXY setting position to ' + xy, 'info', 'dom-screen');
       
  9301         } else {
       
  9302             Y.log('setXY failed to set ' + node + ' to ' + xy, 'info', 'dom-screen');
       
  9303         }
       
  9304     },
       
  9305 
       
  9306     /**
       
  9307      * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
       
  9308      * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
       
  9309      * @method setX
       
  9310      * @param element The target element
       
  9311      * @param {Number} x The X values for new position (coordinates are page-based)
       
  9312      */
       
  9313     setX: function(node, x) {
       
  9314         return Y_DOM.setXY(node, [x, null]);
       
  9315     },
       
  9316 
       
  9317     /**
       
  9318      * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
       
  9319      * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
       
  9320      * @method setY
       
  9321      * @param element The target element
       
  9322      * @param {Number} y The Y values for new position (coordinates are page-based)
       
  9323      */
       
  9324     setY: function(node, y) {
       
  9325         return Y_DOM.setXY(node, [null, y]);
       
  9326     },
       
  9327 
       
  9328     /**
       
  9329      * @method swapXY
       
  9330      * @description Swap the xy position with another node
       
  9331      * @param {Node} node The node to swap with
       
  9332      * @param {Node} otherNode The other node to swap with
       
  9333      * @return {Node}
       
  9334      */
       
  9335     swapXY: function(node, otherNode) {
       
  9336         var xy = Y_DOM.getXY(node);
       
  9337         Y_DOM.setXY(node, Y_DOM.getXY(otherNode));
       
  9338         Y_DOM.setXY(otherNode, xy);
       
  9339     },
       
  9340 
       
  9341     _calcBorders: function(node, xy2) {
       
  9342         var t = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
       
  9343             l = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
       
  9344         if (Y.UA.gecko) {
       
  9345             if (RE_TABLE.test(node.tagName)) {
       
  9346                 t = 0;
       
  9347                 l = 0;
       
  9348             }
       
  9349         }
       
  9350         xy2[0] += l;
       
  9351         xy2[1] += t;
       
  9352         return xy2;
       
  9353     },
       
  9354 
       
  9355     _getWinSize: function(node, doc) {
       
  9356         doc  = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc;
       
  9357         var win = doc.defaultView || doc.parentWindow,
       
  9358             mode = doc[COMPAT_MODE],
       
  9359             h = win.innerHeight,
       
  9360             w = win.innerWidth,
       
  9361             root = doc[DOCUMENT_ELEMENT];
       
  9362 
       
  9363         if ( mode && !Y.UA.opera ) { // IE, Gecko
       
  9364             if (mode != 'CSS1Compat') { // Quirks
       
  9365                 root = doc.body; 
       
  9366             }
       
  9367             h = root.clientHeight;
       
  9368             w = root.clientWidth;
       
  9369         }
       
  9370         return { height: h, width: w };
       
  9371     },
       
  9372 
       
  9373     _getDocSize: function(node) {
       
  9374         var doc = (node) ? Y_DOM._getDoc(node) : Y.config.doc,
       
  9375             root = doc[DOCUMENT_ELEMENT];
       
  9376 
       
  9377         if (doc[COMPAT_MODE] != 'CSS1Compat') {
       
  9378             root = doc.body;
       
  9379         }
       
  9380 
       
  9381         return { height: root.scrollHeight, width: root.scrollWidth };
       
  9382     }
       
  9383 });
       
  9384 
       
  9385 })(Y);
       
  9386 (function(Y) {
       
  9387 var TOP = 'top',
       
  9388     RIGHT = 'right',
       
  9389     BOTTOM = 'bottom',
       
  9390     LEFT = 'left',
       
  9391 
       
  9392     getOffsets = function(r1, r2) {
       
  9393         var t = Math.max(r1[TOP], r2[TOP]),
       
  9394             r = Math.min(r1[RIGHT], r2[RIGHT]),
       
  9395             b = Math.min(r1[BOTTOM], r2[BOTTOM]),
       
  9396             l = Math.max(r1[LEFT], r2[LEFT]),
       
  9397             ret = {};
       
  9398         
       
  9399         ret[TOP] = t;
       
  9400         ret[RIGHT] = r;
       
  9401         ret[BOTTOM] = b;
       
  9402         ret[LEFT] = l;
       
  9403         return ret;
       
  9404     },
       
  9405 
       
  9406     DOM = Y.DOM;
       
  9407 
       
  9408 Y.mix(DOM, {
       
  9409     /**
       
  9410      * Returns an Object literal containing the following about this element: (top, right, bottom, left)
       
  9411      * @for DOM
       
  9412      * @method region
       
  9413      * @param {HTMLElement} element The DOM element. 
       
  9414      * @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
       
  9415      */
       
  9416     region: function(node) {
       
  9417         var xy = DOM.getXY(node),
       
  9418             ret = false;
       
  9419         
       
  9420         if (node && xy) {
       
  9421             ret = DOM._getRegion(
       
  9422                 xy[1], // top
       
  9423                 xy[0] + node.offsetWidth, // right
       
  9424                 xy[1] + node.offsetHeight, // bottom
       
  9425                 xy[0] // left
       
  9426             );
       
  9427         }
       
  9428 
       
  9429         return ret;
       
  9430     },
       
  9431 
       
  9432     /**
       
  9433      * Find the intersect information for the passed nodes.
       
  9434      * @method intersect
       
  9435      * @for DOM
       
  9436      * @param {HTMLElement} element The first element 
       
  9437      * @param {HTMLElement | Object} element2 The element or region to check the interect with
       
  9438      * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance e.g. DragDrop)
       
  9439      * @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
       
  9440      */
       
  9441     intersect: function(node, node2, altRegion) {
       
  9442         var r = altRegion || DOM.region(node), region = {},
       
  9443             n = node2,
       
  9444             off;
       
  9445 
       
  9446         if (n.tagName) {
       
  9447             region = DOM.region(n);
       
  9448         } else if (Y.Lang.isObject(node2)) {
       
  9449             region = node2;
       
  9450         } else {
       
  9451             return false;
       
  9452         }
       
  9453         
       
  9454         off = getOffsets(region, r);
       
  9455         return {
       
  9456             top: off[TOP],
       
  9457             right: off[RIGHT],
       
  9458             bottom: off[BOTTOM],
       
  9459             left: off[LEFT],
       
  9460             area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
       
  9461             yoff: ((off[BOTTOM] - off[TOP])),
       
  9462             xoff: (off[RIGHT] - off[LEFT]),
       
  9463             inRegion: DOM.inRegion(node, node2, false, altRegion)
       
  9464         };
       
  9465         
       
  9466     },
       
  9467     /**
       
  9468      * Check if any part of this node is in the passed region
       
  9469      * @method inRegion
       
  9470      * @for DOM
       
  9471      * @param {Object} node The node to get the region from
       
  9472      * @param {Object} node2 The second node to get the region from or an Object literal of the region
       
  9473      * @param {Boolean} all Should all of the node be inside the region
       
  9474      * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop)
       
  9475      * @return {Boolean} True if in region, false if not.
       
  9476      */
       
  9477     inRegion: function(node, node2, all, altRegion) {
       
  9478         var region = {},
       
  9479             r = altRegion || DOM.region(node),
       
  9480             n = node2,
       
  9481             off;
       
  9482 
       
  9483         if (n.tagName) {
       
  9484             region = DOM.region(n);
       
  9485         } else if (Y.Lang.isObject(node2)) {
       
  9486             region = node2;
       
  9487         } else {
       
  9488             return false;
       
  9489         }
       
  9490             
       
  9491         if (all) {
       
  9492             return (
       
  9493                 r[LEFT]   >= region[LEFT]   &&
       
  9494                 r[RIGHT]  <= region[RIGHT]  && 
       
  9495                 r[TOP]    >= region[TOP]    && 
       
  9496                 r[BOTTOM] <= region[BOTTOM]  );
       
  9497         } else {
       
  9498             off = getOffsets(region, r);
       
  9499             if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
       
  9500                 return true;
       
  9501             } else {
       
  9502                 return false;
       
  9503             }
       
  9504             
       
  9505         }
       
  9506     },
       
  9507 
       
  9508     /**
       
  9509      * Check if any part of this element is in the viewport
       
  9510      * @method inViewportRegion
       
  9511      * @for DOM
       
  9512      * @param {HTMLElement} element The DOM element. 
       
  9513      * @param {Boolean} all Should all of the node be inside the region
       
  9514      * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance e.g. DragDrop)
       
  9515      * @return {Boolean} True if in region, false if not.
       
  9516      */
       
  9517     inViewportRegion: function(node, all, altRegion) {
       
  9518         return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
       
  9519             
       
  9520     },
       
  9521 
       
  9522     _getRegion: function(t, r, b, l) {
       
  9523         var region = {};
       
  9524 
       
  9525         region[TOP] = region[1] = t;
       
  9526         region[LEFT] = region[0] = l;
       
  9527         region[BOTTOM] = b;
       
  9528         region[RIGHT] = r;
       
  9529         region.width = region[RIGHT] - region[LEFT];
       
  9530         region.height = region[BOTTOM] - region[TOP];
       
  9531 
       
  9532         return region;
       
  9533     },
       
  9534 
       
  9535     /**
       
  9536      * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
       
  9537      * @method viewportRegion
       
  9538      * @for DOM
       
  9539      * @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
       
  9540      */
       
  9541     viewportRegion: function(node) {
       
  9542         node = node || Y.config.doc.documentElement;
       
  9543         var ret = false,
       
  9544             scrollX,
       
  9545             scrollY;
       
  9546 
       
  9547         if (node) {
       
  9548             scrollX = DOM.docScrollX(node);
       
  9549             scrollY = DOM.docScrollY(node);
       
  9550 
       
  9551             ret = DOM._getRegion(scrollY, // top
       
  9552                 DOM.winWidth(node) + scrollX, // right
       
  9553                 scrollY + DOM.winHeight(node), // bottom
       
  9554                 scrollX); // left
       
  9555         }
       
  9556 
       
  9557         return ret;
       
  9558     }
       
  9559 });
       
  9560 })(Y);
       
  9561 
       
  9562 
       
  9563 }, '@VERSION@', {"requires": ["dom-base", "dom-style"]});
       
  9564 YUI.add('selector-native', function (Y, NAME) {
       
  9565 
       
  9566 (function(Y) {
       
  9567 /**
       
  9568  * The selector-native module provides support for native querySelector
       
  9569  * @module dom
       
  9570  * @submodule selector-native
       
  9571  * @for Selector
       
  9572  */
       
  9573 
       
  9574 /**
       
  9575  * Provides support for using CSS selectors to query the DOM 
       
  9576  * @class Selector 
       
  9577  * @static
       
  9578  * @for Selector
       
  9579  */
       
  9580 
       
  9581 Y.namespace('Selector'); // allow native module to standalone
       
  9582 
       
  9583 var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
       
  9584     OWNER_DOCUMENT = 'ownerDocument';
       
  9585 
       
  9586 var Selector = {
       
  9587     _types: {
       
  9588         esc: {
       
  9589             token: '\uE000',
       
  9590             re: /\\[:\[\]\(\)#\.\'\>+~"]/gi
       
  9591         },
       
  9592 
       
  9593         attr: {
       
  9594             token: '\uE001',
       
  9595             re: /(\[[^\]]*\])/g
       
  9596         },
       
  9597 
       
  9598         pseudo: {
       
  9599             token: '\uE002',
       
  9600             re: /(\([^\)]*\))/g
       
  9601         }
       
  9602     },
       
  9603 
       
  9604     useNative: true,
       
  9605 
       
  9606     _escapeId: function(id) {
       
  9607         if (id) {
       
  9608             id = id.replace(/([:\[\]\(\)#\.'<>+~"])/g,'\\$1');
       
  9609         }
       
  9610         return id;
       
  9611     },
       
  9612 
       
  9613     _compare: ('sourceIndex' in Y.config.doc.documentElement) ?
       
  9614         function(nodeA, nodeB) {
       
  9615             var a = nodeA.sourceIndex,
       
  9616                 b = nodeB.sourceIndex;
       
  9617 
       
  9618             if (a === b) {
       
  9619                 return 0;
       
  9620             } else if (a > b) {
       
  9621                 return 1;
       
  9622             }
       
  9623 
       
  9624             return -1;
       
  9625 
       
  9626         } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ?
       
  9627         function(nodeA, nodeB) {
       
  9628             if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
       
  9629                 return -1;
       
  9630             } else {
       
  9631                 return 1;
       
  9632             }
       
  9633         } :
       
  9634         function(nodeA, nodeB) {
       
  9635             var rangeA, rangeB, compare;
       
  9636             if (nodeA && nodeB) {
       
  9637                 rangeA = nodeA[OWNER_DOCUMENT].createRange();
       
  9638                 rangeA.setStart(nodeA, 0);
       
  9639                 rangeB = nodeB[OWNER_DOCUMENT].createRange();
       
  9640                 rangeB.setStart(nodeB, 0);
       
  9641                 compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END
       
  9642             }
       
  9643 
       
  9644             return compare;
       
  9645         
       
  9646     }),
       
  9647 
       
  9648     _sort: function(nodes) {
       
  9649         if (nodes) {
       
  9650             nodes = Y.Array(nodes, 0, true);
       
  9651             if (nodes.sort) {
       
  9652                 nodes.sort(Selector._compare);
       
  9653             }
       
  9654         }
       
  9655 
       
  9656         return nodes;
       
  9657     },
       
  9658 
       
  9659     _deDupe: function(nodes) {
       
  9660         var ret = [],
       
  9661             i, node;
       
  9662 
       
  9663         for (i = 0; (node = nodes[i++]);) {
       
  9664             if (!node._found) {
       
  9665                 ret[ret.length] = node;
       
  9666                 node._found = true;
       
  9667             }
       
  9668         }
       
  9669 
       
  9670         for (i = 0; (node = ret[i++]);) {
       
  9671             node._found = null;
       
  9672             node.removeAttribute('_found');
       
  9673         }
       
  9674 
       
  9675         return ret;
       
  9676     },
       
  9677 
       
  9678     /**
       
  9679      * Retrieves a set of nodes based on a given CSS selector. 
       
  9680      * @method query
       
  9681      *
       
  9682      * @param {string} selector The CSS Selector to test the node against.
       
  9683      * @param {HTMLElement} root optional An HTMLElement to start the query from. Defaults to Y.config.doc
       
  9684      * @param {Boolean} firstOnly optional Whether or not to return only the first match.
       
  9685      * @return {Array} An array of nodes that match the given selector.
       
  9686      * @static
       
  9687      */
       
  9688     query: function(selector, root, firstOnly, skipNative) {
       
  9689         root = root || Y.config.doc;
       
  9690         var ret = [],
       
  9691             useNative = (Y.Selector.useNative && Y.config.doc.querySelector && !skipNative),
       
  9692             queries = [[selector, root]],
       
  9693             query,
       
  9694             result,
       
  9695             i,
       
  9696             fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery;
       
  9697 
       
  9698         if (selector && fn) {
       
  9699             // split group into seperate queries
       
  9700             if (!skipNative && // already done if skipping
       
  9701                     (!useNative || root.tagName)) { // split native when element scoping is needed
       
  9702                 queries = Selector._splitQueries(selector, root);
       
  9703             }
       
  9704 
       
  9705             for (i = 0; (query = queries[i++]);) {
       
  9706                 result = fn(query[0], query[1], firstOnly);
       
  9707                 if (!firstOnly) { // coerce DOM Collection to Array
       
  9708                     result = Y.Array(result, 0, true);
       
  9709                 }
       
  9710                 if (result) {
       
  9711                     ret = ret.concat(result);
       
  9712                 }
       
  9713             }
       
  9714 
       
  9715             if (queries.length > 1) { // remove dupes and sort by doc order 
       
  9716                 ret = Selector._sort(Selector._deDupe(ret));
       
  9717             }
       
  9718         }
       
  9719 
       
  9720         Y.log('query: ' + selector + ' returning: ' + ret.length, 'info', 'Selector');
       
  9721         return (firstOnly) ? (ret[0] || null) : ret;
       
  9722 
       
  9723     },
       
  9724 
       
  9725     _replaceSelector: function(selector) {
       
  9726         var esc = Y.Selector._parse('esc', selector), // pull escaped colon, brackets, etc. 
       
  9727             attrs,
       
  9728             pseudos;
       
  9729 
       
  9730         // first replace escaped chars, which could be present in attrs or pseudos
       
  9731         selector = Y.Selector._replace('esc', selector);
       
  9732 
       
  9733         // then replace pseudos before attrs to avoid replacing :not([foo])
       
  9734         pseudos = Y.Selector._parse('pseudo', selector);
       
  9735         selector = Selector._replace('pseudo', selector);
       
  9736 
       
  9737         attrs = Y.Selector._parse('attr', selector);
       
  9738         selector = Y.Selector._replace('attr', selector);
       
  9739 
       
  9740         return {
       
  9741             esc: esc,
       
  9742             attrs: attrs,
       
  9743             pseudos: pseudos,
       
  9744             selector: selector
       
  9745         };
       
  9746     },
       
  9747 
       
  9748     _restoreSelector: function(replaced) {
       
  9749         var selector = replaced.selector;
       
  9750         selector = Y.Selector._restore('attr', selector, replaced.attrs);
       
  9751         selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
       
  9752         selector = Y.Selector._restore('esc', selector, replaced.esc);
       
  9753         return selector;
       
  9754     },
       
  9755 
       
  9756     _replaceCommas: function(selector) {
       
  9757         var replaced = Y.Selector._replaceSelector(selector),
       
  9758             selector = replaced.selector;
       
  9759 
       
  9760         if (selector) {
       
  9761             selector = selector.replace(/,/g, '\uE007');
       
  9762             replaced.selector = selector;
       
  9763             selector = Y.Selector._restoreSelector(replaced);
       
  9764         }
       
  9765         return selector;
       
  9766     },
       
  9767 
       
  9768     // allows element scoped queries to begin with combinator
       
  9769     // e.g. query('> p', document.body) === query('body > p')
       
  9770     _splitQueries: function(selector, node) {
       
  9771         if (selector.indexOf(',') > -1) {
       
  9772             selector = Y.Selector._replaceCommas(selector);
       
  9773         }
       
  9774 
       
  9775         var groups = selector.split('\uE007'), // split on replaced comma token
       
  9776             queries = [],
       
  9777             prefix = '',
       
  9778             id,
       
  9779             i,
       
  9780             len;
       
  9781 
       
  9782         if (node) {
       
  9783             // enforce for element scoping
       
  9784             if (node.nodeType === 1) { // Elements only
       
  9785                 id = Y.Selector._escapeId(Y.DOM.getId(node));
       
  9786 
       
  9787                 if (!id) {
       
  9788                     id = Y.guid();
       
  9789                     Y.DOM.setId(node, id);
       
  9790                 }
       
  9791             
       
  9792                 prefix = '[id="' + id + '"] ';
       
  9793             }
       
  9794 
       
  9795             for (i = 0, len = groups.length; i < len; ++i) {
       
  9796                 selector =  prefix + groups[i];
       
  9797                 queries.push([selector, node]);
       
  9798             }
       
  9799         }
       
  9800 
       
  9801         return queries;
       
  9802     },
       
  9803 
       
  9804     _nativeQuery: function(selector, root, one) {
       
  9805         if (Y.UA.webkit && selector.indexOf(':checked') > -1 &&
       
  9806                 (Y.Selector.pseudos && Y.Selector.pseudos.checked)) { // webkit (chrome, safari) fails to pick up "selected"  with "checked"
       
  9807             return Y.Selector.query(selector, root, one, true); // redo with skipNative true to try brute query
       
  9808         }
       
  9809         try {
       
  9810             //Y.log('trying native query with: ' + selector, 'info', 'selector-native');
       
  9811             return root['querySelector' + (one ? '' : 'All')](selector);
       
  9812         } catch(e) { // fallback to brute if available
       
  9813             //Y.log('native query error; reverting to brute query with: ' + selector, 'info', 'selector-native');
       
  9814             return Y.Selector.query(selector, root, one, true); // redo with skipNative true
       
  9815         }
       
  9816     },
       
  9817 
       
  9818     filter: function(nodes, selector) {
       
  9819         var ret = [],
       
  9820             i, node;
       
  9821 
       
  9822         if (nodes && selector) {
       
  9823             for (i = 0; (node = nodes[i++]);) {
       
  9824                 if (Y.Selector.test(node, selector)) {
       
  9825                     ret[ret.length] = node;
       
  9826                 }
       
  9827             }
       
  9828         } else {
       
  9829             Y.log('invalid filter input (nodes: ' + nodes +
       
  9830                     ', selector: ' + selector + ')', 'warn', 'Selector');
       
  9831         }
       
  9832 
       
  9833         return ret;
       
  9834     },
       
  9835 
       
  9836     test: function(node, selector, root) {
       
  9837         var ret = false,
       
  9838             useFrag = false,
       
  9839             groups,
       
  9840             parent,
       
  9841             item,
       
  9842             items,
       
  9843             frag,
       
  9844             id,
       
  9845             i, j, group;
       
  9846 
       
  9847         if (node && node.tagName) { // only test HTMLElements
       
  9848 
       
  9849             if (typeof selector == 'function') { // test with function
       
  9850                 ret = selector.call(node, node);
       
  9851             } else { // test with query
       
  9852                 // we need a root if off-doc
       
  9853                 groups = selector.split(',');
       
  9854                 if (!root && !Y.DOM.inDoc(node)) {
       
  9855                     parent = node.parentNode;
       
  9856                     if (parent) { 
       
  9857                         root = parent;
       
  9858                     } else { // only use frag when no parent to query
       
  9859                         frag = node[OWNER_DOCUMENT].createDocumentFragment();
       
  9860                         frag.appendChild(node);
       
  9861                         root = frag;
       
  9862                         useFrag = true;
       
  9863                     }
       
  9864                 }
       
  9865                 root = root || node[OWNER_DOCUMENT];
       
  9866 
       
  9867                 id = Y.Selector._escapeId(Y.DOM.getId(node));
       
  9868                 if (!id) {
       
  9869                     id = Y.guid();
       
  9870                     Y.DOM.setId(node, id);
       
  9871                 }
       
  9872 
       
  9873                 for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
       
  9874                     group += '[id="' + id + '"]';
       
  9875                     items = Y.Selector.query(group, root);
       
  9876 
       
  9877                     for (j = 0; item = items[j++];) {
       
  9878                         if (item === node) {
       
  9879                             ret = true;
       
  9880                             break;
       
  9881                         }
       
  9882                     }
       
  9883                     if (ret) {
       
  9884                         break;
       
  9885                     }
       
  9886                 }
       
  9887 
       
  9888                 if (useFrag) { // cleanup
       
  9889                     frag.removeChild(node);
       
  9890                 }
       
  9891             };
       
  9892         }
       
  9893 
       
  9894         return ret;
       
  9895     },
       
  9896 
       
  9897     /**
       
  9898      * A convenience function to emulate Y.Node's aNode.ancestor(selector).
       
  9899      * @param {HTMLElement} element An HTMLElement to start the query from.
       
  9900      * @param {String} selector The CSS selector to test the node against.
       
  9901      * @return {HTMLElement} The ancestor node matching the selector, or null.
       
  9902      * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
       
  9903      * @static
       
  9904      * @method ancestor
       
  9905      */
       
  9906     ancestor: function (element, selector, testSelf) {
       
  9907         return Y.DOM.ancestor(element, function(n) {
       
  9908             return Y.Selector.test(n, selector);
       
  9909         }, testSelf);
       
  9910     },
       
  9911 
       
  9912     _parse: function(name, selector) {
       
  9913         return selector.match(Y.Selector._types[name].re);
       
  9914     },
       
  9915 
       
  9916     _replace: function(name, selector) {
       
  9917         var o = Y.Selector._types[name];
       
  9918         return selector.replace(o.re, o.token);
       
  9919     },
       
  9920 
       
  9921     _restore: function(name, selector, items) {
       
  9922         if (items) {
       
  9923             var token = Y.Selector._types[name].token,
       
  9924                 i, len;
       
  9925             for (i = 0, len = items.length; i < len; ++i) {
       
  9926                 selector = selector.replace(token, items[i]);
       
  9927             }
       
  9928         }
       
  9929         return selector;
       
  9930     }
       
  9931 };
       
  9932 
       
  9933 Y.mix(Y.Selector, Selector, true);
       
  9934 
       
  9935 })(Y);
       
  9936 
       
  9937 
       
  9938 }, '@VERSION@', {"requires": ["dom-base"]});
       
  9939 YUI.add('selector', function (Y, NAME) {
       
  9940 
       
  9941 
       
  9942 
       
  9943 }, '@VERSION@', {"requires": ["selector-native"]});
       
  9944 YUI.add('event-custom-base', function (Y, NAME) {
       
  9945 
       
  9946 /**
       
  9947  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
  9948  * events.
       
  9949  * @module event-custom
       
  9950  */
       
  9951 
       
  9952 Y.Env.evt = {
       
  9953     handles: {},
       
  9954     plugins: {}
       
  9955 };
       
  9956 
       
  9957 
       
  9958 /**
       
  9959  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
  9960  * events.
       
  9961  * @module event-custom
       
  9962  * @submodule event-custom-base
       
  9963  */
       
  9964 
       
  9965 /**
       
  9966  * Allows for the insertion of methods that are executed before or after
       
  9967  * a specified method
       
  9968  * @class Do
       
  9969  * @static
       
  9970  */
       
  9971 
       
  9972 var DO_BEFORE = 0,
       
  9973     DO_AFTER = 1,
       
  9974 
       
  9975 DO = {
       
  9976 
       
  9977     /**
       
  9978      * Cache of objects touched by the utility
       
  9979      * @property objs
       
  9980      * @static
       
  9981      * @deprecated Since 3.6.0. The `_yuiaop` property on the AOP'd object
       
  9982      * replaces the role of this property, but is considered to be private, and
       
  9983      * is only mentioned to provide a migration path.
       
  9984      *
       
  9985      * If you have a use case which warrants migration to the _yuiaop property,
       
  9986      * please file a ticket to let us know what it's used for and we can see if
       
  9987      * we need to expose hooks for that functionality more formally.
       
  9988      */
       
  9989     objs: null,
       
  9990 
       
  9991     /**
       
  9992      * <p>Execute the supplied method before the specified function.  Wrapping
       
  9993      * function may optionally return an instance of the following classes to
       
  9994      * further alter runtime behavior:</p>
       
  9995      * <dl>
       
  9996      *     <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
       
  9997      *         <dd>Immediatly stop execution and return
       
  9998      *         <code>returnValue</code>.  No other wrapping functions will be
       
  9999      *         executed.</dd>
       
 10000      *     <dt></code>Y.Do.AlterArgs(message, newArgArray)</code></dt>
       
 10001      *         <dd>Replace the arguments that the original function will be
       
 10002      *         called with.</dd>
       
 10003      *     <dt></code>Y.Do.Prevent(message)</code></dt>
       
 10004      *         <dd>Don't execute the wrapped function.  Other before phase
       
 10005      *         wrappers will be executed.</dd>
       
 10006      * </dl>
       
 10007      *
       
 10008      * @method before
       
 10009      * @param fn {Function} the function to execute
       
 10010      * @param obj the object hosting the method to displace
       
 10011      * @param sFn {string} the name of the method to displace
       
 10012      * @param c The execution context for fn
       
 10013      * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
       
 10014      * when the event fires.
       
 10015      * @return {string} handle for the subscription
       
 10016      * @static
       
 10017      */
       
 10018     before: function(fn, obj, sFn, c) {
       
 10019         // Y.log('Do before: ' + sFn, 'info', 'event');
       
 10020         var f = fn, a;
       
 10021         if (c) {
       
 10022             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
 10023             f = Y.rbind.apply(Y, a);
       
 10024         }
       
 10025 
       
 10026         return this._inject(DO_BEFORE, f, obj, sFn);
       
 10027     },
       
 10028 
       
 10029     /**
       
 10030      * <p>Execute the supplied method after the specified function.  Wrapping
       
 10031      * function may optionally return an instance of the following classes to
       
 10032      * further alter runtime behavior:</p>
       
 10033      * <dl>
       
 10034      *     <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
       
 10035      *         <dd>Immediatly stop execution and return
       
 10036      *         <code>returnValue</code>.  No other wrapping functions will be
       
 10037      *         executed.</dd>
       
 10038      *     <dt></code>Y.Do.AlterReturn(message, returnValue)</code></dt>
       
 10039      *         <dd>Return <code>returnValue</code> instead of the wrapped
       
 10040      *         method's original return value.  This can be further altered by
       
 10041      *         other after phase wrappers.</dd>
       
 10042      * </dl>
       
 10043      *
       
 10044      * <p>The static properties <code>Y.Do.originalRetVal</code> and
       
 10045      * <code>Y.Do.currentRetVal</code> will be populated for reference.</p>
       
 10046      *
       
 10047      * @method after
       
 10048      * @param fn {Function} the function to execute
       
 10049      * @param obj the object hosting the method to displace
       
 10050      * @param sFn {string} the name of the method to displace
       
 10051      * @param c The execution context for fn
       
 10052      * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
       
 10053      * @return {string} handle for the subscription
       
 10054      * @static
       
 10055      */
       
 10056     after: function(fn, obj, sFn, c) {
       
 10057         var f = fn, a;
       
 10058         if (c) {
       
 10059             a = [fn, c].concat(Y.Array(arguments, 4, true));
       
 10060             f = Y.rbind.apply(Y, a);
       
 10061         }
       
 10062 
       
 10063         return this._inject(DO_AFTER, f, obj, sFn);
       
 10064     },
       
 10065 
       
 10066     /**
       
 10067      * Execute the supplied method before or after the specified function.
       
 10068      * Used by <code>before</code> and <code>after</code>.
       
 10069      *
       
 10070      * @method _inject
       
 10071      * @param when {string} before or after
       
 10072      * @param fn {Function} the function to execute
       
 10073      * @param obj the object hosting the method to displace
       
 10074      * @param sFn {string} the name of the method to displace
       
 10075      * @param c The execution context for fn
       
 10076      * @return {string} handle for the subscription
       
 10077      * @private
       
 10078      * @static
       
 10079      */
       
 10080     _inject: function(when, fn, obj, sFn) {
       
 10081         // object id
       
 10082         var id = Y.stamp(obj), o, sid;
       
 10083 
       
 10084         if (!obj._yuiaop) {
       
 10085             // create a map entry for the obj if it doesn't exist, to hold overridden methods
       
 10086             obj._yuiaop = {};
       
 10087         }
       
 10088 
       
 10089         o = obj._yuiaop;
       
 10090 
       
 10091         if (!o[sFn]) {
       
 10092             // create a map entry for the method if it doesn't exist
       
 10093             o[sFn] = new Y.Do.Method(obj, sFn);
       
 10094 
       
 10095             // re-route the method to our wrapper
       
 10096             obj[sFn] = function() {
       
 10097                 return o[sFn].exec.apply(o[sFn], arguments);
       
 10098             };
       
 10099         }
       
 10100 
       
 10101         // subscriber id
       
 10102         sid = id + Y.stamp(fn) + sFn;
       
 10103 
       
 10104         // register the callback
       
 10105         o[sFn].register(sid, fn, when);
       
 10106 
       
 10107         return new Y.EventHandle(o[sFn], sid);
       
 10108     },
       
 10109 
       
 10110     /**
       
 10111      * Detach a before or after subscription.
       
 10112      *
       
 10113      * @method detach
       
 10114      * @param handle {string} the subscription handle
       
 10115      * @static
       
 10116      */
       
 10117     detach: function(handle) {
       
 10118         if (handle.detach) {
       
 10119             handle.detach();
       
 10120         }
       
 10121     }
       
 10122 };
       
 10123 
       
 10124 Y.Do = DO;
       
 10125 
       
 10126 //////////////////////////////////////////////////////////////////////////
       
 10127 
       
 10128 /**
       
 10129  * Contains the return value from the wrapped method, accessible
       
 10130  * by 'after' event listeners.
       
 10131  *
       
 10132  * @property originalRetVal
       
 10133  * @static
       
 10134  * @since 3.2.0
       
 10135  */
       
 10136 
       
 10137 /**
       
 10138  * Contains the current state of the return value, consumable by
       
 10139  * 'after' event listeners, and updated if an after subscriber
       
 10140  * changes the return value generated by the wrapped function.
       
 10141  *
       
 10142  * @property currentRetVal
       
 10143  * @static
       
 10144  * @since 3.2.0
       
 10145  */
       
 10146 
       
 10147 //////////////////////////////////////////////////////////////////////////
       
 10148 
       
 10149 /**
       
 10150  * Wrapper for a displaced method with aop enabled
       
 10151  * @class Do.Method
       
 10152  * @constructor
       
 10153  * @param obj The object to operate on
       
 10154  * @param sFn The name of the method to displace
       
 10155  */
       
 10156 DO.Method = function(obj, sFn) {
       
 10157     this.obj = obj;
       
 10158     this.methodName = sFn;
       
 10159     this.method = obj[sFn];
       
 10160     this.before = {};
       
 10161     this.after = {};
       
 10162 };
       
 10163 
       
 10164 /**
       
 10165  * Register a aop subscriber
       
 10166  * @method register
       
 10167  * @param sid {string} the subscriber id
       
 10168  * @param fn {Function} the function to execute
       
 10169  * @param when {string} when to execute the function
       
 10170  */
       
 10171 DO.Method.prototype.register = function (sid, fn, when) {
       
 10172     if (when) {
       
 10173         this.after[sid] = fn;
       
 10174     } else {
       
 10175         this.before[sid] = fn;
       
 10176     }
       
 10177 };
       
 10178 
       
 10179 /**
       
 10180  * Unregister a aop subscriber
       
 10181  * @method delete
       
 10182  * @param sid {string} the subscriber id
       
 10183  * @param fn {Function} the function to execute
       
 10184  * @param when {string} when to execute the function
       
 10185  */
       
 10186 DO.Method.prototype._delete = function (sid) {
       
 10187     // Y.log('Y.Do._delete: ' + sid, 'info', 'Event');
       
 10188     delete this.before[sid];
       
 10189     delete this.after[sid];
       
 10190 };
       
 10191 
       
 10192 /**
       
 10193  * <p>Execute the wrapped method.  All arguments are passed into the wrapping
       
 10194  * functions.  If any of the before wrappers return an instance of
       
 10195  * <code>Y.Do.Halt</code> or <code>Y.Do.Prevent</code>, neither the wrapped
       
 10196  * function nor any after phase subscribers will be executed.</p>
       
 10197  *
       
 10198  * <p>The return value will be the return value of the wrapped function or one
       
 10199  * provided by a wrapper function via an instance of <code>Y.Do.Halt</code> or
       
 10200  * <code>Y.Do.AlterReturn</code>.
       
 10201  *
       
 10202  * @method exec
       
 10203  * @param arg* {any} Arguments are passed to the wrapping and wrapped functions
       
 10204  * @return {any} Return value of wrapped function unless overwritten (see above)
       
 10205  */
       
 10206 DO.Method.prototype.exec = function () {
       
 10207 
       
 10208     var args = Y.Array(arguments, 0, true),
       
 10209         i, ret, newRet,
       
 10210         bf = this.before,
       
 10211         af = this.after,
       
 10212         prevented = false;
       
 10213 
       
 10214     // execute before
       
 10215     for (i in bf) {
       
 10216         if (bf.hasOwnProperty(i)) {
       
 10217             ret = bf[i].apply(this.obj, args);
       
 10218             if (ret) {
       
 10219                 switch (ret.constructor) {
       
 10220                     case DO.Halt:
       
 10221                         return ret.retVal;
       
 10222                     case DO.AlterArgs:
       
 10223                         args = ret.newArgs;
       
 10224                         break;
       
 10225                     case DO.Prevent:
       
 10226                         prevented = true;
       
 10227                         break;
       
 10228                     default:
       
 10229                 }
       
 10230             }
       
 10231         }
       
 10232     }
       
 10233 
       
 10234     // execute method
       
 10235     if (!prevented) {
       
 10236         ret = this.method.apply(this.obj, args);
       
 10237     }
       
 10238 
       
 10239     DO.originalRetVal = ret;
       
 10240     DO.currentRetVal = ret;
       
 10241 
       
 10242     // execute after methods.
       
 10243     for (i in af) {
       
 10244         if (af.hasOwnProperty(i)) {
       
 10245             newRet = af[i].apply(this.obj, args);
       
 10246             // Stop processing if a Halt object is returned
       
 10247             if (newRet && newRet.constructor === DO.Halt) {
       
 10248                 return newRet.retVal;
       
 10249             // Check for a new return value
       
 10250             } else if (newRet && newRet.constructor === DO.AlterReturn) {
       
 10251                 ret = newRet.newRetVal;
       
 10252                 // Update the static retval state
       
 10253                 DO.currentRetVal = ret;
       
 10254             }
       
 10255         }
       
 10256     }
       
 10257 
       
 10258     return ret;
       
 10259 };
       
 10260 
       
 10261 //////////////////////////////////////////////////////////////////////////
       
 10262 
       
 10263 /**
       
 10264  * Return an AlterArgs object when you want to change the arguments that
       
 10265  * were passed into the function.  Useful for Do.before subscribers.  An
       
 10266  * example would be a service that scrubs out illegal characters prior to
       
 10267  * executing the core business logic.
       
 10268  * @class Do.AlterArgs
       
 10269  * @constructor
       
 10270  * @param msg {String} (optional) Explanation of the altered return value
       
 10271  * @param newArgs {Array} Call parameters to be used for the original method
       
 10272  *                        instead of the arguments originally passed in.
       
 10273  */
       
 10274 DO.AlterArgs = function(msg, newArgs) {
       
 10275     this.msg = msg;
       
 10276     this.newArgs = newArgs;
       
 10277 };
       
 10278 
       
 10279 /**
       
 10280  * Return an AlterReturn object when you want to change the result returned
       
 10281  * from the core method to the caller.  Useful for Do.after subscribers.
       
 10282  * @class Do.AlterReturn
       
 10283  * @constructor
       
 10284  * @param msg {String} (optional) Explanation of the altered return value
       
 10285  * @param newRetVal {any} Return value passed to code that invoked the wrapped
       
 10286  *                      function.
       
 10287  */
       
 10288 DO.AlterReturn = function(msg, newRetVal) {
       
 10289     this.msg = msg;
       
 10290     this.newRetVal = newRetVal;
       
 10291 };
       
 10292 
       
 10293 /**
       
 10294  * Return a Halt object when you want to terminate the execution
       
 10295  * of all subsequent subscribers as well as the wrapped method
       
 10296  * if it has not exectued yet.  Useful for Do.before subscribers.
       
 10297  * @class Do.Halt
       
 10298  * @constructor
       
 10299  * @param msg {String} (optional) Explanation of why the termination was done
       
 10300  * @param retVal {any} Return value passed to code that invoked the wrapped
       
 10301  *                      function.
       
 10302  */
       
 10303 DO.Halt = function(msg, retVal) {
       
 10304     this.msg = msg;
       
 10305     this.retVal = retVal;
       
 10306 };
       
 10307 
       
 10308 /**
       
 10309  * Return a Prevent object when you want to prevent the wrapped function
       
 10310  * from executing, but want the remaining listeners to execute.  Useful
       
 10311  * for Do.before subscribers.
       
 10312  * @class Do.Prevent
       
 10313  * @constructor
       
 10314  * @param msg {String} (optional) Explanation of why the termination was done
       
 10315  */
       
 10316 DO.Prevent = function(msg) {
       
 10317     this.msg = msg;
       
 10318 };
       
 10319 
       
 10320 /**
       
 10321  * Return an Error object when you want to terminate the execution
       
 10322  * of all subsequent method calls.
       
 10323  * @class Do.Error
       
 10324  * @constructor
       
 10325  * @param msg {String} (optional) Explanation of the altered return value
       
 10326  * @param retVal {any} Return value passed to code that invoked the wrapped
       
 10327  *                      function.
       
 10328  * @deprecated use Y.Do.Halt or Y.Do.Prevent
       
 10329  */
       
 10330 DO.Error = DO.Halt;
       
 10331 
       
 10332 
       
 10333 //////////////////////////////////////////////////////////////////////////
       
 10334 
       
 10335 /**
       
 10336  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 10337  * events.
       
 10338  * @module event-custom
       
 10339  * @submodule event-custom-base
       
 10340  */
       
 10341 
       
 10342 
       
 10343 // var onsubscribeType = "_event:onsub",
       
 10344 var YArray = Y.Array,
       
 10345 
       
 10346     AFTER = 'after',
       
 10347     CONFIGS = [
       
 10348         'broadcast',
       
 10349         'monitored',
       
 10350         'bubbles',
       
 10351         'context',
       
 10352         'contextFn',
       
 10353         'currentTarget',
       
 10354         'defaultFn',
       
 10355         'defaultTargetOnly',
       
 10356         'details',
       
 10357         'emitFacade',
       
 10358         'fireOnce',
       
 10359         'async',
       
 10360         'host',
       
 10361         'preventable',
       
 10362         'preventedFn',
       
 10363         'queuable',
       
 10364         'silent',
       
 10365         'stoppedFn',
       
 10366         'target',
       
 10367         'type'
       
 10368     ],
       
 10369 
       
 10370     CONFIGS_HASH = YArray.hash(CONFIGS),
       
 10371 
       
 10372     nativeSlice = Array.prototype.slice,
       
 10373 
       
 10374     YUI3_SIGNATURE = 9,
       
 10375     YUI_LOG = 'yui:log',
       
 10376 
       
 10377     mixConfigs = function(r, s, ov) {
       
 10378         var p;
       
 10379 
       
 10380         for (p in s) {
       
 10381             if (CONFIGS_HASH[p] && (ov || !(p in r))) {
       
 10382                 r[p] = s[p];
       
 10383             }
       
 10384         }
       
 10385 
       
 10386         return r;
       
 10387     };
       
 10388 
       
 10389 /**
       
 10390  * The CustomEvent class lets you define events for your application
       
 10391  * that can be subscribed to by one or more independent component.
       
 10392  *
       
 10393  * @param {String} type The type of event, which is passed to the callback
       
 10394  * when the event fires.
       
 10395  * @param {object} defaults configuration object.
       
 10396  * @class CustomEvent
       
 10397  * @constructor
       
 10398  */
       
 10399 
       
 10400  /**
       
 10401  * The type of event, returned to subscribers when the event fires
       
 10402  * @property type
       
 10403  * @type string
       
 10404  */
       
 10405 
       
 10406 /**
       
 10407  * By default all custom events are logged in the debug build, set silent
       
 10408  * to true to disable debug outpu for this event.
       
 10409  * @property silent
       
 10410  * @type boolean
       
 10411  */
       
 10412 
       
 10413 Y.CustomEvent = function(type, defaults) {
       
 10414 
       
 10415     this._kds = Y.CustomEvent.keepDeprecatedSubs;
       
 10416 
       
 10417     this.id = Y.guid();
       
 10418 
       
 10419     this.type = type;
       
 10420     this.silent = this.logSystem = (type === YUI_LOG);
       
 10421 
       
 10422     if (this._kds) {
       
 10423         /**
       
 10424          * The subscribers to this event
       
 10425          * @property subscribers
       
 10426          * @type Subscriber {}
       
 10427          * @deprecated
       
 10428          */
       
 10429 
       
 10430         /**
       
 10431          * 'After' subscribers
       
 10432          * @property afters
       
 10433          * @type Subscriber {}
       
 10434          * @deprecated
       
 10435          */
       
 10436         this.subscribers = {};
       
 10437         this.afters = {};
       
 10438     }
       
 10439 
       
 10440     if (defaults) {
       
 10441         mixConfigs(this, defaults, true);
       
 10442     }
       
 10443 };
       
 10444 
       
 10445 /**
       
 10446  * Static flag to enable population of the <a href="#property_subscribers">`subscribers`</a>
       
 10447  * and  <a href="#property_subscribers">`afters`</a> properties held on a `CustomEvent` instance.
       
 10448  *
       
 10449  * These properties were changed to private properties (`_subscribers` and `_afters`), and
       
 10450  * converted from objects to arrays for performance reasons.
       
 10451  *
       
 10452  * Setting this property to true will populate the deprecated `subscribers` and `afters`
       
 10453  * properties for people who may be using them (which is expected to be rare). There will
       
 10454  * be a performance hit, compared to the new array based implementation.
       
 10455  *
       
 10456  * If you are using these deprecated properties for a use case which the public API
       
 10457  * does not support, please file an enhancement request, and we can provide an alternate
       
 10458  * public implementation which doesn't have the performance cost required to maintiain the
       
 10459  * properties as objects.
       
 10460  *
       
 10461  * @property keepDeprecatedSubs
       
 10462  * @static
       
 10463  * @for CustomEvent
       
 10464  * @type boolean
       
 10465  * @default false
       
 10466  * @deprecated
       
 10467  */
       
 10468 Y.CustomEvent.keepDeprecatedSubs = false;
       
 10469 
       
 10470 Y.CustomEvent.mixConfigs = mixConfigs;
       
 10471 
       
 10472 Y.CustomEvent.prototype = {
       
 10473 
       
 10474     constructor: Y.CustomEvent,
       
 10475 
       
 10476     /**
       
 10477      * Monitor when an event is attached or detached.
       
 10478      *
       
 10479      * @property monitored
       
 10480      * @type boolean
       
 10481      */
       
 10482 
       
 10483     /**
       
 10484      * If 0, this event does not broadcast.  If 1, the YUI instance is notified
       
 10485      * every time this event fires.  If 2, the YUI instance and the YUI global
       
 10486      * (if event is enabled on the global) are notified every time this event
       
 10487      * fires.
       
 10488      * @property broadcast
       
 10489      * @type int
       
 10490      */
       
 10491 
       
 10492     /**
       
 10493      * Specifies whether this event should be queued when the host is actively
       
 10494      * processing an event.  This will effect exectution order of the callbacks
       
 10495      * for the various events.
       
 10496      * @property queuable
       
 10497      * @type boolean
       
 10498      * @default false
       
 10499      */
       
 10500 
       
 10501     /**
       
 10502      * This event has fired if true
       
 10503      *
       
 10504      * @property fired
       
 10505      * @type boolean
       
 10506      * @default false;
       
 10507      */
       
 10508 
       
 10509     /**
       
 10510      * An array containing the arguments the custom event
       
 10511      * was last fired with.
       
 10512      * @property firedWith
       
 10513      * @type Array
       
 10514      */
       
 10515 
       
 10516     /**
       
 10517      * This event should only fire one time if true, and if
       
 10518      * it has fired, any new subscribers should be notified
       
 10519      * immediately.
       
 10520      *
       
 10521      * @property fireOnce
       
 10522      * @type boolean
       
 10523      * @default false;
       
 10524      */
       
 10525 
       
 10526     /**
       
 10527      * fireOnce listeners will fire syncronously unless async
       
 10528      * is set to true
       
 10529      * @property async
       
 10530      * @type boolean
       
 10531      * @default false
       
 10532      */
       
 10533 
       
 10534     /**
       
 10535      * Flag for stopPropagation that is modified during fire()
       
 10536      * 1 means to stop propagation to bubble targets.  2 means
       
 10537      * to also stop additional subscribers on this target.
       
 10538      * @property stopped
       
 10539      * @type int
       
 10540      */
       
 10541 
       
 10542     /**
       
 10543      * Flag for preventDefault that is modified during fire().
       
 10544      * if it is not 0, the default behavior for this event
       
 10545      * @property prevented
       
 10546      * @type int
       
 10547      */
       
 10548 
       
 10549     /**
       
 10550      * Specifies the host for this custom event.  This is used
       
 10551      * to enable event bubbling
       
 10552      * @property host
       
 10553      * @type EventTarget
       
 10554      */
       
 10555 
       
 10556     /**
       
 10557      * The default function to execute after event listeners
       
 10558      * have fire, but only if the default action was not
       
 10559      * prevented.
       
 10560      * @property defaultFn
       
 10561      * @type Function
       
 10562      */
       
 10563 
       
 10564     /**
       
 10565      * The function to execute if a subscriber calls
       
 10566      * stopPropagation or stopImmediatePropagation
       
 10567      * @property stoppedFn
       
 10568      * @type Function
       
 10569      */
       
 10570 
       
 10571     /**
       
 10572      * The function to execute if a subscriber calls
       
 10573      * preventDefault
       
 10574      * @property preventedFn
       
 10575      * @type Function
       
 10576      */
       
 10577 
       
 10578     /**
       
 10579      * The subscribers to this event
       
 10580      * @property _subscribers
       
 10581      * @type Subscriber []
       
 10582      * @private
       
 10583      */
       
 10584 
       
 10585     /**
       
 10586      * 'After' subscribers
       
 10587      * @property _afters
       
 10588      * @type Subscriber []
       
 10589      * @private
       
 10590      */
       
 10591 
       
 10592     /**
       
 10593      * If set to true, the custom event will deliver an EventFacade object
       
 10594      * that is similar to a DOM event object.
       
 10595      * @property emitFacade
       
 10596      * @type boolean
       
 10597      * @default false
       
 10598      */
       
 10599 
       
 10600     /**
       
 10601      * Supports multiple options for listener signatures in order to
       
 10602      * port YUI 2 apps.
       
 10603      * @property signature
       
 10604      * @type int
       
 10605      * @default 9
       
 10606      */
       
 10607     signature : YUI3_SIGNATURE,
       
 10608 
       
 10609     /**
       
 10610      * The context the the event will fire from by default.  Defaults to the YUI
       
 10611      * instance.
       
 10612      * @property context
       
 10613      * @type object
       
 10614      */
       
 10615     context : Y,
       
 10616 
       
 10617     /**
       
 10618      * Specifies whether or not this event's default function
       
 10619      * can be cancelled by a subscriber by executing preventDefault()
       
 10620      * on the event facade
       
 10621      * @property preventable
       
 10622      * @type boolean
       
 10623      * @default true
       
 10624      */
       
 10625     preventable : true,
       
 10626 
       
 10627     /**
       
 10628      * Specifies whether or not a subscriber can stop the event propagation
       
 10629      * via stopPropagation(), stopImmediatePropagation(), or halt()
       
 10630      *
       
 10631      * Events can only bubble if emitFacade is true.
       
 10632      *
       
 10633      * @property bubbles
       
 10634      * @type boolean
       
 10635      * @default true
       
 10636      */
       
 10637     bubbles : true,
       
 10638 
       
 10639     /**
       
 10640      * Returns the number of subscribers for this event as the sum of the on()
       
 10641      * subscribers and after() subscribers.
       
 10642      *
       
 10643      * @method hasSubs
       
 10644      * @return Number
       
 10645      */
       
 10646     hasSubs: function(when) {
       
 10647         var s = 0,
       
 10648             a = 0,
       
 10649             subs = this._subscribers,
       
 10650             afters = this._afters,
       
 10651             sib = this.sibling;
       
 10652 
       
 10653         if (subs) {
       
 10654             s = subs.length;
       
 10655         }
       
 10656 
       
 10657         if (afters) {
       
 10658             a = afters.length;
       
 10659         }
       
 10660 
       
 10661         if (sib) {
       
 10662             subs = sib._subscribers;
       
 10663             afters = sib._afters;
       
 10664 
       
 10665             if (subs) {
       
 10666                 s += subs.length;
       
 10667             }
       
 10668 
       
 10669             if (afters) {
       
 10670                 a += afters.length;
       
 10671             }
       
 10672         }
       
 10673 
       
 10674         if (when) {
       
 10675             return (when === 'after') ? a : s;
       
 10676         }
       
 10677 
       
 10678         return (s + a);
       
 10679     },
       
 10680 
       
 10681     /**
       
 10682      * Monitor the event state for the subscribed event.  The first parameter
       
 10683      * is what should be monitored, the rest are the normal parameters when
       
 10684      * subscribing to an event.
       
 10685      * @method monitor
       
 10686      * @param what {string} what to monitor ('detach', 'attach', 'publish').
       
 10687      * @return {EventHandle} return value from the monitor event subscription.
       
 10688      */
       
 10689     monitor: function(what) {
       
 10690         this.monitored = true;
       
 10691         var type = this.id + '|' + this.type + '_' + what,
       
 10692             args = nativeSlice.call(arguments, 0);
       
 10693         args[0] = type;
       
 10694         return this.host.on.apply(this.host, args);
       
 10695     },
       
 10696 
       
 10697     /**
       
 10698      * Get all of the subscribers to this event and any sibling event
       
 10699      * @method getSubs
       
 10700      * @return {Array} first item is the on subscribers, second the after.
       
 10701      */
       
 10702     getSubs: function() {
       
 10703 
       
 10704         var sibling = this.sibling,
       
 10705             subs = this._subscribers,
       
 10706             afters = this._afters,
       
 10707             siblingSubs,
       
 10708             siblingAfters;
       
 10709 
       
 10710         if (sibling) {
       
 10711             siblingSubs = sibling._subscribers;
       
 10712             siblingAfters = sibling._afters;
       
 10713         }
       
 10714 
       
 10715         if (siblingSubs) {
       
 10716             if (subs) {
       
 10717                 subs = subs.concat(siblingSubs);
       
 10718             } else {
       
 10719                 subs = siblingSubs.concat();
       
 10720             }
       
 10721         } else {
       
 10722             if (subs) {
       
 10723                 subs = subs.concat();
       
 10724             } else {
       
 10725                 subs = [];
       
 10726             }
       
 10727         }
       
 10728 
       
 10729         if (siblingAfters) {
       
 10730             if (afters) {
       
 10731                 afters = afters.concat(siblingAfters);
       
 10732             } else {
       
 10733                 afters = siblingAfters.concat();
       
 10734             }
       
 10735         } else {
       
 10736             if (afters) {
       
 10737                 afters = afters.concat();
       
 10738             } else {
       
 10739                 afters = [];
       
 10740             }
       
 10741         }
       
 10742 
       
 10743         return [subs, afters];
       
 10744     },
       
 10745 
       
 10746     /**
       
 10747      * Apply configuration properties.  Only applies the CONFIG whitelist
       
 10748      * @method applyConfig
       
 10749      * @param o hash of properties to apply.
       
 10750      * @param force {boolean} if true, properties that exist on the event
       
 10751      * will be overwritten.
       
 10752      */
       
 10753     applyConfig: function(o, force) {
       
 10754         mixConfigs(this, o, force);
       
 10755     },
       
 10756 
       
 10757     /**
       
 10758      * Create the Subscription for subscribing function, context, and bound
       
 10759      * arguments.  If this is a fireOnce event, the subscriber is immediately
       
 10760      * notified.
       
 10761      *
       
 10762      * @method _on
       
 10763      * @param fn {Function} Subscription callback
       
 10764      * @param [context] {Object} Override `this` in the callback
       
 10765      * @param [args] {Array} bound arguments that will be passed to the callback after the arguments generated by fire()
       
 10766      * @param [when] {String} "after" to slot into after subscribers
       
 10767      * @return {EventHandle}
       
 10768      * @protected
       
 10769      */
       
 10770     _on: function(fn, context, args, when) {
       
 10771 
       
 10772         if (!fn) { this.log('Invalid callback for CE: ' + this.type); }
       
 10773 
       
 10774         var s = new Y.Subscriber(fn, context, args, when);
       
 10775 
       
 10776         if (this.fireOnce && this.fired) {
       
 10777             if (this.async) {
       
 10778                 setTimeout(Y.bind(this._notify, this, s, this.firedWith), 0);
       
 10779             } else {
       
 10780                 this._notify(s, this.firedWith);
       
 10781             }
       
 10782         }
       
 10783 
       
 10784         if (when === AFTER) {
       
 10785             if (!this._afters) {
       
 10786                 this._afters = [];
       
 10787                 this._hasAfters = true;
       
 10788             }
       
 10789             this._afters.push(s);
       
 10790         } else {
       
 10791             if (!this._subscribers) {
       
 10792                 this._subscribers = [];
       
 10793                 this._hasSubs = true;
       
 10794             }
       
 10795             this._subscribers.push(s);
       
 10796         }
       
 10797 
       
 10798         if (this._kds) {
       
 10799             if (when === AFTER) {
       
 10800                 this.afters[s.id] = s;
       
 10801             } else {
       
 10802                 this.subscribers[s.id] = s;
       
 10803             }
       
 10804         }
       
 10805 
       
 10806         return new Y.EventHandle(this, s);
       
 10807     },
       
 10808 
       
 10809     /**
       
 10810      * Listen for this event
       
 10811      * @method subscribe
       
 10812      * @param {Function} fn The function to execute.
       
 10813      * @return {EventHandle} Unsubscribe handle.
       
 10814      * @deprecated use on.
       
 10815      */
       
 10816     subscribe: function(fn, context) {
       
 10817         Y.log('ce.subscribe deprecated, use "on"', 'warn', 'deprecated');
       
 10818         var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null;
       
 10819         return this._on(fn, context, a, true);
       
 10820     },
       
 10821 
       
 10822     /**
       
 10823      * Listen for this event
       
 10824      * @method on
       
 10825      * @param {Function} fn The function to execute.
       
 10826      * @param {object} context optional execution context.
       
 10827      * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
       
 10828      * when the event fires.
       
 10829      * @return {EventHandle} An object with a detach method to detch the handler(s).
       
 10830      */
       
 10831     on: function(fn, context) {
       
 10832         var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null;
       
 10833 
       
 10834         if (this.monitored && this.host) {
       
 10835             this.host._monitor('attach', this, {
       
 10836                 args: arguments
       
 10837             });
       
 10838         }
       
 10839         return this._on(fn, context, a, true);
       
 10840     },
       
 10841 
       
 10842     /**
       
 10843      * Listen for this event after the normal subscribers have been notified and
       
 10844      * the default behavior has been applied.  If a normal subscriber prevents the
       
 10845      * default behavior, it also prevents after listeners from firing.
       
 10846      * @method after
       
 10847      * @param {Function} fn The function to execute.
       
 10848      * @param {object} context optional execution context.
       
 10849      * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
       
 10850      * when the event fires.
       
 10851      * @return {EventHandle} handle Unsubscribe handle.
       
 10852      */
       
 10853     after: function(fn, context) {
       
 10854         var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null;
       
 10855         return this._on(fn, context, a, AFTER);
       
 10856     },
       
 10857 
       
 10858     /**
       
 10859      * Detach listeners.
       
 10860      * @method detach
       
 10861      * @param {Function} fn  The subscribed function to remove, if not supplied
       
 10862      *                       all will be removed.
       
 10863      * @param {Object}   context The context object passed to subscribe.
       
 10864      * @return {int} returns the number of subscribers unsubscribed.
       
 10865      */
       
 10866     detach: function(fn, context) {
       
 10867         // unsubscribe handle
       
 10868         if (fn && fn.detach) {
       
 10869             return fn.detach();
       
 10870         }
       
 10871 
       
 10872         var i, s,
       
 10873             found = 0,
       
 10874             subs = this._subscribers,
       
 10875             afters = this._afters;
       
 10876 
       
 10877         if (subs) {
       
 10878             for (i = subs.length; i >= 0; i--) {
       
 10879                 s = subs[i];
       
 10880                 if (s && (!fn || fn === s.fn)) {
       
 10881                     this._delete(s, subs, i);
       
 10882                     found++;
       
 10883                 }
       
 10884             }
       
 10885         }
       
 10886 
       
 10887         if (afters) {
       
 10888             for (i = afters.length; i >= 0; i--) {
       
 10889                 s = afters[i];
       
 10890                 if (s && (!fn || fn === s.fn)) {
       
 10891                     this._delete(s, afters, i);
       
 10892                     found++;
       
 10893                 }
       
 10894             }
       
 10895         }
       
 10896 
       
 10897         return found;
       
 10898     },
       
 10899 
       
 10900     /**
       
 10901      * Detach listeners.
       
 10902      * @method unsubscribe
       
 10903      * @param {Function} fn  The subscribed function to remove, if not supplied
       
 10904      *                       all will be removed.
       
 10905      * @param {Object}   context The context object passed to subscribe.
       
 10906      * @return {int|undefined} returns the number of subscribers unsubscribed.
       
 10907      * @deprecated use detach.
       
 10908      */
       
 10909     unsubscribe: function() {
       
 10910         return this.detach.apply(this, arguments);
       
 10911     },
       
 10912 
       
 10913     /**
       
 10914      * Notify a single subscriber
       
 10915      * @method _notify
       
 10916      * @param {Subscriber} s the subscriber.
       
 10917      * @param {Array} args the arguments array to apply to the listener.
       
 10918      * @protected
       
 10919      */
       
 10920     _notify: function(s, args, ef) {
       
 10921 
       
 10922         this.log(this.type + '->' + 'sub: ' + s.id);
       
 10923 
       
 10924         var ret;
       
 10925 
       
 10926         ret = s.notify(args, this);
       
 10927 
       
 10928         if (false === ret || this.stopped > 1) {
       
 10929             this.log(this.type + ' cancelled by subscriber');
       
 10930             return false;
       
 10931         }
       
 10932 
       
 10933         return true;
       
 10934     },
       
 10935 
       
 10936     /**
       
 10937      * Logger abstraction to centralize the application of the silent flag
       
 10938      * @method log
       
 10939      * @param {string} msg message to log.
       
 10940      * @param {string} cat log category.
       
 10941      */
       
 10942     log: function(msg, cat) {
       
 10943         if (!this.silent) { Y.log(this.id + ': ' + msg, cat || 'info', 'event'); }
       
 10944     },
       
 10945 
       
 10946     /**
       
 10947      * Notifies the subscribers.  The callback functions will be executed
       
 10948      * from the context specified when the event was created, and with the
       
 10949      * following parameters:
       
 10950      *   <ul>
       
 10951      *   <li>The type of event</li>
       
 10952      *   <li>All of the arguments fire() was executed with as an array</li>
       
 10953      *   <li>The custom object (if any) that was passed into the subscribe()
       
 10954      *       method</li>
       
 10955      *   </ul>
       
 10956      * @method fire
       
 10957      * @param {Object*} arguments an arbitrary set of parameters to pass to
       
 10958      *                            the handler.
       
 10959      * @return {boolean} false if one of the subscribers returned false,
       
 10960      *                   true otherwise.
       
 10961      *
       
 10962      */
       
 10963     fire: function() {
       
 10964 
       
 10965         // push is the fastest way to go from arguments to arrays
       
 10966         // for most browsers currently
       
 10967         // http://jsperf.com/push-vs-concat-vs-slice/2
       
 10968 
       
 10969         var args = [];
       
 10970         args.push.apply(args, arguments);
       
 10971 
       
 10972         return this._fire(args);
       
 10973     },
       
 10974 
       
 10975     /**
       
 10976      * Private internal implementation for `fire`, which is can be used directly by
       
 10977      * `EventTarget` and other event module classes which have already converted from
       
 10978      * an `arguments` list to an array, to avoid the repeated overhead.
       
 10979      *
       
 10980      * @method _fire
       
 10981      * @private
       
 10982      * @param {Array} args The array of arguments passed to be passed to handlers.
       
 10983      * @return {boolean} false if one of the subscribers returned false, true otherwise.
       
 10984      */
       
 10985     _fire: function(args) {
       
 10986 
       
 10987         if (this.fireOnce && this.fired) {
       
 10988             this.log('fireOnce event: ' + this.type + ' already fired');
       
 10989             return true;
       
 10990         } else {
       
 10991 
       
 10992             // this doesn't happen if the event isn't published
       
 10993             // this.host._monitor('fire', this.type, args);
       
 10994 
       
 10995             this.fired = true;
       
 10996 
       
 10997             if (this.fireOnce) {
       
 10998                 this.firedWith = args;
       
 10999             }
       
 11000 
       
 11001             if (this.emitFacade) {
       
 11002                 return this.fireComplex(args);
       
 11003             } else {
       
 11004                 return this.fireSimple(args);
       
 11005             }
       
 11006         }
       
 11007     },
       
 11008 
       
 11009     /**
       
 11010      * Set up for notifying subscribers of non-emitFacade events.
       
 11011      *
       
 11012      * @method fireSimple
       
 11013      * @param args {Array} Arguments passed to fire()
       
 11014      * @return Boolean false if a subscriber returned false
       
 11015      * @protected
       
 11016      */
       
 11017     fireSimple: function(args) {
       
 11018         this.stopped = 0;
       
 11019         this.prevented = 0;
       
 11020         if (this.hasSubs()) {
       
 11021             var subs = this.getSubs();
       
 11022             this._procSubs(subs[0], args);
       
 11023             this._procSubs(subs[1], args);
       
 11024         }
       
 11025         if (this.broadcast) {
       
 11026             this._broadcast(args);
       
 11027         }
       
 11028         return this.stopped ? false : true;
       
 11029     },
       
 11030 
       
 11031     // Requires the event-custom-complex module for full funcitonality.
       
 11032     fireComplex: function(args) {
       
 11033         this.log('Missing event-custom-complex needed to emit a facade for: ' + this.type);
       
 11034         args[0] = args[0] || {};
       
 11035         return this.fireSimple(args);
       
 11036     },
       
 11037 
       
 11038     /**
       
 11039      * Notifies a list of subscribers.
       
 11040      *
       
 11041      * @method _procSubs
       
 11042      * @param subs {Array} List of subscribers
       
 11043      * @param args {Array} Arguments passed to fire()
       
 11044      * @param ef {}
       
 11045      * @return Boolean false if a subscriber returns false or stops the event
       
 11046      *              propagation via e.stopPropagation(),
       
 11047      *              e.stopImmediatePropagation(), or e.halt()
       
 11048      * @private
       
 11049      */
       
 11050     _procSubs: function(subs, args, ef) {
       
 11051         var s, i, l;
       
 11052 
       
 11053         for (i = 0, l = subs.length; i < l; i++) {
       
 11054             s = subs[i];
       
 11055             if (s && s.fn) {
       
 11056                 if (false === this._notify(s, args, ef)) {
       
 11057                     this.stopped = 2;
       
 11058                 }
       
 11059                 if (this.stopped === 2) {
       
 11060                     return false;
       
 11061                 }
       
 11062             }
       
 11063         }
       
 11064 
       
 11065         return true;
       
 11066     },
       
 11067 
       
 11068     /**
       
 11069      * Notifies the YUI instance if the event is configured with broadcast = 1,
       
 11070      * and both the YUI instance and Y.Global if configured with broadcast = 2.
       
 11071      *
       
 11072      * @method _broadcast
       
 11073      * @param args {Array} Arguments sent to fire()
       
 11074      * @private
       
 11075      */
       
 11076     _broadcast: function(args) {
       
 11077         if (!this.stopped && this.broadcast) {
       
 11078 
       
 11079             var a = args.concat();
       
 11080             a.unshift(this.type);
       
 11081 
       
 11082             if (this.host !== Y) {
       
 11083                 Y.fire.apply(Y, a);
       
 11084             }
       
 11085 
       
 11086             if (this.broadcast === 2) {
       
 11087                 Y.Global.fire.apply(Y.Global, a);
       
 11088             }
       
 11089         }
       
 11090     },
       
 11091 
       
 11092     /**
       
 11093      * Removes all listeners
       
 11094      * @method unsubscribeAll
       
 11095      * @return {int} The number of listeners unsubscribed.
       
 11096      * @deprecated use detachAll.
       
 11097      */
       
 11098     unsubscribeAll: function() {
       
 11099         return this.detachAll.apply(this, arguments);
       
 11100     },
       
 11101 
       
 11102     /**
       
 11103      * Removes all listeners
       
 11104      * @method detachAll
       
 11105      * @return {int} The number of listeners unsubscribed.
       
 11106      */
       
 11107     detachAll: function() {
       
 11108         return this.detach();
       
 11109     },
       
 11110 
       
 11111     /**
       
 11112      * Deletes the subscriber from the internal store of on() and after()
       
 11113      * subscribers.
       
 11114      *
       
 11115      * @method _delete
       
 11116      * @param s subscriber object.
       
 11117      * @param subs (optional) on or after subscriber array
       
 11118      * @param index (optional) The index found.
       
 11119      * @private
       
 11120      */
       
 11121     _delete: function(s, subs, i) {
       
 11122         var when = s._when;
       
 11123 
       
 11124         if (!subs) {
       
 11125             subs = (when === AFTER) ? this._afters : this._subscribers;
       
 11126         }
       
 11127 
       
 11128         if (subs) {
       
 11129             i = YArray.indexOf(subs, s, 0);
       
 11130 
       
 11131             if (s && subs[i] === s) {
       
 11132                 subs.splice(i, 1);
       
 11133 
       
 11134                 if (subs.length === 0) {
       
 11135                     if (when === AFTER) {
       
 11136                         this._hasAfters = false;
       
 11137                     } else {
       
 11138                         this._hasSubs = false;
       
 11139                     }
       
 11140                 }
       
 11141             }
       
 11142         }
       
 11143 
       
 11144         if (this._kds) {
       
 11145             if (when === AFTER) {
       
 11146                 delete this.afters[s.id];
       
 11147             } else {
       
 11148                 delete this.subscribers[s.id];
       
 11149             }
       
 11150         }
       
 11151 
       
 11152         if (this.monitored && this.host) {
       
 11153             this.host._monitor('detach', this, {
       
 11154                 ce: this,
       
 11155                 sub: s
       
 11156             });
       
 11157         }
       
 11158 
       
 11159         if (s) {
       
 11160             s.deleted = true;
       
 11161         }
       
 11162     }
       
 11163 };
       
 11164 /**
       
 11165  * Stores the subscriber information to be used when the event fires.
       
 11166  * @param {Function} fn       The wrapped function to execute.
       
 11167  * @param {Object}   context  The value of the keyword 'this' in the listener.
       
 11168  * @param {Array} args*       0..n additional arguments to supply the listener.
       
 11169  *
       
 11170  * @class Subscriber
       
 11171  * @constructor
       
 11172  */
       
 11173 Y.Subscriber = function(fn, context, args, when) {
       
 11174 
       
 11175     /**
       
 11176      * The callback that will be execute when the event fires
       
 11177      * This is wrapped by Y.rbind if obj was supplied.
       
 11178      * @property fn
       
 11179      * @type Function
       
 11180      */
       
 11181     this.fn = fn;
       
 11182 
       
 11183     /**
       
 11184      * Optional 'this' keyword for the listener
       
 11185      * @property context
       
 11186      * @type Object
       
 11187      */
       
 11188     this.context = context;
       
 11189 
       
 11190     /**
       
 11191      * Unique subscriber id
       
 11192      * @property id
       
 11193      * @type String
       
 11194      */
       
 11195     this.id = Y.guid();
       
 11196 
       
 11197     /**
       
 11198      * Additional arguments to propagate to the subscriber
       
 11199      * @property args
       
 11200      * @type Array
       
 11201      */
       
 11202     this.args = args;
       
 11203 
       
 11204     this._when = when;
       
 11205 
       
 11206     /**
       
 11207      * Custom events for a given fire transaction.
       
 11208      * @property events
       
 11209      * @type {EventTarget}
       
 11210      */
       
 11211     // this.events = null;
       
 11212 
       
 11213     /**
       
 11214      * This listener only reacts to the event once
       
 11215      * @property once
       
 11216      */
       
 11217     // this.once = false;
       
 11218 
       
 11219 };
       
 11220 
       
 11221 Y.Subscriber.prototype = {
       
 11222     constructor: Y.Subscriber,
       
 11223 
       
 11224     _notify: function(c, args, ce) {
       
 11225         if (this.deleted && !this.postponed) {
       
 11226             if (this.postponed) {
       
 11227                 delete this.fn;
       
 11228                 delete this.context;
       
 11229             } else {
       
 11230                 delete this.postponed;
       
 11231                 return null;
       
 11232             }
       
 11233         }
       
 11234         var a = this.args, ret;
       
 11235         switch (ce.signature) {
       
 11236             case 0:
       
 11237                 ret = this.fn.call(c, ce.type, args, c);
       
 11238                 break;
       
 11239             case 1:
       
 11240                 ret = this.fn.call(c, args[0] || null, c);
       
 11241                 break;
       
 11242             default:
       
 11243                 if (a || args) {
       
 11244                     args = args || [];
       
 11245                     a = (a) ? args.concat(a) : args;
       
 11246                     ret = this.fn.apply(c, a);
       
 11247                 } else {
       
 11248                     ret = this.fn.call(c);
       
 11249                 }
       
 11250         }
       
 11251 
       
 11252         if (this.once) {
       
 11253             ce._delete(this);
       
 11254         }
       
 11255 
       
 11256         return ret;
       
 11257     },
       
 11258 
       
 11259     /**
       
 11260      * Executes the subscriber.
       
 11261      * @method notify
       
 11262      * @param args {Array} Arguments array for the subscriber.
       
 11263      * @param ce {CustomEvent} The custom event that sent the notification.
       
 11264      */
       
 11265     notify: function(args, ce) {
       
 11266         var c = this.context,
       
 11267             ret = true;
       
 11268 
       
 11269         if (!c) {
       
 11270             c = (ce.contextFn) ? ce.contextFn() : ce.context;
       
 11271         }
       
 11272 
       
 11273         // only catch errors if we will not re-throw them.
       
 11274         if (Y.config && Y.config.throwFail) {
       
 11275             ret = this._notify(c, args, ce);
       
 11276         } else {
       
 11277             try {
       
 11278                 ret = this._notify(c, args, ce);
       
 11279             } catch (e) {
       
 11280                 Y.error(this + ' failed: ' + e.message, e);
       
 11281             }
       
 11282         }
       
 11283 
       
 11284         return ret;
       
 11285     },
       
 11286 
       
 11287     /**
       
 11288      * Returns true if the fn and obj match this objects properties.
       
 11289      * Used by the unsubscribe method to match the right subscriber.
       
 11290      *
       
 11291      * @method contains
       
 11292      * @param {Function} fn the function to execute.
       
 11293      * @param {Object} context optional 'this' keyword for the listener.
       
 11294      * @return {boolean} true if the supplied arguments match this
       
 11295      *                   subscriber's signature.
       
 11296      */
       
 11297     contains: function(fn, context) {
       
 11298         if (context) {
       
 11299             return ((this.fn === fn) && this.context === context);
       
 11300         } else {
       
 11301             return (this.fn === fn);
       
 11302         }
       
 11303     },
       
 11304 
       
 11305     valueOf : function() {
       
 11306         return this.id;
       
 11307     }
       
 11308 
       
 11309 };
       
 11310 /**
       
 11311  * Return value from all subscribe operations
       
 11312  * @class EventHandle
       
 11313  * @constructor
       
 11314  * @param {CustomEvent} evt the custom event.
       
 11315  * @param {Subscriber} sub the subscriber.
       
 11316  */
       
 11317 Y.EventHandle = function(evt, sub) {
       
 11318 
       
 11319     /**
       
 11320      * The custom event
       
 11321      *
       
 11322      * @property evt
       
 11323      * @type CustomEvent
       
 11324      */
       
 11325     this.evt = evt;
       
 11326 
       
 11327     /**
       
 11328      * The subscriber object
       
 11329      *
       
 11330      * @property sub
       
 11331      * @type Subscriber
       
 11332      */
       
 11333     this.sub = sub;
       
 11334 };
       
 11335 
       
 11336 Y.EventHandle.prototype = {
       
 11337     batch: function(f, c) {
       
 11338         f.call(c || this, this);
       
 11339         if (Y.Lang.isArray(this.evt)) {
       
 11340             Y.Array.each(this.evt, function(h) {
       
 11341                 h.batch.call(c || h, f);
       
 11342             });
       
 11343         }
       
 11344     },
       
 11345 
       
 11346     /**
       
 11347      * Detaches this subscriber
       
 11348      * @method detach
       
 11349      * @return {int} the number of detached listeners
       
 11350      */
       
 11351     detach: function() {
       
 11352         var evt = this.evt, detached = 0, i;
       
 11353         if (evt) {
       
 11354             // Y.log('EventHandle.detach: ' + this.sub, 'info', 'Event');
       
 11355             if (Y.Lang.isArray(evt)) {
       
 11356                 for (i = 0; i < evt.length; i++) {
       
 11357                     detached += evt[i].detach();
       
 11358                 }
       
 11359             } else {
       
 11360                 evt._delete(this.sub);
       
 11361                 detached = 1;
       
 11362             }
       
 11363 
       
 11364         }
       
 11365 
       
 11366         return detached;
       
 11367     },
       
 11368 
       
 11369     /**
       
 11370      * Monitor the event state for the subscribed event.  The first parameter
       
 11371      * is what should be monitored, the rest are the normal parameters when
       
 11372      * subscribing to an event.
       
 11373      * @method monitor
       
 11374      * @param what {string} what to monitor ('attach', 'detach', 'publish').
       
 11375      * @return {EventHandle} return value from the monitor event subscription.
       
 11376      */
       
 11377     monitor: function(what) {
       
 11378         return this.evt.monitor.apply(this.evt, arguments);
       
 11379     }
       
 11380 };
       
 11381 
       
 11382 /**
       
 11383  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 11384  * events.
       
 11385  * @module event-custom
       
 11386  * @submodule event-custom-base
       
 11387  */
       
 11388 
       
 11389 /**
       
 11390  * EventTarget provides the implementation for any object to
       
 11391  * publish, subscribe and fire to custom events, and also
       
 11392  * alows other EventTargets to target the object with events
       
 11393  * sourced from the other object.
       
 11394  * EventTarget is designed to be used with Y.augment to wrap
       
 11395  * EventCustom in an interface that allows events to be listened to
       
 11396  * and fired by name.  This makes it possible for implementing code to
       
 11397  * subscribe to an event that either has not been created yet, or will
       
 11398  * not be created at all.
       
 11399  * @class EventTarget
       
 11400  * @param opts a configuration object
       
 11401  * @config emitFacade {boolean} if true, all events will emit event
       
 11402  * facade payloads by default (default false)
       
 11403  * @config prefix {String} the prefix to apply to non-prefixed event names
       
 11404  */
       
 11405 
       
 11406 var L = Y.Lang,
       
 11407     PREFIX_DELIMITER = ':',
       
 11408     CATEGORY_DELIMITER = '|',
       
 11409     AFTER_PREFIX = '~AFTER~',
       
 11410     WILD_TYPE_RE = /(.*?)(:)(.*?)/,
       
 11411 
       
 11412     _wildType = Y.cached(function(type) {
       
 11413         return type.replace(WILD_TYPE_RE, "*$2$3");
       
 11414     }),
       
 11415 
       
 11416     /**
       
 11417      * If the instance has a prefix attribute and the
       
 11418      * event type is not prefixed, the instance prefix is
       
 11419      * applied to the supplied type.
       
 11420      * @method _getType
       
 11421      * @private
       
 11422      */
       
 11423     _getType = function(type, pre) {
       
 11424 
       
 11425         if (!pre || type.indexOf(PREFIX_DELIMITER) > -1) {
       
 11426             return type;
       
 11427         }
       
 11428 
       
 11429         return pre + PREFIX_DELIMITER + type;
       
 11430     },
       
 11431 
       
 11432     /**
       
 11433      * Returns an array with the detach key (if provided),
       
 11434      * and the prefixed event name from _getType
       
 11435      * Y.on('detachcategory| menu:click', fn)
       
 11436      * @method _parseType
       
 11437      * @private
       
 11438      */
       
 11439     _parseType = Y.cached(function(type, pre) {
       
 11440 
       
 11441         var t = type, detachcategory, after, i;
       
 11442 
       
 11443         if (!L.isString(t)) {
       
 11444             return t;
       
 11445         }
       
 11446 
       
 11447         i = t.indexOf(AFTER_PREFIX);
       
 11448 
       
 11449         if (i > -1) {
       
 11450             after = true;
       
 11451             t = t.substr(AFTER_PREFIX.length);
       
 11452         }
       
 11453 
       
 11454         i = t.indexOf(CATEGORY_DELIMITER);
       
 11455 
       
 11456         if (i > -1) {
       
 11457             detachcategory = t.substr(0, (i));
       
 11458             t = t.substr(i+1);
       
 11459             if (t === '*') {
       
 11460                 t = null;
       
 11461             }
       
 11462         }
       
 11463 
       
 11464         // detach category, full type with instance prefix, is this an after listener, short type
       
 11465         return [detachcategory, (pre) ? _getType(t, pre) : t, after, t];
       
 11466     }),
       
 11467 
       
 11468     ET = function(opts) {
       
 11469 
       
 11470         var etState = this._yuievt,
       
 11471             etConfig;
       
 11472 
       
 11473         if (!etState) {
       
 11474             etState = this._yuievt = {
       
 11475                 events: {},    // PERF: Not much point instantiating lazily. We're bound to have events
       
 11476                 targets: null, // PERF: Instantiate lazily, if user actually adds target,
       
 11477                 config: {
       
 11478                     host: this,
       
 11479                     context: this
       
 11480                 },
       
 11481                 chain: Y.config.chain
       
 11482             };
       
 11483         }
       
 11484 
       
 11485         etConfig = etState.config;
       
 11486 
       
 11487         if (opts) {
       
 11488             mixConfigs(etConfig, opts, true);
       
 11489 
       
 11490             if (opts.chain !== undefined) {
       
 11491                 etState.chain = opts.chain;
       
 11492             }
       
 11493 
       
 11494             if (opts.prefix) {
       
 11495                 etConfig.prefix = opts.prefix;
       
 11496             }
       
 11497         }
       
 11498     };
       
 11499 
       
 11500 ET.prototype = {
       
 11501 
       
 11502     constructor: ET,
       
 11503 
       
 11504     /**
       
 11505      * Listen to a custom event hosted by this object one time.
       
 11506      * This is the equivalent to <code>on</code> except the
       
 11507      * listener is immediatelly detached when it is executed.
       
 11508      * @method once
       
 11509      * @param {String} type The name of the event
       
 11510      * @param {Function} fn The callback to execute in response to the event
       
 11511      * @param {Object} [context] Override `this` object in callback
       
 11512      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11513      * @return {EventHandle} A subscription handle capable of detaching the
       
 11514      *                       subscription
       
 11515      */
       
 11516     once: function() {
       
 11517         var handle = this.on.apply(this, arguments);
       
 11518         handle.batch(function(hand) {
       
 11519             if (hand.sub) {
       
 11520                 hand.sub.once = true;
       
 11521             }
       
 11522         });
       
 11523         return handle;
       
 11524     },
       
 11525 
       
 11526     /**
       
 11527      * Listen to a custom event hosted by this object one time.
       
 11528      * This is the equivalent to <code>after</code> except the
       
 11529      * listener is immediatelly detached when it is executed.
       
 11530      * @method onceAfter
       
 11531      * @param {String} type The name of the event
       
 11532      * @param {Function} fn The callback to execute in response to the event
       
 11533      * @param {Object} [context] Override `this` object in callback
       
 11534      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11535      * @return {EventHandle} A subscription handle capable of detaching that
       
 11536      *                       subscription
       
 11537      */
       
 11538     onceAfter: function() {
       
 11539         var handle = this.after.apply(this, arguments);
       
 11540         handle.batch(function(hand) {
       
 11541             if (hand.sub) {
       
 11542                 hand.sub.once = true;
       
 11543             }
       
 11544         });
       
 11545         return handle;
       
 11546     },
       
 11547 
       
 11548     /**
       
 11549      * Takes the type parameter passed to 'on' and parses out the
       
 11550      * various pieces that could be included in the type.  If the
       
 11551      * event type is passed without a prefix, it will be expanded
       
 11552      * to include the prefix one is supplied or the event target
       
 11553      * is configured with a default prefix.
       
 11554      * @method parseType
       
 11555      * @param {String} type the type
       
 11556      * @param {String} [pre=this._yuievt.config.prefix] the prefix
       
 11557      * @since 3.3.0
       
 11558      * @return {Array} an array containing:
       
 11559      *  * the detach category, if supplied,
       
 11560      *  * the prefixed event type,
       
 11561      *  * whether or not this is an after listener,
       
 11562      *  * the supplied event type
       
 11563      */
       
 11564     parseType: function(type, pre) {
       
 11565         return _parseType(type, pre || this._yuievt.config.prefix);
       
 11566     },
       
 11567 
       
 11568     /**
       
 11569      * Subscribe a callback function to a custom event fired by this object or
       
 11570      * from an object that bubbles its events to this object.
       
 11571      *
       
 11572      * Callback functions for events published with `emitFacade = true` will
       
 11573      * receive an `EventFacade` as the first argument (typically named "e").
       
 11574      * These callbacks can then call `e.preventDefault()` to disable the
       
 11575      * behavior published to that event's `defaultFn`.  See the `EventFacade`
       
 11576      * API for all available properties and methods. Subscribers to
       
 11577      * non-`emitFacade` events will receive the arguments passed to `fire()`
       
 11578      * after the event name.
       
 11579      *
       
 11580      * To subscribe to multiple events at once, pass an object as the first
       
 11581      * argument, where the key:value pairs correspond to the eventName:callback,
       
 11582      * or pass an array of event names as the first argument to subscribe to
       
 11583      * all listed events with the same callback.
       
 11584      *
       
 11585      * Returning `false` from a callback is supported as an alternative to
       
 11586      * calling `e.preventDefault(); e.stopPropagation();`.  However, it is
       
 11587      * recommended to use the event methods whenever possible.
       
 11588      *
       
 11589      * @method on
       
 11590      * @param {String} type The name of the event
       
 11591      * @param {Function} fn The callback to execute in response to the event
       
 11592      * @param {Object} [context] Override `this` object in callback
       
 11593      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 11594      * @return {EventHandle} A subscription handle capable of detaching that
       
 11595      *                       subscription
       
 11596      */
       
 11597     on: function(type, fn, context) {
       
 11598 
       
 11599         var yuievt = this._yuievt,
       
 11600             parts = _parseType(type, yuievt.config.prefix), f, c, args, ret, ce,
       
 11601             detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype,
       
 11602             Node = Y.Node, n, domevent, isArr;
       
 11603 
       
 11604         // full name, args, detachcategory, after
       
 11605         this._monitor('attach', parts[1], {
       
 11606             args: arguments,
       
 11607             category: parts[0],
       
 11608             after: parts[2]
       
 11609         });
       
 11610 
       
 11611         if (L.isObject(type)) {
       
 11612 
       
 11613             if (L.isFunction(type)) {
       
 11614                 return Y.Do.before.apply(Y.Do, arguments);
       
 11615             }
       
 11616 
       
 11617             f = fn;
       
 11618             c = context;
       
 11619             args = nativeSlice.call(arguments, 0);
       
 11620             ret = [];
       
 11621 
       
 11622             if (L.isArray(type)) {
       
 11623                 isArr = true;
       
 11624             }
       
 11625 
       
 11626             after = type._after;
       
 11627             delete type._after;
       
 11628 
       
 11629             Y.each(type, function(v, k) {
       
 11630 
       
 11631                 if (L.isObject(v)) {
       
 11632                     f = v.fn || ((L.isFunction(v)) ? v : f);
       
 11633                     c = v.context || c;
       
 11634                 }
       
 11635 
       
 11636                 var nv = (after) ? AFTER_PREFIX : '';
       
 11637 
       
 11638                 args[0] = nv + ((isArr) ? v : k);
       
 11639                 args[1] = f;
       
 11640                 args[2] = c;
       
 11641 
       
 11642                 ret.push(this.on.apply(this, args));
       
 11643 
       
 11644             }, this);
       
 11645 
       
 11646             return (yuievt.chain) ? this : new Y.EventHandle(ret);
       
 11647         }
       
 11648 
       
 11649         detachcategory = parts[0];
       
 11650         after = parts[2];
       
 11651         shorttype = parts[3];
       
 11652 
       
 11653         // extra redirection so we catch adaptor events too.  take a look at this.
       
 11654         if (Node && Y.instanceOf(this, Node) && (shorttype in Node.DOM_EVENTS)) {
       
 11655             args = nativeSlice.call(arguments, 0);
       
 11656             args.splice(2, 0, Node.getDOMNode(this));
       
 11657             // Y.log("Node detected, redirecting with these args: " + args);
       
 11658             return Y.on.apply(Y, args);
       
 11659         }
       
 11660 
       
 11661         type = parts[1];
       
 11662 
       
 11663         if (Y.instanceOf(this, YUI)) {
       
 11664 
       
 11665             adapt = Y.Env.evt.plugins[type];
       
 11666             args  = nativeSlice.call(arguments, 0);
       
 11667             args[0] = shorttype;
       
 11668 
       
 11669             if (Node) {
       
 11670                 n = args[2];
       
 11671 
       
 11672                 if (Y.instanceOf(n, Y.NodeList)) {
       
 11673                     n = Y.NodeList.getDOMNodes(n);
       
 11674                 } else if (Y.instanceOf(n, Node)) {
       
 11675                     n = Node.getDOMNode(n);
       
 11676                 }
       
 11677 
       
 11678                 domevent = (shorttype in Node.DOM_EVENTS);
       
 11679 
       
 11680                 // Captures both DOM events and event plugins.
       
 11681                 if (domevent) {
       
 11682                     args[2] = n;
       
 11683                 }
       
 11684             }
       
 11685 
       
 11686             // check for the existance of an event adaptor
       
 11687             if (adapt) {
       
 11688                 Y.log('Using adaptor for ' + shorttype + ', ' + n, 'info', 'event');
       
 11689                 handle = adapt.on.apply(Y, args);
       
 11690             } else if ((!type) || domevent) {
       
 11691                 handle = Y.Event._attach(args);
       
 11692             }
       
 11693 
       
 11694         }
       
 11695 
       
 11696         if (!handle) {
       
 11697             ce = yuievt.events[type] || this.publish(type);
       
 11698             handle = ce._on(fn, context, (arguments.length > 3) ? nativeSlice.call(arguments, 3) : null, (after) ? 'after' : true);
       
 11699 
       
 11700             // TODO: More robust regex, accounting for category
       
 11701             if (type.indexOf("*:") !== -1) {
       
 11702                 this._hasSiblings = true;
       
 11703             }
       
 11704         }
       
 11705 
       
 11706         if (detachcategory) {
       
 11707             store[detachcategory] = store[detachcategory] || {};
       
 11708             store[detachcategory][type] = store[detachcategory][type] || [];
       
 11709             store[detachcategory][type].push(handle);
       
 11710         }
       
 11711 
       
 11712         return (yuievt.chain) ? this : handle;
       
 11713 
       
 11714     },
       
 11715 
       
 11716     /**
       
 11717      * subscribe to an event
       
 11718      * @method subscribe
       
 11719      * @deprecated use on
       
 11720      */
       
 11721     subscribe: function() {
       
 11722         Y.log('EventTarget subscribe() is deprecated, use on()', 'warn', 'deprecated');
       
 11723         return this.on.apply(this, arguments);
       
 11724     },
       
 11725 
       
 11726     /**
       
 11727      * Detach one or more listeners the from the specified event
       
 11728      * @method detach
       
 11729      * @param type {string|Object}   Either the handle to the subscriber or the
       
 11730      *                        type of event.  If the type
       
 11731      *                        is not specified, it will attempt to remove
       
 11732      *                        the listener from all hosted events.
       
 11733      * @param fn   {Function} The subscribed function to unsubscribe, if not
       
 11734      *                          supplied, all subscribers will be removed.
       
 11735      * @param context  {Object}   The custom object passed to subscribe.  This is
       
 11736      *                        optional, but if supplied will be used to
       
 11737      *                        disambiguate multiple listeners that are the same
       
 11738      *                        (e.g., you subscribe many object using a function
       
 11739      *                        that lives on the prototype)
       
 11740      * @return {EventTarget} the host
       
 11741      */
       
 11742     detach: function(type, fn, context) {
       
 11743 
       
 11744         var evts = this._yuievt.events,
       
 11745             i,
       
 11746             Node = Y.Node,
       
 11747             isNode = Node && (Y.instanceOf(this, Node));
       
 11748 
       
 11749         // detachAll disabled on the Y instance.
       
 11750         if (!type && (this !== Y)) {
       
 11751             for (i in evts) {
       
 11752                 if (evts.hasOwnProperty(i)) {
       
 11753                     evts[i].detach(fn, context);
       
 11754                 }
       
 11755             }
       
 11756             if (isNode) {
       
 11757                 Y.Event.purgeElement(Node.getDOMNode(this));
       
 11758             }
       
 11759 
       
 11760             return this;
       
 11761         }
       
 11762 
       
 11763         var parts = _parseType(type, this._yuievt.config.prefix),
       
 11764         detachcategory = L.isArray(parts) ? parts[0] : null,
       
 11765         shorttype = (parts) ? parts[3] : null,
       
 11766         adapt, store = Y.Env.evt.handles, detachhost, cat, args,
       
 11767         ce,
       
 11768 
       
 11769         keyDetacher = function(lcat, ltype, host) {
       
 11770             var handles = lcat[ltype], ce, i;
       
 11771             if (handles) {
       
 11772                 for (i = handles.length - 1; i >= 0; --i) {
       
 11773                     ce = handles[i].evt;
       
 11774                     if (ce.host === host || ce.el === host) {
       
 11775                         handles[i].detach();
       
 11776                     }
       
 11777                 }
       
 11778             }
       
 11779         };
       
 11780 
       
 11781         if (detachcategory) {
       
 11782 
       
 11783             cat = store[detachcategory];
       
 11784             type = parts[1];
       
 11785             detachhost = (isNode) ? Y.Node.getDOMNode(this) : this;
       
 11786 
       
 11787             if (cat) {
       
 11788                 if (type) {
       
 11789                     keyDetacher(cat, type, detachhost);
       
 11790                 } else {
       
 11791                     for (i in cat) {
       
 11792                         if (cat.hasOwnProperty(i)) {
       
 11793                             keyDetacher(cat, i, detachhost);
       
 11794                         }
       
 11795                     }
       
 11796                 }
       
 11797 
       
 11798                 return this;
       
 11799             }
       
 11800 
       
 11801         // If this is an event handle, use it to detach
       
 11802         } else if (L.isObject(type) && type.detach) {
       
 11803             type.detach();
       
 11804             return this;
       
 11805         // extra redirection so we catch adaptor events too.  take a look at this.
       
 11806         } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) {
       
 11807             args = nativeSlice.call(arguments, 0);
       
 11808             args[2] = Node.getDOMNode(this);
       
 11809             Y.detach.apply(Y, args);
       
 11810             return this;
       
 11811         }
       
 11812 
       
 11813         adapt = Y.Env.evt.plugins[shorttype];
       
 11814 
       
 11815         // The YUI instance handles DOM events and adaptors
       
 11816         if (Y.instanceOf(this, YUI)) {
       
 11817             args = nativeSlice.call(arguments, 0);
       
 11818             // use the adaptor specific detach code if
       
 11819             if (adapt && adapt.detach) {
       
 11820                 adapt.detach.apply(Y, args);
       
 11821                 return this;
       
 11822             // DOM event fork
       
 11823             } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
       
 11824                 args[0] = type;
       
 11825                 Y.Event.detach.apply(Y.Event, args);
       
 11826                 return this;
       
 11827             }
       
 11828         }
       
 11829 
       
 11830         // ce = evts[type];
       
 11831         ce = evts[parts[1]];
       
 11832         if (ce) {
       
 11833             ce.detach(fn, context);
       
 11834         }
       
 11835 
       
 11836         return this;
       
 11837     },
       
 11838 
       
 11839     /**
       
 11840      * detach a listener
       
 11841      * @method unsubscribe
       
 11842      * @deprecated use detach
       
 11843      */
       
 11844     unsubscribe: function() {
       
 11845 Y.log('EventTarget unsubscribe() is deprecated, use detach()', 'warn', 'deprecated');
       
 11846         return this.detach.apply(this, arguments);
       
 11847     },
       
 11848 
       
 11849     /**
       
 11850      * Removes all listeners from the specified event.  If the event type
       
 11851      * is not specified, all listeners from all hosted custom events will
       
 11852      * be removed.
       
 11853      * @method detachAll
       
 11854      * @param type {String}   The type, or name of the event
       
 11855      */
       
 11856     detachAll: function(type) {
       
 11857         return this.detach(type);
       
 11858     },
       
 11859 
       
 11860     /**
       
 11861      * Removes all listeners from the specified event.  If the event type
       
 11862      * is not specified, all listeners from all hosted custom events will
       
 11863      * be removed.
       
 11864      * @method unsubscribeAll
       
 11865      * @param type {String}   The type, or name of the event
       
 11866      * @deprecated use detachAll
       
 11867      */
       
 11868     unsubscribeAll: function() {
       
 11869 Y.log('EventTarget unsubscribeAll() is deprecated, use detachAll()', 'warn', 'deprecated');
       
 11870         return this.detachAll.apply(this, arguments);
       
 11871     },
       
 11872 
       
 11873     /**
       
 11874      * Creates a new custom event of the specified type.  If a custom event
       
 11875      * by that name already exists, it will not be re-created.  In either
       
 11876      * case the custom event is returned.
       
 11877      *
       
 11878      * @method publish
       
 11879      *
       
 11880      * @param type {String} the type, or name of the event
       
 11881      * @param opts {object} optional config params.  Valid properties are:
       
 11882      *
       
 11883      *  <ul>
       
 11884      *    <li>
       
 11885      *   'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
       
 11886      *    </li>
       
 11887      *    <li>
       
 11888      *   'bubbles': whether or not this event bubbles (true)
       
 11889      *              Events can only bubble if emitFacade is true.
       
 11890      *    </li>
       
 11891      *    <li>
       
 11892      *   'context': the default execution context for the listeners (this)
       
 11893      *    </li>
       
 11894      *    <li>
       
 11895      *   'defaultFn': the default function to execute when this event fires if preventDefault was not called
       
 11896      *    </li>
       
 11897      *    <li>
       
 11898      *   'emitFacade': whether or not this event emits a facade (false)
       
 11899      *    </li>
       
 11900      *    <li>
       
 11901      *   'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click'
       
 11902      *    </li>
       
 11903      *    <li>
       
 11904      *   'fireOnce': if an event is configured to fire once, new subscribers after
       
 11905      *   the fire will be notified immediately.
       
 11906      *    </li>
       
 11907      *    <li>
       
 11908      *   'async': fireOnce event listeners will fire synchronously if the event has already
       
 11909      *    fired unless async is true.
       
 11910      *    </li>
       
 11911      *    <li>
       
 11912      *   'preventable': whether or not preventDefault() has an effect (true)
       
 11913      *    </li>
       
 11914      *    <li>
       
 11915      *   'preventedFn': a function that is executed when preventDefault is called
       
 11916      *    </li>
       
 11917      *    <li>
       
 11918      *   'queuable': whether or not this event can be queued during bubbling (false)
       
 11919      *    </li>
       
 11920      *    <li>
       
 11921      *   'silent': if silent is true, debug messages are not provided for this event.
       
 11922      *    </li>
       
 11923      *    <li>
       
 11924      *   'stoppedFn': a function that is executed when stopPropagation is called
       
 11925      *    </li>
       
 11926      *
       
 11927      *    <li>
       
 11928      *   'monitored': specifies whether or not this event should send notifications about
       
 11929      *   when the event has been attached, detached, or published.
       
 11930      *    </li>
       
 11931      *    <li>
       
 11932      *   'type': the event type (valid option if not provided as the first parameter to publish)
       
 11933      *    </li>
       
 11934      *  </ul>
       
 11935      *
       
 11936      *  @return {CustomEvent} the custom event
       
 11937      *
       
 11938      */
       
 11939     publish: function(type, opts) {
       
 11940 
       
 11941         var ret,
       
 11942             etState = this._yuievt,
       
 11943             etConfig = etState.config,
       
 11944             pre = etConfig.prefix;
       
 11945 
       
 11946         if (typeof type === "string")  {
       
 11947             if (pre) {
       
 11948                 type = _getType(type, pre);
       
 11949             }
       
 11950             ret = this._publish(type, etConfig, opts);
       
 11951         } else {
       
 11952             ret = {};
       
 11953 
       
 11954             Y.each(type, function(v, k) {
       
 11955                 if (pre) {
       
 11956                     k = _getType(k, pre);
       
 11957                 }
       
 11958                 ret[k] = this._publish(k, etConfig, v || opts);
       
 11959             }, this);
       
 11960 
       
 11961         }
       
 11962 
       
 11963         return ret;
       
 11964     },
       
 11965 
       
 11966     /**
       
 11967      * Returns the fully qualified type, given a short type string.
       
 11968      * That is, returns "foo:bar" when given "bar" if "foo" is the configured prefix.
       
 11969      *
       
 11970      * NOTE: This method, unlike _getType, does no checking of the value passed in, and
       
 11971      * is designed to be used with the low level _publish() method, for critical path
       
 11972      * implementations which need to fast-track publish for performance reasons.
       
 11973      *
       
 11974      * @method _getFullType
       
 11975      * @private
       
 11976      * @param {String} type The short type to prefix
       
 11977      * @return {String} The prefixed type, if a prefix is set, otherwise the type passed in
       
 11978      */
       
 11979     _getFullType : function(type) {
       
 11980 
       
 11981         var pre = this._yuievt.config.prefix;
       
 11982 
       
 11983         if (pre) {
       
 11984             return pre + PREFIX_DELIMITER + type;
       
 11985         } else {
       
 11986             return type;
       
 11987         }
       
 11988     },
       
 11989 
       
 11990     /**
       
 11991      * The low level event publish implementation. It expects all the massaging to have been done
       
 11992      * outside of this method. e.g. the `type` to `fullType` conversion. It's designed to be a fast
       
 11993      * path publish, which can be used by critical code paths to improve performance.
       
 11994      *
       
 11995      * @method _publish
       
 11996      * @private
       
 11997      * @param {String} fullType The prefixed type of the event to publish.
       
 11998      * @param {Object} etOpts The EventTarget specific configuration to mix into the published event.
       
 11999      * @param {Object} ceOpts The publish specific configuration to mix into the published event.
       
 12000      * @return {CustomEvent} The published event. If called without `etOpts` or `ceOpts`, this will
       
 12001      * be the default `CustomEvent` instance, and can be configured independently.
       
 12002      */
       
 12003     _publish : function(fullType, etOpts, ceOpts) {
       
 12004 
       
 12005         var ce,
       
 12006             etState = this._yuievt,
       
 12007             etConfig = etState.config,
       
 12008             host = etConfig.host,
       
 12009             context = etConfig.context,
       
 12010             events = etState.events;
       
 12011 
       
 12012         ce = events[fullType];
       
 12013 
       
 12014         // PERF: Hate to pull the check out of monitor, but trying to keep critical path tight.
       
 12015         if ((etConfig.monitored && !ce) || (ce && ce.monitored)) {
       
 12016             this._monitor('publish', fullType, {
       
 12017                 args: arguments
       
 12018             });
       
 12019         }
       
 12020 
       
 12021         if (!ce) {
       
 12022             // Publish event
       
 12023             ce = events[fullType] = new Y.CustomEvent(fullType, etOpts);
       
 12024 
       
 12025             if (!etOpts) {
       
 12026                 ce.host = host;
       
 12027                 ce.context = context;
       
 12028             }
       
 12029         }
       
 12030 
       
 12031         if (ceOpts) {
       
 12032             mixConfigs(ce, ceOpts, true);
       
 12033         }
       
 12034 
       
 12035         return ce;
       
 12036     },
       
 12037 
       
 12038     /**
       
 12039      * This is the entry point for the event monitoring system.
       
 12040      * You can monitor 'attach', 'detach', 'fire', and 'publish'.
       
 12041      * When configured, these events generate an event.  click ->
       
 12042      * click_attach, click_detach, click_publish -- these can
       
 12043      * be subscribed to like other events to monitor the event
       
 12044      * system.  Inividual published events can have monitoring
       
 12045      * turned on or off (publish can't be turned off before it
       
 12046      * it published) by setting the events 'monitor' config.
       
 12047      *
       
 12048      * @method _monitor
       
 12049      * @param what {String} 'attach', 'detach', 'fire', or 'publish'
       
 12050      * @param eventType {String|CustomEvent} The prefixed name of the event being monitored, or the CustomEvent object.
       
 12051      * @param o {Object} Information about the event interaction, such as
       
 12052      *                  fire() args, subscription category, publish config
       
 12053      * @private
       
 12054      */
       
 12055     _monitor: function(what, eventType, o) {
       
 12056         var monitorevt, ce, type;
       
 12057 
       
 12058         if (eventType) {
       
 12059             if (typeof eventType === "string") {
       
 12060                 type = eventType;
       
 12061                 ce = this.getEvent(eventType, true);
       
 12062             } else {
       
 12063                 ce = eventType;
       
 12064                 type = eventType.type;
       
 12065             }
       
 12066 
       
 12067             if ((this._yuievt.config.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) {
       
 12068                 monitorevt = type + '_' + what;
       
 12069                 o.monitored = what;
       
 12070                 this.fire.call(this, monitorevt, o);
       
 12071             }
       
 12072         }
       
 12073     },
       
 12074 
       
 12075     /**
       
 12076      * Fire a custom event by name.  The callback functions will be executed
       
 12077      * from the context specified when the event was created, and with the
       
 12078      * following parameters.
       
 12079      *
       
 12080      * If the custom event object hasn't been created, then the event hasn't
       
 12081      * been published and it has no subscribers.  For performance sake, we
       
 12082      * immediate exit in this case.  This means the event won't bubble, so
       
 12083      * if the intention is that a bubble target be notified, the event must
       
 12084      * be published on this object first.
       
 12085      *
       
 12086      * The first argument is the event type, and any additional arguments are
       
 12087      * passed to the listeners as parameters.  If the first of these is an
       
 12088      * object literal, and the event is configured to emit an event facade,
       
 12089      * that object is mixed into the event facade and the facade is provided
       
 12090      * in place of the original object.
       
 12091      *
       
 12092      * @method fire
       
 12093      * @param type {String|Object} The type of the event, or an object that contains
       
 12094      * a 'type' property.
       
 12095      * @param arguments {Object*} an arbitrary set of parameters to pass to
       
 12096      * the handler.  If the first of these is an object literal and the event is
       
 12097      * configured to emit an event facade, the event facade will replace that
       
 12098      * parameter after the properties the object literal contains are copied to
       
 12099      * the event facade.
       
 12100      * @return {EventTarget} the event host
       
 12101      */
       
 12102     fire: function(type) {
       
 12103 
       
 12104         var typeIncluded = (typeof type === "string"),
       
 12105             argCount = arguments.length,
       
 12106             t = type,
       
 12107             yuievt = this._yuievt,
       
 12108             etConfig = yuievt.config,
       
 12109             pre = etConfig.prefix,
       
 12110             ret,
       
 12111             ce,
       
 12112             ce2,
       
 12113             args;
       
 12114 
       
 12115         if (typeIncluded && argCount <= 3) {
       
 12116 
       
 12117             // PERF: Try to avoid slice/iteration for the common signatures
       
 12118 
       
 12119             // Most common
       
 12120             if (argCount === 2) {
       
 12121                 args = [arguments[1]]; // fire("foo", {})
       
 12122             } else if (argCount === 3) {
       
 12123                 args = [arguments[1], arguments[2]]; // fire("foo", {}, opts)
       
 12124             } else {
       
 12125                 args = []; // fire("foo")
       
 12126             }
       
 12127 
       
 12128         } else {
       
 12129             args = nativeSlice.call(arguments, ((typeIncluded) ? 1 : 0));
       
 12130         }
       
 12131 
       
 12132         if (!typeIncluded) {
       
 12133             t = (type && type.type);
       
 12134         }
       
 12135 
       
 12136         if (pre) {
       
 12137             t = _getType(t, pre);
       
 12138         }
       
 12139 
       
 12140         ce = yuievt.events[t];
       
 12141 
       
 12142         if (this._hasSiblings) {
       
 12143             ce2 = this.getSibling(t, ce);
       
 12144 
       
 12145             if (ce2 && !ce) {
       
 12146                 ce = this.publish(t);
       
 12147             }
       
 12148         }
       
 12149 
       
 12150         // PERF: trying to avoid function call, since this is a critical path
       
 12151         if ((etConfig.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) {
       
 12152             this._monitor('fire', (ce || t), {
       
 12153                 args: args
       
 12154             });
       
 12155         }
       
 12156 
       
 12157         // this event has not been published or subscribed to
       
 12158         if (!ce) {
       
 12159             if (yuievt.hasTargets) {
       
 12160                 return this.bubble({ type: t }, args, this);
       
 12161             }
       
 12162 
       
 12163             // otherwise there is nothing to be done
       
 12164             ret = true;
       
 12165         } else {
       
 12166 
       
 12167             if (ce2) {
       
 12168                 ce.sibling = ce2;
       
 12169             }
       
 12170 
       
 12171             ret = ce._fire(args);
       
 12172         }
       
 12173 
       
 12174         return (yuievt.chain) ? this : ret;
       
 12175     },
       
 12176 
       
 12177     getSibling: function(type, ce) {
       
 12178         var ce2;
       
 12179 
       
 12180         // delegate to *:type events if there are subscribers
       
 12181         if (type.indexOf(PREFIX_DELIMITER) > -1) {
       
 12182             type = _wildType(type);
       
 12183             ce2 = this.getEvent(type, true);
       
 12184             if (ce2) {
       
 12185                 ce2.applyConfig(ce);
       
 12186                 ce2.bubbles = false;
       
 12187                 ce2.broadcast = 0;
       
 12188             }
       
 12189         }
       
 12190 
       
 12191         return ce2;
       
 12192     },
       
 12193 
       
 12194     /**
       
 12195      * Returns the custom event of the provided type has been created, a
       
 12196      * falsy value otherwise
       
 12197      * @method getEvent
       
 12198      * @param type {String} the type, or name of the event
       
 12199      * @param prefixed {String} if true, the type is prefixed already
       
 12200      * @return {CustomEvent} the custom event or null
       
 12201      */
       
 12202     getEvent: function(type, prefixed) {
       
 12203         var pre, e;
       
 12204 
       
 12205         if (!prefixed) {
       
 12206             pre = this._yuievt.config.prefix;
       
 12207             type = (pre) ? _getType(type, pre) : type;
       
 12208         }
       
 12209         e = this._yuievt.events;
       
 12210         return e[type] || null;
       
 12211     },
       
 12212 
       
 12213     /**
       
 12214      * Subscribe to a custom event hosted by this object.  The
       
 12215      * supplied callback will execute after any listeners add
       
 12216      * via the subscribe method, and after the default function,
       
 12217      * if configured for the event, has executed.
       
 12218      *
       
 12219      * @method after
       
 12220      * @param {String} type The name of the event
       
 12221      * @param {Function} fn The callback to execute in response to the event
       
 12222      * @param {Object} [context] Override `this` object in callback
       
 12223      * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 12224      * @return {EventHandle} A subscription handle capable of detaching the
       
 12225      *                       subscription
       
 12226      */
       
 12227     after: function(type, fn) {
       
 12228 
       
 12229         var a = nativeSlice.call(arguments, 0);
       
 12230 
       
 12231         switch (L.type(type)) {
       
 12232             case 'function':
       
 12233                 return Y.Do.after.apply(Y.Do, arguments);
       
 12234             case 'array':
       
 12235             //     YArray.each(a[0], function(v) {
       
 12236             //         v = AFTER_PREFIX + v;
       
 12237             //     });
       
 12238             //     break;
       
 12239             case 'object':
       
 12240                 a[0]._after = true;
       
 12241                 break;
       
 12242             default:
       
 12243                 a[0] = AFTER_PREFIX + type;
       
 12244         }
       
 12245 
       
 12246         return this.on.apply(this, a);
       
 12247 
       
 12248     },
       
 12249 
       
 12250     /**
       
 12251      * Executes the callback before a DOM event, custom event
       
 12252      * or method.  If the first argument is a function, it
       
 12253      * is assumed the target is a method.  For DOM and custom
       
 12254      * events, this is an alias for Y.on.
       
 12255      *
       
 12256      * For DOM and custom events:
       
 12257      * type, callback, context, 0-n arguments
       
 12258      *
       
 12259      * For methods:
       
 12260      * callback, object (method host), methodName, context, 0-n arguments
       
 12261      *
       
 12262      * @method before
       
 12263      * @return detach handle
       
 12264      */
       
 12265     before: function() {
       
 12266         return this.on.apply(this, arguments);
       
 12267     }
       
 12268 
       
 12269 };
       
 12270 
       
 12271 Y.EventTarget = ET;
       
 12272 
       
 12273 // make Y an event target
       
 12274 Y.mix(Y, ET.prototype);
       
 12275 ET.call(Y, { bubbles: false });
       
 12276 
       
 12277 YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
       
 12278 
       
 12279 /**
       
 12280  * Hosts YUI page level events.  This is where events bubble to
       
 12281  * when the broadcast config is set to 2.  This property is
       
 12282  * only available if the custom event module is loaded.
       
 12283  * @property Global
       
 12284  * @type EventTarget
       
 12285  * @for YUI
       
 12286  */
       
 12287 Y.Global = YUI.Env.globalEvents;
       
 12288 
       
 12289 // @TODO implement a global namespace function on Y.Global?
       
 12290 
       
 12291 /**
       
 12292 `Y.on()` can do many things:
       
 12293 
       
 12294 <ul>
       
 12295     <li>Subscribe to custom events `publish`ed and `fire`d from Y</li>
       
 12296     <li>Subscribe to custom events `publish`ed with `broadcast` 1 or 2 and
       
 12297         `fire`d from any object in the YUI instance sandbox</li>
       
 12298     <li>Subscribe to DOM events</li>
       
 12299     <li>Subscribe to the execution of a method on any object, effectively
       
 12300     treating that method as an event</li>
       
 12301 </ul>
       
 12302 
       
 12303 For custom event subscriptions, pass the custom event name as the first argument
       
 12304 and callback as the second. The `this` object in the callback will be `Y` unless
       
 12305 an override is passed as the third argument.
       
 12306 
       
 12307     Y.on('io:complete', function () {
       
 12308         Y.MyApp.updateStatus('Transaction complete');
       
 12309     });
       
 12310 
       
 12311 To subscribe to DOM events, pass the name of a DOM event as the first argument
       
 12312 and a CSS selector string as the third argument after the callback function.
       
 12313 Alternately, the third argument can be a `Node`, `NodeList`, `HTMLElement`,
       
 12314 array, or simply omitted (the default is the `window` object).
       
 12315 
       
 12316     Y.on('click', function (e) {
       
 12317         e.preventDefault();
       
 12318 
       
 12319         // proceed with ajax form submission
       
 12320         var url = this.get('action');
       
 12321         ...
       
 12322     }, '#my-form');
       
 12323 
       
 12324 The `this` object in DOM event callbacks will be the `Node` targeted by the CSS
       
 12325 selector or other identifier.
       
 12326 
       
 12327 `on()` subscribers for DOM events or custom events `publish`ed with a
       
 12328 `defaultFn` can prevent the default behavior with `e.preventDefault()` from the
       
 12329 event object passed as the first parameter to the subscription callback.
       
 12330 
       
 12331 To subscribe to the execution of an object method, pass arguments corresponding to the call signature for
       
 12332 <a href="../classes/Do.html#methods_before">`Y.Do.before(...)`</a>.
       
 12333 
       
 12334 NOTE: The formal parameter list below is for events, not for function
       
 12335 injection.  See `Y.Do.before` for that signature.
       
 12336 
       
 12337 @method on
       
 12338 @param {String} type DOM or custom event name
       
 12339 @param {Function} fn The callback to execute in response to the event
       
 12340 @param {Object} [context] Override `this` object in callback
       
 12341 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 12342 @return {EventHandle} A subscription handle capable of detaching the
       
 12343                       subscription
       
 12344 @see Do.before
       
 12345 @for YUI
       
 12346 **/
       
 12347 
       
 12348 /**
       
 12349 Listen for an event one time.  Equivalent to `on()`, except that
       
 12350 the listener is immediately detached when executed.
       
 12351 
       
 12352 See the <a href="#methods_on">`on()` method</a> for additional subscription
       
 12353 options.
       
 12354 
       
 12355 @see on
       
 12356 @method once
       
 12357 @param {String} type DOM or custom event name
       
 12358 @param {Function} fn The callback to execute in response to the event
       
 12359 @param {Object} [context] Override `this` object in callback
       
 12360 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 12361 @return {EventHandle} A subscription handle capable of detaching the
       
 12362                       subscription
       
 12363 @for YUI
       
 12364 **/
       
 12365 
       
 12366 /**
       
 12367 Listen for an event one time.  Equivalent to `once()`, except, like `after()`,
       
 12368 the subscription callback executes after all `on()` subscribers and the event's
       
 12369 `defaultFn` (if configured) have executed.  Like `after()` if any `on()` phase
       
 12370 subscriber calls `e.preventDefault()`, neither the `defaultFn` nor the `after()`
       
 12371 subscribers will execute.
       
 12372 
       
 12373 The listener is immediately detached when executed.
       
 12374 
       
 12375 See the <a href="#methods_on">`on()` method</a> for additional subscription
       
 12376 options.
       
 12377 
       
 12378 @see once
       
 12379 @method onceAfter
       
 12380 @param {String} type The custom event name
       
 12381 @param {Function} fn The callback to execute in response to the event
       
 12382 @param {Object} [context] Override `this` object in callback
       
 12383 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 12384 @return {EventHandle} A subscription handle capable of detaching the
       
 12385                       subscription
       
 12386 @for YUI
       
 12387 **/
       
 12388 
       
 12389 /**
       
 12390 Like `on()`, this method creates a subscription to a custom event or to the
       
 12391 execution of a method on an object.
       
 12392 
       
 12393 For events, `after()` subscribers are executed after the event's
       
 12394 `defaultFn` unless `e.preventDefault()` was called from an `on()` subscriber.
       
 12395 
       
 12396 See the <a href="#methods_on">`on()` method</a> for additional subscription
       
 12397 options.
       
 12398 
       
 12399 NOTE: The subscription signature shown is for events, not for function
       
 12400 injection.  See <a href="../classes/Do.html#methods_after">`Y.Do.after`</a>
       
 12401 for that signature.
       
 12402 
       
 12403 @see on
       
 12404 @see Do.after
       
 12405 @method after
       
 12406 @param {String} type The custom event name
       
 12407 @param {Function} fn The callback to execute in response to the event
       
 12408 @param {Object} [context] Override `this` object in callback
       
 12409 @param {Any} [args*] 0..n additional arguments to supply to the subscriber
       
 12410 @return {EventHandle} A subscription handle capable of detaching the
       
 12411                       subscription
       
 12412 @for YUI
       
 12413 **/
       
 12414 
       
 12415 
       
 12416 }, '@VERSION@', {"requires": ["oop"]});
       
 12417 YUI.add('event-custom-complex', function (Y, NAME) {
       
 12418 
       
 12419 
       
 12420 /**
       
 12421  * Adds event facades, preventable default behavior, and bubbling.
       
 12422  * events.
       
 12423  * @module event-custom
       
 12424  * @submodule event-custom-complex
       
 12425  */
       
 12426 
       
 12427 var FACADE,
       
 12428     FACADE_KEYS,
       
 12429     YObject = Y.Object,
       
 12430     key,
       
 12431     EMPTY = {},
       
 12432     CEProto = Y.CustomEvent.prototype,
       
 12433     ETProto = Y.EventTarget.prototype,
       
 12434 
       
 12435     mixFacadeProps = function(facade, payload) {
       
 12436         var p;
       
 12437 
       
 12438         for (p in payload) {
       
 12439             if (!(FACADE_KEYS.hasOwnProperty(p))) {
       
 12440                 facade[p] = payload[p];
       
 12441             }
       
 12442         }
       
 12443     };
       
 12444 
       
 12445 /**
       
 12446  * Wraps and protects a custom event for use when emitFacade is set to true.
       
 12447  * Requires the event-custom-complex module
       
 12448  * @class EventFacade
       
 12449  * @param e {Event} the custom event
       
 12450  * @param currentTarget {HTMLElement} the element the listener was attached to
       
 12451  */
       
 12452 
       
 12453 Y.EventFacade = function(e, currentTarget) {
       
 12454 
       
 12455     if (!e) {
       
 12456         e = EMPTY;
       
 12457     }
       
 12458 
       
 12459     this._event = e;
       
 12460 
       
 12461     /**
       
 12462      * The arguments passed to fire
       
 12463      * @property details
       
 12464      * @type Array
       
 12465      */
       
 12466     this.details = e.details;
       
 12467 
       
 12468     /**
       
 12469      * The event type, this can be overridden by the fire() payload
       
 12470      * @property type
       
 12471      * @type string
       
 12472      */
       
 12473     this.type = e.type;
       
 12474 
       
 12475     /**
       
 12476      * The real event type
       
 12477      * @property _type
       
 12478      * @type string
       
 12479      * @private
       
 12480      */
       
 12481     this._type = e.type;
       
 12482 
       
 12483     //////////////////////////////////////////////////////
       
 12484 
       
 12485     /**
       
 12486      * Node reference for the targeted eventtarget
       
 12487      * @property target
       
 12488      * @type Node
       
 12489      */
       
 12490     this.target = e.target;
       
 12491 
       
 12492     /**
       
 12493      * Node reference for the element that the listener was attached to.
       
 12494      * @property currentTarget
       
 12495      * @type Node
       
 12496      */
       
 12497     this.currentTarget = currentTarget;
       
 12498 
       
 12499     /**
       
 12500      * Node reference to the relatedTarget
       
 12501      * @property relatedTarget
       
 12502      * @type Node
       
 12503      */
       
 12504     this.relatedTarget = e.relatedTarget;
       
 12505 
       
 12506 };
       
 12507 
       
 12508 Y.mix(Y.EventFacade.prototype, {
       
 12509 
       
 12510     /**
       
 12511      * Stops the propagation to the next bubble target
       
 12512      * @method stopPropagation
       
 12513      */
       
 12514     stopPropagation: function() {
       
 12515         this._event.stopPropagation();
       
 12516         this.stopped = 1;
       
 12517     },
       
 12518 
       
 12519     /**
       
 12520      * Stops the propagation to the next bubble target and
       
 12521      * prevents any additional listeners from being exectued
       
 12522      * on the current target.
       
 12523      * @method stopImmediatePropagation
       
 12524      */
       
 12525     stopImmediatePropagation: function() {
       
 12526         this._event.stopImmediatePropagation();
       
 12527         this.stopped = 2;
       
 12528     },
       
 12529 
       
 12530     /**
       
 12531      * Prevents the event's default behavior
       
 12532      * @method preventDefault
       
 12533      */
       
 12534     preventDefault: function() {
       
 12535         this._event.preventDefault();
       
 12536         this.prevented = 1;
       
 12537     },
       
 12538 
       
 12539     /**
       
 12540      * Stops the event propagation and prevents the default
       
 12541      * event behavior.
       
 12542      * @method halt
       
 12543      * @param immediate {boolean} if true additional listeners
       
 12544      * on the current target will not be executed
       
 12545      */
       
 12546     halt: function(immediate) {
       
 12547         this._event.halt(immediate);
       
 12548         this.prevented = 1;
       
 12549         this.stopped = (immediate) ? 2 : 1;
       
 12550     }
       
 12551 
       
 12552 });
       
 12553 
       
 12554 CEProto.fireComplex = function(args) {
       
 12555 
       
 12556     var es,
       
 12557         ef,
       
 12558         q,
       
 12559         queue,
       
 12560         ce,
       
 12561         ret = true,
       
 12562         events,
       
 12563         subs,
       
 12564         ons,
       
 12565         afters,
       
 12566         afterQueue,
       
 12567         postponed,
       
 12568         prevented,
       
 12569         preventedFn,
       
 12570         defaultFn,
       
 12571         self = this,
       
 12572         host = self.host || self,
       
 12573         next,
       
 12574         oldbubble,
       
 12575         stack,
       
 12576         yuievt = host._yuievt,
       
 12577         hasPotentialSubscribers;
       
 12578 
       
 12579     stack = self.stack;
       
 12580 
       
 12581     if (stack) {
       
 12582 
       
 12583         // queue this event if the current item in the queue bubbles
       
 12584         if (self.queuable && self.type !== stack.next.type) {
       
 12585             self.log('queue ' + self.type);
       
 12586 
       
 12587             if (!stack.queue) {
       
 12588                 stack.queue = [];
       
 12589             }
       
 12590             stack.queue.push([self, args]);
       
 12591 
       
 12592             return true;
       
 12593         }
       
 12594     }
       
 12595 
       
 12596     hasPotentialSubscribers = self.hasSubs() || yuievt.hasTargets || self.broadcast;
       
 12597 
       
 12598     self.target = self.target || host;
       
 12599     self.currentTarget = host;
       
 12600 
       
 12601     self.details = args.concat();
       
 12602 
       
 12603     if (hasPotentialSubscribers) {
       
 12604 
       
 12605         es = stack || {
       
 12606 
       
 12607            id: self.id, // id of the first event in the stack
       
 12608            next: self,
       
 12609            silent: self.silent,
       
 12610            stopped: 0,
       
 12611            prevented: 0,
       
 12612            bubbling: null,
       
 12613            type: self.type,
       
 12614            // defaultFnQueue: new Y.Queue(),
       
 12615            defaultTargetOnly: self.defaultTargetOnly
       
 12616 
       
 12617         };
       
 12618 
       
 12619         subs = self.getSubs();
       
 12620         ons = subs[0];
       
 12621         afters = subs[1];
       
 12622 
       
 12623         self.stopped = (self.type !== es.type) ? 0 : es.stopped;
       
 12624         self.prevented = (self.type !== es.type) ? 0 : es.prevented;
       
 12625 
       
 12626         if (self.stoppedFn) {
       
 12627             // PERF TODO: Can we replace with callback, like preventedFn. Look into history
       
 12628             events = new Y.EventTarget({
       
 12629                 fireOnce: true,
       
 12630                 context: host
       
 12631             });
       
 12632             self.events = events;
       
 12633             events.on('stopped', self.stoppedFn);
       
 12634         }
       
 12635 
       
 12636         // self.log("Firing " + self  + ", " + "args: " + args);
       
 12637         self.log("Firing " + self.type);
       
 12638 
       
 12639         self._facade = null; // kill facade to eliminate stale properties
       
 12640 
       
 12641         ef = self._getFacade(args);
       
 12642 
       
 12643         if (ons) {
       
 12644             self._procSubs(ons, args, ef);
       
 12645         }
       
 12646 
       
 12647         // bubble if this is hosted in an event target and propagation has not been stopped
       
 12648         if (self.bubbles && host.bubble && !self.stopped) {
       
 12649             oldbubble = es.bubbling;
       
 12650 
       
 12651             es.bubbling = self.type;
       
 12652 
       
 12653             if (es.type !== self.type) {
       
 12654                 es.stopped = 0;
       
 12655                 es.prevented = 0;
       
 12656             }
       
 12657 
       
 12658             ret = host.bubble(self, args, null, es);
       
 12659 
       
 12660             self.stopped = Math.max(self.stopped, es.stopped);
       
 12661             self.prevented = Math.max(self.prevented, es.prevented);
       
 12662 
       
 12663             es.bubbling = oldbubble;
       
 12664         }
       
 12665 
       
 12666         prevented = self.prevented;
       
 12667 
       
 12668         if (prevented) {
       
 12669             preventedFn = self.preventedFn;
       
 12670             if (preventedFn) {
       
 12671                 preventedFn.apply(host, args);
       
 12672             }
       
 12673         } else {
       
 12674             defaultFn = self.defaultFn;
       
 12675 
       
 12676             if (defaultFn && ((!self.defaultTargetOnly && !es.defaultTargetOnly) || host === ef.target)) {
       
 12677                 defaultFn.apply(host, args);
       
 12678             }
       
 12679         }
       
 12680 
       
 12681         // broadcast listeners are fired as discreet events on the
       
 12682         // YUI instance and potentially the YUI global.
       
 12683         if (self.broadcast) {
       
 12684             self._broadcast(args);
       
 12685         }
       
 12686 
       
 12687         if (afters && !self.prevented && self.stopped < 2) {
       
 12688 
       
 12689             // Queue the after
       
 12690             afterQueue = es.afterQueue;
       
 12691 
       
 12692             if (es.id === self.id || self.type !== yuievt.bubbling) {
       
 12693 
       
 12694                 self._procSubs(afters, args, ef);
       
 12695 
       
 12696                 if (afterQueue) {
       
 12697                     while ((next = afterQueue.last())) {
       
 12698                         next();
       
 12699                     }
       
 12700                 }
       
 12701             } else {
       
 12702                 postponed = afters;
       
 12703 
       
 12704                 if (es.execDefaultCnt) {
       
 12705                     postponed = Y.merge(postponed);
       
 12706 
       
 12707                     Y.each(postponed, function(s) {
       
 12708                         s.postponed = true;
       
 12709                     });
       
 12710                 }
       
 12711 
       
 12712                 if (!afterQueue) {
       
 12713                     es.afterQueue = new Y.Queue();
       
 12714                 }
       
 12715 
       
 12716                 es.afterQueue.add(function() {
       
 12717                     self._procSubs(postponed, args, ef);
       
 12718                 });
       
 12719             }
       
 12720 
       
 12721         }
       
 12722 
       
 12723         self.target = null;
       
 12724 
       
 12725         if (es.id === self.id) {
       
 12726 
       
 12727             queue = es.queue;
       
 12728 
       
 12729             if (queue) {
       
 12730                 while (queue.length) {
       
 12731                     q = queue.pop();
       
 12732                     ce = q[0];
       
 12733                     // set up stack to allow the next item to be processed
       
 12734                     es.next = ce;
       
 12735                     ce._fire(q[1]);
       
 12736                 }
       
 12737             }
       
 12738 
       
 12739             self.stack = null;
       
 12740         }
       
 12741 
       
 12742         ret = !(self.stopped);
       
 12743 
       
 12744         if (self.type !== yuievt.bubbling) {
       
 12745             es.stopped = 0;
       
 12746             es.prevented = 0;
       
 12747             self.stopped = 0;
       
 12748             self.prevented = 0;
       
 12749         }
       
 12750 
       
 12751     } else {
       
 12752         defaultFn = self.defaultFn;
       
 12753 
       
 12754         if(defaultFn) {
       
 12755             ef = self._getFacade(args);
       
 12756 
       
 12757             if ((!self.defaultTargetOnly) || (host === ef.target)) {
       
 12758                 defaultFn.apply(host, args);
       
 12759             }
       
 12760         }
       
 12761     }
       
 12762 
       
 12763     // Kill the cached facade to free up memory.
       
 12764     // Otherwise we have the facade from the last fire, sitting around forever.
       
 12765     self._facade = null;
       
 12766 
       
 12767     return ret;
       
 12768 };
       
 12769 
       
 12770 CEProto._getFacade = function(fireArgs) {
       
 12771 
       
 12772     var userArgs = this.details,
       
 12773         firstArg = userArgs && userArgs[0],
       
 12774         firstArgIsObj = (firstArg && (typeof firstArg === "object")),
       
 12775         ef = this._facade;
       
 12776 
       
 12777     if (!ef) {
       
 12778         ef = new Y.EventFacade(this, this.currentTarget);
       
 12779     }
       
 12780 
       
 12781     if (firstArgIsObj) {
       
 12782         // protect the event facade properties
       
 12783         mixFacadeProps(ef, firstArg);
       
 12784 
       
 12785         // Allow the event type to be faked http://yuilibrary.com/projects/yui3/ticket/2528376
       
 12786         if (firstArg.type) {
       
 12787             ef.type = firstArg.type;
       
 12788         }
       
 12789 
       
 12790         if (fireArgs) {
       
 12791             fireArgs[0] = ef;
       
 12792         }
       
 12793     } else {
       
 12794         if (fireArgs) {
       
 12795             fireArgs.unshift(ef);
       
 12796         }
       
 12797     }
       
 12798 
       
 12799     // update the details field with the arguments
       
 12800     ef.details = this.details;
       
 12801 
       
 12802     // use the original target when the event bubbled to this target
       
 12803     ef.target = this.originalTarget || this.target;
       
 12804 
       
 12805     ef.currentTarget = this.currentTarget;
       
 12806     ef.stopped = 0;
       
 12807     ef.prevented = 0;
       
 12808 
       
 12809     this._facade = ef;
       
 12810 
       
 12811     return this._facade;
       
 12812 };
       
 12813 
       
 12814 /**
       
 12815  * Stop propagation to bubble targets
       
 12816  * @for CustomEvent
       
 12817  * @method stopPropagation
       
 12818  */
       
 12819 CEProto.stopPropagation = function() {
       
 12820     this.stopped = 1;
       
 12821     if (this.stack) {
       
 12822         this.stack.stopped = 1;
       
 12823     }
       
 12824     if (this.events) {
       
 12825         this.events.fire('stopped', this);
       
 12826     }
       
 12827 };
       
 12828 
       
 12829 /**
       
 12830  * Stops propagation to bubble targets, and prevents any remaining
       
 12831  * subscribers on the current target from executing.
       
 12832  * @method stopImmediatePropagation
       
 12833  */
       
 12834 CEProto.stopImmediatePropagation = function() {
       
 12835     this.stopped = 2;
       
 12836     if (this.stack) {
       
 12837         this.stack.stopped = 2;
       
 12838     }
       
 12839     if (this.events) {
       
 12840         this.events.fire('stopped', this);
       
 12841     }
       
 12842 };
       
 12843 
       
 12844 /**
       
 12845  * Prevents the execution of this event's defaultFn
       
 12846  * @method preventDefault
       
 12847  */
       
 12848 CEProto.preventDefault = function() {
       
 12849     if (this.preventable) {
       
 12850         this.prevented = 1;
       
 12851         if (this.stack) {
       
 12852             this.stack.prevented = 1;
       
 12853         }
       
 12854     }
       
 12855 };
       
 12856 
       
 12857 /**
       
 12858  * Stops the event propagation and prevents the default
       
 12859  * event behavior.
       
 12860  * @method halt
       
 12861  * @param immediate {boolean} if true additional listeners
       
 12862  * on the current target will not be executed
       
 12863  */
       
 12864 CEProto.halt = function(immediate) {
       
 12865     if (immediate) {
       
 12866         this.stopImmediatePropagation();
       
 12867     } else {
       
 12868         this.stopPropagation();
       
 12869     }
       
 12870     this.preventDefault();
       
 12871 };
       
 12872 
       
 12873 /**
       
 12874  * Registers another EventTarget as a bubble target.  Bubble order
       
 12875  * is determined by the order registered.  Multiple targets can
       
 12876  * be specified.
       
 12877  *
       
 12878  * Events can only bubble if emitFacade is true.
       
 12879  *
       
 12880  * Included in the event-custom-complex submodule.
       
 12881  *
       
 12882  * @method addTarget
       
 12883  * @param o {EventTarget} the target to add
       
 12884  * @for EventTarget
       
 12885  */
       
 12886 ETProto.addTarget = function(o) {
       
 12887     var etState = this._yuievt;
       
 12888 
       
 12889     if (!etState.targets) {
       
 12890         etState.targets = {};
       
 12891     }
       
 12892 
       
 12893     etState.targets[Y.stamp(o)] = o;
       
 12894     etState.hasTargets = true;
       
 12895 };
       
 12896 
       
 12897 /**
       
 12898  * Returns an array of bubble targets for this object.
       
 12899  * @method getTargets
       
 12900  * @return EventTarget[]
       
 12901  */
       
 12902 ETProto.getTargets = function() {
       
 12903     var targets = this._yuievt.targets;
       
 12904     return targets ? YObject.values(targets) : [];
       
 12905 };
       
 12906 
       
 12907 /**
       
 12908  * Removes a bubble target
       
 12909  * @method removeTarget
       
 12910  * @param o {EventTarget} the target to remove
       
 12911  * @for EventTarget
       
 12912  */
       
 12913 ETProto.removeTarget = function(o) {
       
 12914     var targets = this._yuievt.targets;
       
 12915 
       
 12916     if (targets) {
       
 12917         delete targets[Y.stamp(o, true)];
       
 12918 
       
 12919         if (YObject.size(targets) === 0) {
       
 12920             this._yuievt.hasTargets = false;
       
 12921         }
       
 12922     }
       
 12923 };
       
 12924 
       
 12925 /**
       
 12926  * Propagate an event.  Requires the event-custom-complex module.
       
 12927  * @method bubble
       
 12928  * @param evt {CustomEvent} the custom event to propagate
       
 12929  * @return {boolean} the aggregated return value from Event.Custom.fire
       
 12930  * @for EventTarget
       
 12931  */
       
 12932 ETProto.bubble = function(evt, args, target, es) {
       
 12933 
       
 12934     var targs = this._yuievt.targets,
       
 12935         ret = true,
       
 12936         t,
       
 12937         ce,
       
 12938         i,
       
 12939         bc,
       
 12940         ce2,
       
 12941         type = evt && evt.type,
       
 12942         originalTarget = target || (evt && evt.target) || this,
       
 12943         oldbubble;
       
 12944 
       
 12945     if (!evt || ((!evt.stopped) && targs)) {
       
 12946 
       
 12947         for (i in targs) {
       
 12948             if (targs.hasOwnProperty(i)) {
       
 12949 
       
 12950                 t = targs[i];
       
 12951 
       
 12952                 ce = t._yuievt.events[type];
       
 12953 
       
 12954                 if (t._hasSiblings) {
       
 12955                     ce2 = t.getSibling(type, ce);
       
 12956                 }
       
 12957 
       
 12958                 if (ce2 && !ce) {
       
 12959                     ce = t.publish(type);
       
 12960                 }
       
 12961 
       
 12962                 oldbubble = t._yuievt.bubbling;
       
 12963                 t._yuievt.bubbling = type;
       
 12964 
       
 12965                 // if this event was not published on the bubble target,
       
 12966                 // continue propagating the event.
       
 12967                 if (!ce) {
       
 12968                     if (t._yuievt.hasTargets) {
       
 12969                         t.bubble(evt, args, originalTarget, es);
       
 12970                     }
       
 12971                 } else {
       
 12972 
       
 12973                     if (ce2) {
       
 12974                         ce.sibling = ce2;
       
 12975                     }
       
 12976 
       
 12977                     // set the original target to that the target payload on the facade is correct.
       
 12978                     ce.target = originalTarget;
       
 12979                     ce.originalTarget = originalTarget;
       
 12980                     ce.currentTarget = t;
       
 12981                     bc = ce.broadcast;
       
 12982                     ce.broadcast = false;
       
 12983 
       
 12984                     // default publish may not have emitFacade true -- that
       
 12985                     // shouldn't be what the implementer meant to do
       
 12986                     ce.emitFacade = true;
       
 12987 
       
 12988                     ce.stack = es;
       
 12989 
       
 12990                     // TODO: See what's getting in the way of changing this to use
       
 12991                     // the more performant ce._fire(args || evt.details || []).
       
 12992 
       
 12993                     // Something in Widget Parent/Child tests is not happy if we
       
 12994                     // change it - maybe evt.details related?
       
 12995                     ret = ret && ce.fire.apply(ce, args || evt.details || []);
       
 12996 
       
 12997                     ce.broadcast = bc;
       
 12998                     ce.originalTarget = null;
       
 12999 
       
 13000                     // stopPropagation() was called
       
 13001                     if (ce.stopped) {
       
 13002                         break;
       
 13003                     }
       
 13004                 }
       
 13005 
       
 13006                 t._yuievt.bubbling = oldbubble;
       
 13007             }
       
 13008         }
       
 13009     }
       
 13010 
       
 13011     return ret;
       
 13012 };
       
 13013 
       
 13014 FACADE = new Y.EventFacade();
       
 13015 FACADE_KEYS = {};
       
 13016 
       
 13017 // Flatten whitelist
       
 13018 for (key in FACADE) {
       
 13019     FACADE_KEYS[key] = true;
       
 13020 }
       
 13021 
       
 13022 
       
 13023 }, '@VERSION@', {"requires": ["event-custom-base"]});
       
 13024 YUI.add('node-core', function (Y, NAME) {
       
 13025 
       
 13026 /**
       
 13027  * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
       
 13028  * @module node
       
 13029  * @main node
       
 13030  * @submodule node-core
       
 13031  */
       
 13032 
       
 13033 /**
       
 13034  * The Node class provides a wrapper for manipulating DOM Nodes.
       
 13035  * Node properties can be accessed via the set/get methods.
       
 13036  * Use `Y.one()` to retrieve Node instances.
       
 13037  *
       
 13038  * <strong>NOTE:</strong> Node properties are accessed using
       
 13039  * the <code>set</code> and <code>get</code> methods.
       
 13040  *
       
 13041  * @class Node
       
 13042  * @constructor
       
 13043  * @param {DOMNode} node the DOM node to be mapped to the Node instance.
       
 13044  * @uses EventTarget
       
 13045  */
       
 13046 
       
 13047 // "globals"
       
 13048 var DOT = '.',
       
 13049     NODE_NAME = 'nodeName',
       
 13050     NODE_TYPE = 'nodeType',
       
 13051     OWNER_DOCUMENT = 'ownerDocument',
       
 13052     TAG_NAME = 'tagName',
       
 13053     UID = '_yuid',
       
 13054     EMPTY_OBJ = {},
       
 13055 
       
 13056     _slice = Array.prototype.slice,
       
 13057 
       
 13058     Y_DOM = Y.DOM,
       
 13059 
       
 13060     Y_Node = function(node) {
       
 13061         if (!this.getDOMNode) { // support optional "new"
       
 13062             return new Y_Node(node);
       
 13063         }
       
 13064 
       
 13065         if (typeof node == 'string') {
       
 13066             node = Y_Node._fromString(node);
       
 13067             if (!node) {
       
 13068                 return null; // NOTE: return
       
 13069             }
       
 13070         }
       
 13071 
       
 13072         var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID];
       
 13073 
       
 13074         if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) {
       
 13075             node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
       
 13076         }
       
 13077 
       
 13078         uid = uid || Y.stamp(node);
       
 13079         if (!uid) { // stamp failed; likely IE non-HTMLElement
       
 13080             uid = Y.guid();
       
 13081         }
       
 13082 
       
 13083         this[UID] = uid;
       
 13084 
       
 13085         /**
       
 13086          * The underlying DOM node bound to the Y.Node instance
       
 13087          * @property _node
       
 13088          * @type DOMNode
       
 13089          * @private
       
 13090          */
       
 13091         this._node = node;
       
 13092 
       
 13093         this._stateProxy = node; // when augmented with Attribute
       
 13094 
       
 13095         if (this._initPlugins) { // when augmented with Plugin.Host
       
 13096             this._initPlugins();
       
 13097         }
       
 13098     },
       
 13099 
       
 13100     // used with previous/next/ancestor tests
       
 13101     _wrapFn = function(fn) {
       
 13102         var ret = null;
       
 13103         if (fn) {
       
 13104             ret = (typeof fn == 'string') ?
       
 13105             function(n) {
       
 13106                 return Y.Selector.test(n, fn);
       
 13107             } :
       
 13108             function(n) {
       
 13109                 return fn(Y.one(n));
       
 13110             };
       
 13111         }
       
 13112 
       
 13113         return ret;
       
 13114     };
       
 13115 // end "globals"
       
 13116 
       
 13117 Y_Node.ATTRS = {};
       
 13118 Y_Node.DOM_EVENTS = {};
       
 13119 
       
 13120 Y_Node._fromString = function(node) {
       
 13121     if (node) {
       
 13122         if (node.indexOf('doc') === 0) { // doc OR document
       
 13123             node = Y.config.doc;
       
 13124         } else if (node.indexOf('win') === 0) { // win OR window
       
 13125             node = Y.config.win;
       
 13126         } else {
       
 13127             node = Y.Selector.query(node, null, true);
       
 13128         }
       
 13129     }
       
 13130 
       
 13131     return node || null;
       
 13132 };
       
 13133 
       
 13134 /**
       
 13135  * The name of the component
       
 13136  * @static
       
 13137  * @type String
       
 13138  * @property NAME
       
 13139  */
       
 13140 Y_Node.NAME = 'node';
       
 13141 
       
 13142 /*
       
 13143  * The pattern used to identify ARIA attributes
       
 13144  */
       
 13145 Y_Node.re_aria = /^(?:role$|aria-)/;
       
 13146 
       
 13147 Y_Node.SHOW_TRANSITION = 'fadeIn';
       
 13148 Y_Node.HIDE_TRANSITION = 'fadeOut';
       
 13149 
       
 13150 /**
       
 13151  * A list of Node instances that have been created
       
 13152  * @private
       
 13153  * @type Object
       
 13154  * @property _instances
       
 13155  * @static
       
 13156  *
       
 13157  */
       
 13158 Y_Node._instances = {};
       
 13159 
       
 13160 /**
       
 13161  * Retrieves the DOM node bound to a Node instance
       
 13162  * @method getDOMNode
       
 13163  * @static
       
 13164  *
       
 13165  * @param {Node | HTMLNode} node The Node instance or an HTMLNode
       
 13166  * @return {HTMLNode} The DOM node bound to the Node instance.  If a DOM node is passed
       
 13167  * as the node argument, it is simply returned.
       
 13168  */
       
 13169 Y_Node.getDOMNode = function(node) {
       
 13170     if (node) {
       
 13171         return (node.nodeType) ? node : node._node || null;
       
 13172     }
       
 13173     return null;
       
 13174 };
       
 13175 
       
 13176 /**
       
 13177  * Checks Node return values and wraps DOM Nodes as Y.Node instances
       
 13178  * and DOM Collections / Arrays as Y.NodeList instances.
       
 13179  * Other return values just pass thru.  If undefined is returned (e.g. no return)
       
 13180  * then the Node instance is returned for chainability.
       
 13181  * @method scrubVal
       
 13182  * @static
       
 13183  *
       
 13184  * @param {any} node The Node instance or an HTMLNode
       
 13185  * @return {Node | NodeList | Any} Depends on what is returned from the DOM node.
       
 13186  */
       
 13187 Y_Node.scrubVal = function(val, node) {
       
 13188     if (val) { // only truthy values are risky
       
 13189          if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function
       
 13190             if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window
       
 13191                 val = Y.one(val);
       
 13192             } else if ((val.item && !val._nodes) || // dom collection or Node instance
       
 13193                     (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
       
 13194                 val = Y.all(val);
       
 13195             }
       
 13196         }
       
 13197     } else if (typeof val === 'undefined') {
       
 13198         val = node; // for chaining
       
 13199     } else if (val === null) {
       
 13200         val = null; // IE: DOM null not the same as null
       
 13201     }
       
 13202 
       
 13203     return val;
       
 13204 };
       
 13205 
       
 13206 /**
       
 13207  * Adds methods to the Y.Node prototype, routing through scrubVal.
       
 13208  * @method addMethod
       
 13209  * @static
       
 13210  *
       
 13211  * @param {String} name The name of the method to add
       
 13212  * @param {Function} fn The function that becomes the method
       
 13213  * @param {Object} context An optional context to call the method with
       
 13214  * (defaults to the Node instance)
       
 13215  * @return {any} Depends on what is returned from the DOM node.
       
 13216  */
       
 13217 Y_Node.addMethod = function(name, fn, context) {
       
 13218     if (name && fn && typeof fn == 'function') {
       
 13219         Y_Node.prototype[name] = function() {
       
 13220             var args = _slice.call(arguments),
       
 13221                 node = this,
       
 13222                 ret;
       
 13223 
       
 13224             if (args[0] && args[0]._node) {
       
 13225                 args[0] = args[0]._node;
       
 13226             }
       
 13227 
       
 13228             if (args[1] && args[1]._node) {
       
 13229                 args[1] = args[1]._node;
       
 13230             }
       
 13231             args.unshift(node._node);
       
 13232 
       
 13233             ret = fn.apply(node, args);
       
 13234 
       
 13235             if (ret) { // scrub truthy
       
 13236                 ret = Y_Node.scrubVal(ret, node);
       
 13237             }
       
 13238 
       
 13239             (typeof ret != 'undefined') || (ret = node);
       
 13240             return ret;
       
 13241         };
       
 13242     } else {
       
 13243         Y.log('unable to add method: ' + name, 'warn', 'Node');
       
 13244     }
       
 13245 };
       
 13246 
       
 13247 /**
       
 13248  * Imports utility methods to be added as Y.Node methods.
       
 13249  * @method importMethod
       
 13250  * @static
       
 13251  *
       
 13252  * @param {Object} host The object that contains the method to import.
       
 13253  * @param {String} name The name of the method to import
       
 13254  * @param {String} altName An optional name to use in place of the host name
       
 13255  * @param {Object} context An optional context to call the method with
       
 13256  */
       
 13257 Y_Node.importMethod = function(host, name, altName) {
       
 13258     if (typeof name == 'string') {
       
 13259         altName = altName || name;
       
 13260         Y_Node.addMethod(altName, host[name], host);
       
 13261     } else {
       
 13262         Y.Array.each(name, function(n) {
       
 13263             Y_Node.importMethod(host, n);
       
 13264         });
       
 13265     }
       
 13266 };
       
 13267 
       
 13268 /**
       
 13269  * Retrieves a NodeList based on the given CSS selector.
       
 13270  * @method all
       
 13271  *
       
 13272  * @param {string} selector The CSS selector to test against.
       
 13273  * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
 13274  * @for YUI
       
 13275  */
       
 13276 
       
 13277 /**
       
 13278  * Returns a single Node instance bound to the node or the
       
 13279  * first element matching the given selector. Returns null if no match found.
       
 13280  * <strong>Note:</strong> For chaining purposes you may want to
       
 13281  * use <code>Y.all</code>, which returns a NodeList when no match is found.
       
 13282  * @method one
       
 13283  * @param {String | HTMLElement} node a node or Selector
       
 13284  * @return {Node | null} a Node instance or null if no match found.
       
 13285  * @for YUI
       
 13286  */
       
 13287 
       
 13288 /**
       
 13289  * Returns a single Node instance bound to the node or the
       
 13290  * first element matching the given selector. Returns null if no match found.
       
 13291  * <strong>Note:</strong> For chaining purposes you may want to
       
 13292  * use <code>Y.all</code>, which returns a NodeList when no match is found.
       
 13293  * @method one
       
 13294  * @static
       
 13295  * @param {String | HTMLElement} node a node or Selector
       
 13296  * @return {Node | null} a Node instance or null if no match found.
       
 13297  * @for Node
       
 13298  */
       
 13299 Y_Node.one = function(node) {
       
 13300     var instance = null,
       
 13301         cachedNode,
       
 13302         uid;
       
 13303 
       
 13304     if (node) {
       
 13305         if (typeof node == 'string') {
       
 13306             node = Y_Node._fromString(node);
       
 13307             if (!node) {
       
 13308                 return null; // NOTE: return
       
 13309             }
       
 13310         } else if (node.getDOMNode) {
       
 13311             return node; // NOTE: return
       
 13312         }
       
 13313 
       
 13314         if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc)
       
 13315             uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid;
       
 13316             instance = Y_Node._instances[uid]; // reuse exising instances
       
 13317             cachedNode = instance ? instance._node : null;
       
 13318             if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
       
 13319                 instance = new Y_Node(node);
       
 13320                 if (node.nodeType != 11) { // dont cache document fragment
       
 13321                     Y_Node._instances[instance[UID]] = instance; // cache node
       
 13322                 }
       
 13323             }
       
 13324         }
       
 13325     }
       
 13326 
       
 13327     return instance;
       
 13328 };
       
 13329 
       
 13330 /**
       
 13331  * The default setter for DOM properties
       
 13332  * Called with instance context (this === the Node instance)
       
 13333  * @method DEFAULT_SETTER
       
 13334  * @static
       
 13335  * @param {String} name The attribute/property being set
       
 13336  * @param {any} val The value to be set
       
 13337  * @return {any} The value
       
 13338  */
       
 13339 Y_Node.DEFAULT_SETTER = function(name, val) {
       
 13340     var node = this._stateProxy,
       
 13341         strPath;
       
 13342 
       
 13343     if (name.indexOf(DOT) > -1) {
       
 13344         strPath = name;
       
 13345         name = name.split(DOT);
       
 13346         // only allow when defined on node
       
 13347         Y.Object.setValue(node, name, val);
       
 13348     } else if (typeof node[name] != 'undefined') { // pass thru DOM properties
       
 13349         node[name] = val;
       
 13350     }
       
 13351 
       
 13352     return val;
       
 13353 };
       
 13354 
       
 13355 /**
       
 13356  * The default getter for DOM properties
       
 13357  * Called with instance context (this === the Node instance)
       
 13358  * @method DEFAULT_GETTER
       
 13359  * @static
       
 13360  * @param {String} name The attribute/property to look up
       
 13361  * @return {any} The current value
       
 13362  */
       
 13363 Y_Node.DEFAULT_GETTER = function(name) {
       
 13364     var node = this._stateProxy,
       
 13365         val;
       
 13366 
       
 13367     if (name.indexOf && name.indexOf(DOT) > -1) {
       
 13368         val = Y.Object.getValue(node, name.split(DOT));
       
 13369     } else if (typeof node[name] != 'undefined') { // pass thru from DOM
       
 13370         val = node[name];
       
 13371     }
       
 13372 
       
 13373     return val;
       
 13374 };
       
 13375 
       
 13376 Y.mix(Y_Node.prototype, {
       
 13377     DATA_PREFIX: 'data-',
       
 13378 
       
 13379     /**
       
 13380      * The method called when outputting Node instances as strings
       
 13381      * @method toString
       
 13382      * @return {String} A string representation of the Node instance
       
 13383      */
       
 13384     toString: function() {
       
 13385         var str = this[UID] + ': not bound to a node',
       
 13386             node = this._node,
       
 13387             attrs, id, className;
       
 13388 
       
 13389         if (node) {
       
 13390             attrs = node.attributes;
       
 13391             id = (attrs && attrs.id) ? node.getAttribute('id') : null;
       
 13392             className = (attrs && attrs.className) ? node.getAttribute('className') : null;
       
 13393             str = node[NODE_NAME];
       
 13394 
       
 13395             if (id) {
       
 13396                 str += '#' + id;
       
 13397             }
       
 13398 
       
 13399             if (className) {
       
 13400                 str += '.' + className.replace(' ', '.');
       
 13401             }
       
 13402 
       
 13403             // TODO: add yuid?
       
 13404             str += ' ' + this[UID];
       
 13405         }
       
 13406         return str;
       
 13407     },
       
 13408 
       
 13409     /**
       
 13410      * Returns an attribute value on the Node instance.
       
 13411      * Unless pre-configured (via `Node.ATTRS`), get hands
       
 13412      * off to the underlying DOM node.  Only valid
       
 13413      * attributes/properties for the node will be queried.
       
 13414      * @method get
       
 13415      * @param {String} attr The attribute
       
 13416      * @return {any} The current value of the attribute
       
 13417      */
       
 13418     get: function(attr) {
       
 13419         var val;
       
 13420 
       
 13421         if (this._getAttr) { // use Attribute imple
       
 13422             val = this._getAttr(attr);
       
 13423         } else {
       
 13424             val = this._get(attr);
       
 13425         }
       
 13426 
       
 13427         if (val) {
       
 13428             val = Y_Node.scrubVal(val, this);
       
 13429         } else if (val === null) {
       
 13430             val = null; // IE: DOM null is not true null (even though they ===)
       
 13431         }
       
 13432         return val;
       
 13433     },
       
 13434 
       
 13435     /**
       
 13436      * Helper method for get.
       
 13437      * @method _get
       
 13438      * @private
       
 13439      * @param {String} attr The attribute
       
 13440      * @return {any} The current value of the attribute
       
 13441      */
       
 13442     _get: function(attr) {
       
 13443         var attrConfig = Y_Node.ATTRS[attr],
       
 13444             val;
       
 13445 
       
 13446         if (attrConfig && attrConfig.getter) {
       
 13447             val = attrConfig.getter.call(this);
       
 13448         } else if (Y_Node.re_aria.test(attr)) {
       
 13449             val = this._node.getAttribute(attr, 2);
       
 13450         } else {
       
 13451             val = Y_Node.DEFAULT_GETTER.apply(this, arguments);
       
 13452         }
       
 13453 
       
 13454         return val;
       
 13455     },
       
 13456 
       
 13457     /**
       
 13458      * Sets an attribute on the Node instance.
       
 13459      * Unless pre-configured (via Node.ATTRS), set hands
       
 13460      * off to the underlying DOM node.  Only valid
       
 13461      * attributes/properties for the node will be set.
       
 13462      * To set custom attributes use setAttribute.
       
 13463      * @method set
       
 13464      * @param {String} attr The attribute to be set.
       
 13465      * @param {any} val The value to set the attribute to.
       
 13466      * @chainable
       
 13467      */
       
 13468     set: function(attr, val) {
       
 13469         var attrConfig = Y_Node.ATTRS[attr];
       
 13470 
       
 13471         if (this._setAttr) { // use Attribute imple
       
 13472             this._setAttr.apply(this, arguments);
       
 13473         } else { // use setters inline
       
 13474             if (attrConfig && attrConfig.setter) {
       
 13475                 attrConfig.setter.call(this, val, attr);
       
 13476             } else if (Y_Node.re_aria.test(attr)) { // special case Aria
       
 13477                 this._node.setAttribute(attr, val);
       
 13478             } else {
       
 13479                 Y_Node.DEFAULT_SETTER.apply(this, arguments);
       
 13480             }
       
 13481         }
       
 13482 
       
 13483         return this;
       
 13484     },
       
 13485 
       
 13486     /**
       
 13487      * Sets multiple attributes.
       
 13488      * @method setAttrs
       
 13489      * @param {Object} attrMap an object of name/value pairs to set
       
 13490      * @chainable
       
 13491      */
       
 13492     setAttrs: function(attrMap) {
       
 13493         if (this._setAttrs) { // use Attribute imple
       
 13494             this._setAttrs(attrMap);
       
 13495         } else { // use setters inline
       
 13496             Y.Object.each(attrMap, function(v, n) {
       
 13497                 this.set(n, v);
       
 13498             }, this);
       
 13499         }
       
 13500 
       
 13501         return this;
       
 13502     },
       
 13503 
       
 13504     /**
       
 13505      * Returns an object containing the values for the requested attributes.
       
 13506      * @method getAttrs
       
 13507      * @param {Array} attrs an array of attributes to get values
       
 13508      * @return {Object} An object with attribute name/value pairs.
       
 13509      */
       
 13510     getAttrs: function(attrs) {
       
 13511         var ret = {};
       
 13512         if (this._getAttrs) { // use Attribute imple
       
 13513             this._getAttrs(attrs);
       
 13514         } else { // use setters inline
       
 13515             Y.Array.each(attrs, function(v, n) {
       
 13516                 ret[v] = this.get(v);
       
 13517             }, this);
       
 13518         }
       
 13519 
       
 13520         return ret;
       
 13521     },
       
 13522 
       
 13523     /**
       
 13524      * Compares nodes to determine if they match.
       
 13525      * Node instances can be compared to each other and/or HTMLElements.
       
 13526      * @method compareTo
       
 13527      * @param {HTMLElement | Node} refNode The reference node to compare to the node.
       
 13528      * @return {Boolean} True if the nodes match, false if they do not.
       
 13529      */
       
 13530     compareTo: function(refNode) {
       
 13531         var node = this._node;
       
 13532 
       
 13533         if (refNode && refNode._node) {
       
 13534             refNode = refNode._node;
       
 13535         }
       
 13536         return node === refNode;
       
 13537     },
       
 13538 
       
 13539     /**
       
 13540      * Determines whether the node is appended to the document.
       
 13541      * @method inDoc
       
 13542      * @param {Node|HTMLElement} doc optional An optional document to check against.
       
 13543      * Defaults to current document.
       
 13544      * @return {Boolean} Whether or not this node is appended to the document.
       
 13545      */
       
 13546     inDoc: function(doc) {
       
 13547         var node = this._node;
       
 13548         doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
       
 13549         if (doc.documentElement) {
       
 13550             return Y_DOM.contains(doc.documentElement, node);
       
 13551         }
       
 13552     },
       
 13553 
       
 13554     getById: function(id) {
       
 13555         var node = this._node,
       
 13556             ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]);
       
 13557         if (ret && Y_DOM.contains(node, ret)) {
       
 13558             ret = Y.one(ret);
       
 13559         } else {
       
 13560             ret = null;
       
 13561         }
       
 13562         return ret;
       
 13563     },
       
 13564 
       
 13565    /**
       
 13566      * Returns the nearest ancestor that passes the test applied by supplied boolean method.
       
 13567      * @method ancestor
       
 13568      * @param {String | Function} fn A selector string or boolean method for testing elements.
       
 13569      * If a function is used, it receives the current node being tested as the only argument.
       
 13570      * If fn is not passed as an argument, the parent node will be returned.
       
 13571      * @param {Boolean} testSelf optional Whether or not to include the element in the scan
       
 13572      * @param {String | Function} stopFn optional A selector string or boolean
       
 13573      * method to indicate when the search should stop. The search bails when the function
       
 13574      * returns true or the selector matches.
       
 13575      * If a function is used, it receives the current node being tested as the only argument.
       
 13576      * @return {Node} The matching Node instance or null if not found
       
 13577      */
       
 13578     ancestor: function(fn, testSelf, stopFn) {
       
 13579         // testSelf is optional, check for stopFn as 2nd arg
       
 13580         if (arguments.length === 2 &&
       
 13581                 (typeof testSelf == 'string' || typeof testSelf == 'function')) {
       
 13582             stopFn = testSelf;
       
 13583         }
       
 13584 
       
 13585         return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
       
 13586     },
       
 13587 
       
 13588    /**
       
 13589      * Returns the ancestors that pass the test applied by supplied boolean method.
       
 13590      * @method ancestors
       
 13591      * @param {String | Function} fn A selector string or boolean method for testing elements.
       
 13592      * @param {Boolean} testSelf optional Whether or not to include the element in the scan
       
 13593      * If a function is used, it receives the current node being tested as the only argument.
       
 13594      * @return {NodeList} A NodeList instance containing the matching elements
       
 13595      */
       
 13596     ancestors: function(fn, testSelf, stopFn) {
       
 13597         if (arguments.length === 2 &&
       
 13598                 (typeof testSelf == 'string' || typeof testSelf == 'function')) {
       
 13599             stopFn = testSelf;
       
 13600         }
       
 13601         return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
       
 13602     },
       
 13603 
       
 13604     /**
       
 13605      * Returns the previous matching sibling.
       
 13606      * Returns the nearest element node sibling if no method provided.
       
 13607      * @method previous
       
 13608      * @param {String | Function} fn A selector or boolean method for testing elements.
       
 13609      * If a function is used, it receives the current node being tested as the only argument.
       
 13610      * @return {Node} Node instance or null if not found
       
 13611      */
       
 13612     previous: function(fn, all) {
       
 13613         return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
       
 13614     },
       
 13615 
       
 13616     /**
       
 13617      * Returns the next matching sibling.
       
 13618      * Returns the nearest element node sibling if no method provided.
       
 13619      * @method next
       
 13620      * @param {String | Function} fn A selector or boolean method for testing elements.
       
 13621      * If a function is used, it receives the current node being tested as the only argument.
       
 13622      * @return {Node} Node instance or null if not found
       
 13623      */
       
 13624     next: function(fn, all) {
       
 13625         return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
       
 13626     },
       
 13627 
       
 13628     /**
       
 13629      * Returns all matching siblings.
       
 13630      * Returns all siblings if no method provided.
       
 13631      * @method siblings
       
 13632      * @param {String | Function} fn A selector or boolean method for testing elements.
       
 13633      * If a function is used, it receives the current node being tested as the only argument.
       
 13634      * @return {NodeList} NodeList instance bound to found siblings
       
 13635      */
       
 13636     siblings: function(fn) {
       
 13637         return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn)));
       
 13638     },
       
 13639 
       
 13640     /**
       
 13641      * Retrieves a single Node instance, the first element matching the given 
       
 13642      * CSS selector.
       
 13643      * Returns null if no match found.
       
 13644      * @method one
       
 13645      *
       
 13646      * @param {string} selector The CSS selector to test against.
       
 13647      * @return {Node | null} A Node instance for the matching HTMLElement or null 
       
 13648      * if no match found.
       
 13649      */
       
 13650     one: function(selector) {
       
 13651         return Y.one(Y.Selector.query(selector, this._node, true));
       
 13652     },
       
 13653 
       
 13654     /**
       
 13655      * Retrieves a NodeList based on the given CSS selector.
       
 13656      * @method all
       
 13657      *
       
 13658      * @param {string} selector The CSS selector to test against.
       
 13659      * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
       
 13660      */
       
 13661     all: function(selector) {
       
 13662         var nodelist;
       
 13663         
       
 13664         if (this._node) {
       
 13665             nodelist = Y.all(Y.Selector.query(selector, this._node));
       
 13666             nodelist._query = selector;
       
 13667             nodelist._queryRoot = this._node;
       
 13668         }
       
 13669 
       
 13670         return nodelist || Y.all([]);
       
 13671     },
       
 13672 
       
 13673     // TODO: allow fn test
       
 13674     /**
       
 13675      * Test if the supplied node matches the supplied selector.
       
 13676      * @method test
       
 13677      *
       
 13678      * @param {string} selector The CSS selector to test against.
       
 13679      * @return {boolean} Whether or not the node matches the selector.
       
 13680      */
       
 13681     test: function(selector) {
       
 13682         return Y.Selector.test(this._node, selector);
       
 13683     },
       
 13684 
       
 13685     /**
       
 13686      * Removes the node from its parent.
       
 13687      * Shortcut for myNode.get('parentNode').removeChild(myNode);
       
 13688      * @method remove
       
 13689      * @param {Boolean} destroy whether or not to call destroy() on the node
       
 13690      * after removal.
       
 13691      * @chainable
       
 13692      *
       
 13693      */
       
 13694     remove: function(destroy) {
       
 13695         var node = this._node;
       
 13696 
       
 13697         if (node && node.parentNode) {
       
 13698             node.parentNode.removeChild(node);
       
 13699         }
       
 13700 
       
 13701         if (destroy) {
       
 13702             this.destroy();
       
 13703         }
       
 13704 
       
 13705         return this;
       
 13706     },
       
 13707 
       
 13708     /**
       
 13709      * Replace the node with the other node. This is a DOM update only
       
 13710      * and does not change the node bound to the Node instance.
       
 13711      * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
       
 13712      * @method replace
       
 13713      * @param {Node | HTMLNode} newNode Node to be inserted
       
 13714      * @chainable
       
 13715      *
       
 13716      */
       
 13717     replace: function(newNode) {
       
 13718         var node = this._node;
       
 13719         if (typeof newNode == 'string') {
       
 13720             newNode = Y_Node.create(newNode);
       
 13721         }
       
 13722         node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node);
       
 13723         return this;
       
 13724     },
       
 13725 
       
 13726     /**
       
 13727      * @method replaceChild
       
 13728      * @for Node
       
 13729      * @param {String | HTMLElement | Node} node Node to be inserted
       
 13730      * @param {HTMLElement | Node} refNode Node to be replaced
       
 13731      * @return {Node} The replaced node
       
 13732      */
       
 13733     replaceChild: function(node, refNode) {
       
 13734         if (typeof node == 'string') {
       
 13735             node = Y_DOM.create(node);
       
 13736         }
       
 13737 
       
 13738         return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode)));
       
 13739     },
       
 13740 
       
 13741     /**
       
 13742      * Nulls internal node references, removes any plugins and event listeners.
       
 13743      * Note that destroy() will not remove the node from its parent or from the DOM. For that
       
 13744      * functionality, call remove(true).
       
 13745      * @method destroy
       
 13746      * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the
       
 13747      * node's subtree (default is false)
       
 13748      *
       
 13749      */
       
 13750     destroy: function(recursive) {
       
 13751         var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid',
       
 13752             instance;
       
 13753 
       
 13754         this.purge(); // TODO: only remove events add via this Node
       
 13755 
       
 13756         if (this.unplug) { // may not be a PluginHost
       
 13757             this.unplug();
       
 13758         }
       
 13759 
       
 13760         this.clearData();
       
 13761 
       
 13762         if (recursive) {
       
 13763             Y.NodeList.each(this.all('*'), function(node) {
       
 13764                 instance = Y_Node._instances[node[UID]];
       
 13765                 if (instance) {
       
 13766                    instance.destroy();
       
 13767                 } else { // purge in case added by other means
       
 13768                     Y.Event.purgeElement(node);
       
 13769                 }
       
 13770             });
       
 13771         }
       
 13772 
       
 13773         this._node = null;
       
 13774         this._stateProxy = null;
       
 13775 
       
 13776         delete Y_Node._instances[this._yuid];
       
 13777     },
       
 13778 
       
 13779     /**
       
 13780      * Invokes a method on the Node instance
       
 13781      * @method invoke
       
 13782      * @param {String} method The name of the method to invoke
       
 13783      * @param {Any}  a, b, c, etc. Arguments to invoke the method with.
       
 13784      * @return Whatever the underly method returns.
       
 13785      * DOM Nodes and Collections return values
       
 13786      * are converted to Node/NodeList instances.
       
 13787      *
       
 13788      */
       
 13789     invoke: function(method, a, b, c, d, e) {
       
 13790         var node = this._node,
       
 13791             ret;
       
 13792 
       
 13793         if (a && a._node) {
       
 13794             a = a._node;
       
 13795         }
       
 13796 
       
 13797         if (b && b._node) {
       
 13798             b = b._node;
       
 13799         }
       
 13800 
       
 13801         ret = node[method](a, b, c, d, e);
       
 13802         return Y_Node.scrubVal(ret, this);
       
 13803     },
       
 13804 
       
 13805     /**
       
 13806     * @method swap
       
 13807     * @description Swap DOM locations with the given node.
       
 13808     * This does not change which DOM node each Node instance refers to.
       
 13809     * @param {Node} otherNode The node to swap with
       
 13810      * @chainable
       
 13811     */
       
 13812     swap: Y.config.doc.documentElement.swapNode ?
       
 13813         function(otherNode) {
       
 13814             this._node.swapNode(Y_Node.getDOMNode(otherNode));
       
 13815         } :
       
 13816         function(otherNode) {
       
 13817             otherNode = Y_Node.getDOMNode(otherNode);
       
 13818             var node = this._node,
       
 13819                 parent = otherNode.parentNode,
       
 13820                 nextSibling = otherNode.nextSibling;
       
 13821 
       
 13822             if (nextSibling === node) {
       
 13823                 parent.insertBefore(node, otherNode);
       
 13824             } else if (otherNode === node.nextSibling) {
       
 13825                 parent.insertBefore(otherNode, node);
       
 13826             } else {
       
 13827                 node.parentNode.replaceChild(otherNode, node);
       
 13828                 Y_DOM.addHTML(parent, node, nextSibling);
       
 13829             }
       
 13830             return this;
       
 13831         },
       
 13832 
       
 13833 
       
 13834     hasMethod: function(method) {
       
 13835         var node = this._node;
       
 13836         return !!(node && method in node &&
       
 13837                 typeof node[method] != 'unknown' &&
       
 13838             (typeof node[method] == 'function' ||
       
 13839                 String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space
       
 13840     },
       
 13841 
       
 13842     isFragment: function() {
       
 13843         return (this.get('nodeType') === 11);
       
 13844     },
       
 13845 
       
 13846     /**
       
 13847      * Removes and destroys all of the nodes within the node.
       
 13848      * @method empty
       
 13849      * @chainable
       
 13850      */
       
 13851     empty: function() {
       
 13852         this.get('childNodes').remove().destroy(true);
       
 13853         return this;
       
 13854     },
       
 13855 
       
 13856     /**
       
 13857      * Returns the DOM node bound to the Node instance
       
 13858      * @method getDOMNode
       
 13859      * @return {DOMNode}
       
 13860      */
       
 13861     getDOMNode: function() {
       
 13862         return this._node;
       
 13863     }
       
 13864 }, true);
       
 13865 
       
 13866 Y.Node = Y_Node;
       
 13867 Y.one = Y_Node.one;
       
 13868 /**
       
 13869  * The NodeList module provides support for managing collections of Nodes.
       
 13870  * @module node
       
 13871  * @submodule node-core
       
 13872  */
       
 13873 
       
 13874 /**
       
 13875  * The NodeList class provides a wrapper for manipulating DOM NodeLists.
       
 13876  * NodeList properties can be accessed via the set/get methods.
       
 13877  * Use Y.all() to retrieve NodeList instances.
       
 13878  *
       
 13879  * @class NodeList
       
 13880  * @constructor
       
 13881  * @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.
       
 13882  */
       
 13883 
       
 13884 var NodeList = function(nodes) {
       
 13885     var tmp = [];
       
 13886 
       
 13887     if (nodes) {
       
 13888         if (typeof nodes === 'string') { // selector query
       
 13889             this._query = nodes;
       
 13890             nodes = Y.Selector.query(nodes);
       
 13891         } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window
       
 13892             nodes = [nodes];
       
 13893         } else if (nodes._node) { // Y.Node
       
 13894             nodes = [nodes._node];
       
 13895         } else if (nodes[0] && nodes[0]._node) { // allow array of Y.Nodes
       
 13896             Y.Array.each(nodes, function(node) {
       
 13897                 if (node._node) {
       
 13898                     tmp.push(node._node);
       
 13899                 }
       
 13900             });
       
 13901             nodes = tmp;
       
 13902         } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes)
       
 13903             nodes = Y.Array(nodes, 0, true);
       
 13904         }
       
 13905     }
       
 13906 
       
 13907     /**
       
 13908      * The underlying array of DOM nodes bound to the Y.NodeList instance
       
 13909      * @property _nodes
       
 13910      * @private
       
 13911      */
       
 13912     this._nodes = nodes || [];
       
 13913 };
       
 13914 
       
 13915 NodeList.NAME = 'NodeList';
       
 13916 
       
 13917 /**
       
 13918  * Retrieves the DOM nodes bound to a NodeList instance
       
 13919  * @method getDOMNodes
       
 13920  * @static
       
 13921  *
       
 13922  * @param {NodeList} nodelist The NodeList instance
       
 13923  * @return {Array} The array of DOM nodes bound to the NodeList
       
 13924  */
       
 13925 NodeList.getDOMNodes = function(nodelist) {
       
 13926     return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist;
       
 13927 };
       
 13928 
       
 13929 NodeList.each = function(instance, fn, context) {
       
 13930     var nodes = instance._nodes;
       
 13931     if (nodes && nodes.length) {
       
 13932         Y.Array.each(nodes, fn, context || instance);
       
 13933     } else {
       
 13934         Y.log('no nodes bound to ' + this, 'warn', 'NodeList');
       
 13935     }
       
 13936 };
       
 13937 
       
 13938 NodeList.addMethod = function(name, fn, context) {
       
 13939     if (name && fn) {
       
 13940         NodeList.prototype[name] = function() {
       
 13941             var ret = [],
       
 13942                 args = arguments;
       
 13943 
       
 13944             Y.Array.each(this._nodes, function(node) {
       
 13945                 var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid',
       
 13946                     instance = Y.Node._instances[node[UID]],
       
 13947                     ctx,
       
 13948                     result;
       
 13949 
       
 13950                 if (!instance) {
       
 13951                     instance = NodeList._getTempNode(node);
       
 13952                 }
       
 13953                 ctx = context || instance;
       
 13954                 result = fn.apply(ctx, args);
       
 13955                 if (result !== undefined && result !== instance) {
       
 13956                     ret[ret.length] = result;
       
 13957                 }
       
 13958             });
       
 13959 
       
 13960             // TODO: remove tmp pointer
       
 13961             return ret.length ? ret : this;
       
 13962         };
       
 13963     } else {
       
 13964         Y.log('unable to add method: ' + name + ' to NodeList', 'warn', 'node');
       
 13965     }
       
 13966 };
       
 13967 
       
 13968 NodeList.importMethod = function(host, name, altName) {
       
 13969     if (typeof name === 'string') {
       
 13970         altName = altName || name;
       
 13971         NodeList.addMethod(name, host[name]);
       
 13972     } else {
       
 13973         Y.Array.each(name, function(n) {
       
 13974             NodeList.importMethod(host, n);
       
 13975         });
       
 13976     }
       
 13977 };
       
 13978 
       
 13979 NodeList._getTempNode = function(node) {
       
 13980     var tmp = NodeList._tempNode;
       
 13981     if (!tmp) {
       
 13982         tmp = Y.Node.create('<div></div>');
       
 13983         NodeList._tempNode = tmp;
       
 13984     }
       
 13985 
       
 13986     tmp._node = node;
       
 13987     tmp._stateProxy = node;
       
 13988     return tmp;
       
 13989 };
       
 13990 
       
 13991 Y.mix(NodeList.prototype, {
       
 13992     _invoke: function(method, args, getter) {
       
 13993         var ret = (getter) ? [] : this;
       
 13994 
       
 13995         this.each(function(node) {
       
 13996             var val = node[method].apply(node, args);
       
 13997             if (getter) {
       
 13998                 ret.push(val);
       
 13999             }
       
 14000         });
       
 14001 
       
 14002         return ret;
       
 14003     },
       
 14004 
       
 14005     /**
       
 14006      * Retrieves the Node instance at the given index.
       
 14007      * @method item
       
 14008      *
       
 14009      * @param {Number} index The index of the target Node.
       
 14010      * @return {Node} The Node instance at the given index.
       
 14011      */
       
 14012     item: function(index) {
       
 14013         return Y.one((this._nodes || [])[index]);
       
 14014     },
       
 14015 
       
 14016     /**
       
 14017      * Applies the given function to each Node in the NodeList.
       
 14018      * @method each
       
 14019      * @param {Function} fn The function to apply. It receives 3 arguments:
       
 14020      * the current node instance, the node's index, and the NodeList instance
       
 14021      * @param {Object} context optional An optional context to apply the function with
       
 14022      * Default context is the current Node instance
       
 14023      * @chainable
       
 14024      */
       
 14025     each: function(fn, context) {
       
 14026         var instance = this;
       
 14027         Y.Array.each(this._nodes, function(node, index) {
       
 14028             node = Y.one(node);
       
 14029             return fn.call(context || node, node, index, instance);
       
 14030         });
       
 14031         return instance;
       
 14032     },
       
 14033 
       
 14034     batch: function(fn, context) {
       
 14035         var nodelist = this;
       
 14036 
       
 14037         Y.Array.each(this._nodes, function(node, index) {
       
 14038             var instance = Y.Node._instances[node[UID]];
       
 14039             if (!instance) {
       
 14040                 instance = NodeList._getTempNode(node);
       
 14041             }
       
 14042 
       
 14043             return fn.call(context || instance, instance, index, nodelist);
       
 14044         });
       
 14045         return nodelist;
       
 14046     },
       
 14047 
       
 14048     /**
       
 14049      * Executes the function once for each node until a true value is returned.
       
 14050      * @method some
       
 14051      * @param {Function} fn The function to apply. It receives 3 arguments:
       
 14052      * the current node instance, the node's index, and the NodeList instance
       
 14053      * @param {Object} context optional An optional context to execute the function from.
       
 14054      * Default context is the current Node instance
       
 14055      * @return {Boolean} Whether or not the function returned true for any node.
       
 14056      */
       
 14057     some: function(fn, context) {
       
 14058         var instance = this;
       
 14059         return Y.Array.some(this._nodes, function(node, index) {
       
 14060             node = Y.one(node);
       
 14061             context = context || node;
       
 14062             return fn.call(context, node, index, instance);
       
 14063         });
       
 14064     },
       
 14065 
       
 14066     /**
       
 14067      * Creates a documenFragment from the nodes bound to the NodeList instance
       
 14068      * @method toFrag
       
 14069      * @return {Node} a Node instance bound to the documentFragment
       
 14070      */
       
 14071     toFrag: function() {
       
 14072         return Y.one(Y.DOM._nl2frag(this._nodes));
       
 14073     },
       
 14074 
       
 14075     /**
       
 14076      * Returns the index of the node in the NodeList instance
       
 14077      * or -1 if the node isn't found.
       
 14078      * @method indexOf
       
 14079      * @param {Node | DOMNode} node the node to search for
       
 14080      * @return {Int} the index of the node value or -1 if not found
       
 14081      */
       
 14082     indexOf: function(node) {
       
 14083         return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
       
 14084     },
       
 14085 
       
 14086     /**
       
 14087      * Filters the NodeList instance down to only nodes matching the given selector.
       
 14088      * @method filter
       
 14089      * @param {String} selector The selector to filter against
       
 14090      * @return {NodeList} NodeList containing the updated collection
       
 14091      * @see Selector
       
 14092      */
       
 14093     filter: function(selector) {
       
 14094         return Y.all(Y.Selector.filter(this._nodes, selector));
       
 14095     },
       
 14096 
       
 14097 
       
 14098     /**
       
 14099      * Creates a new NodeList containing all nodes at every n indices, where
       
 14100      * remainder n % index equals r.
       
 14101      * (zero-based index).
       
 14102      * @method modulus
       
 14103      * @param {Int} n The offset to use (return every nth node)
       
 14104      * @param {Int} r An optional remainder to use with the modulus operation (defaults to zero)
       
 14105      * @return {NodeList} NodeList containing the updated collection
       
 14106      */
       
 14107     modulus: function(n, r) {
       
 14108         r = r || 0;
       
 14109         var nodes = [];
       
 14110         NodeList.each(this, function(node, i) {
       
 14111             if (i % n === r) {
       
 14112                 nodes.push(node);
       
 14113             }
       
 14114         });
       
 14115 
       
 14116         return Y.all(nodes);
       
 14117     },
       
 14118 
       
 14119     /**
       
 14120      * Creates a new NodeList containing all nodes at odd indices
       
 14121      * (zero-based index).
       
 14122      * @method odd
       
 14123      * @return {NodeList} NodeList containing the updated collection
       
 14124      */
       
 14125     odd: function() {
       
 14126         return this.modulus(2, 1);
       
 14127     },
       
 14128 
       
 14129     /**
       
 14130      * Creates a new NodeList containing all nodes at even indices
       
 14131      * (zero-based index), including zero.
       
 14132      * @method even
       
 14133      * @return {NodeList} NodeList containing the updated collection
       
 14134      */
       
 14135     even: function() {
       
 14136         return this.modulus(2);
       
 14137     },
       
 14138 
       
 14139     destructor: function() {
       
 14140     },
       
 14141 
       
 14142     /**
       
 14143      * Reruns the initial query, when created using a selector query
       
 14144      * @method refresh
       
 14145      * @chainable
       
 14146      */
       
 14147     refresh: function() {
       
 14148         var doc,
       
 14149             nodes = this._nodes,
       
 14150             query = this._query,
       
 14151             root = this._queryRoot;
       
 14152 
       
 14153         if (query) {
       
 14154             if (!root) {
       
 14155                 if (nodes && nodes[0] && nodes[0].ownerDocument) {
       
 14156                     root = nodes[0].ownerDocument;
       
 14157                 }
       
 14158             }
       
 14159 
       
 14160             this._nodes = Y.Selector.query(query, root);
       
 14161         }
       
 14162 
       
 14163         return this;
       
 14164     },
       
 14165 
       
 14166     /**
       
 14167      * Returns the current number of items in the NodeList.
       
 14168      * @method size
       
 14169      * @return {Int} The number of items in the NodeList.
       
 14170      */
       
 14171     size: function() {
       
 14172         return this._nodes.length;
       
 14173     },
       
 14174 
       
 14175     /**
       
 14176      * Determines if the instance is bound to any nodes
       
 14177      * @method isEmpty
       
 14178      * @return {Boolean} Whether or not the NodeList is bound to any nodes
       
 14179      */
       
 14180     isEmpty: function() {
       
 14181         return this._nodes.length < 1;
       
 14182     },
       
 14183 
       
 14184     toString: function() {
       
 14185         var str = '',
       
 14186             errorMsg = this[UID] + ': not bound to any nodes',
       
 14187             nodes = this._nodes,
       
 14188             node;
       
 14189 
       
 14190         if (nodes && nodes[0]) {
       
 14191             node = nodes[0];
       
 14192             str += node[NODE_NAME];
       
 14193             if (node.id) {
       
 14194                 str += '#' + node.id;
       
 14195             }
       
 14196 
       
 14197             if (node.className) {
       
 14198                 str += '.' + node.className.replace(' ', '.');
       
 14199             }
       
 14200 
       
 14201             if (nodes.length > 1) {
       
 14202                 str += '...[' + nodes.length + ' items]';
       
 14203             }
       
 14204         }
       
 14205         return str || errorMsg;
       
 14206     },
       
 14207 
       
 14208     /**
       
 14209      * Returns the DOM node bound to the Node instance
       
 14210      * @method getDOMNodes
       
 14211      * @return {Array}
       
 14212      */
       
 14213     getDOMNodes: function() {
       
 14214         return this._nodes;
       
 14215     }
       
 14216 }, true);
       
 14217 
       
 14218 NodeList.importMethod(Y.Node.prototype, [
       
 14219      /** 
       
 14220       * Called on each Node instance. Nulls internal node references, 
       
 14221       * removes any plugins and event listeners
       
 14222       * @method destroy
       
 14223       * @param {Boolean} recursivePurge (optional) Whether or not to 
       
 14224       * remove listeners from the node's subtree (default is false)
       
 14225       * @see Node.destroy
       
 14226       */
       
 14227     'destroy',
       
 14228 
       
 14229      /** 
       
 14230       * Called on each Node instance. Removes and destroys all of the nodes 
       
 14231       * within the node
       
 14232       * @method empty
       
 14233       * @chainable
       
 14234       * @see Node.empty
       
 14235       */
       
 14236     'empty',
       
 14237 
       
 14238      /** 
       
 14239       * Called on each Node instance. Removes the node from its parent.
       
 14240       * Shortcut for myNode.get('parentNode').removeChild(myNode);
       
 14241       * @method remove
       
 14242       * @param {Boolean} destroy whether or not to call destroy() on the node
       
 14243       * after removal.
       
 14244       * @chainable
       
 14245       * @see Node.remove
       
 14246       */
       
 14247     'remove',
       
 14248 
       
 14249      /** 
       
 14250       * Called on each Node instance. Sets an attribute on the Node instance.
       
 14251       * Unless pre-configured (via Node.ATTRS), set hands
       
 14252       * off to the underlying DOM node.  Only valid
       
 14253       * attributes/properties for the node will be set.
       
 14254       * To set custom attributes use setAttribute.
       
 14255       * @method set
       
 14256       * @param {String} attr The attribute to be set.
       
 14257       * @param {any} val The value to set the attribute to.
       
 14258       * @chainable
       
 14259       * @see Node.set
       
 14260       */
       
 14261     'set'
       
 14262 ]);
       
 14263 
       
 14264 // one-off implementation to convert array of Nodes to NodeList
       
 14265 // e.g. Y.all('input').get('parentNode');
       
 14266 
       
 14267 /** Called on each Node instance
       
 14268   * @method get
       
 14269   * @see Node
       
 14270   */
       
 14271 NodeList.prototype.get = function(attr) {
       
 14272     var ret = [],
       
 14273         nodes = this._nodes,
       
 14274         isNodeList = false,
       
 14275         getTemp = NodeList._getTempNode,
       
 14276         instance,
       
 14277         val;
       
 14278 
       
 14279     if (nodes[0]) {
       
 14280         instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
       
 14281         val = instance._get(attr);
       
 14282         if (val && val.nodeType) {
       
 14283             isNodeList = true;
       
 14284         }
       
 14285     }
       
 14286 
       
 14287     Y.Array.each(nodes, function(node) {
       
 14288         instance = Y.Node._instances[node._yuid];
       
 14289 
       
 14290         if (!instance) {
       
 14291             instance = getTemp(node);
       
 14292         }
       
 14293 
       
 14294         val = instance._get(attr);
       
 14295         if (!isNodeList) { // convert array of Nodes to NodeList
       
 14296             val = Y.Node.scrubVal(val, instance);
       
 14297         }
       
 14298 
       
 14299         ret.push(val);
       
 14300     });
       
 14301 
       
 14302     return (isNodeList) ? Y.all(ret) : ret;
       
 14303 };
       
 14304 
       
 14305 Y.NodeList = NodeList;
       
 14306 
       
 14307 Y.all = function(nodes) {
       
 14308     return new NodeList(nodes);
       
 14309 };
       
 14310 
       
 14311 Y.Node.all = Y.all;
       
 14312 /**
       
 14313  * @module node
       
 14314  * @submodule node-core
       
 14315  */
       
 14316 
       
 14317 var Y_NodeList = Y.NodeList,
       
 14318     ArrayProto = Array.prototype,
       
 14319     ArrayMethods = {
       
 14320         /** Returns a new NodeList combining the given NodeList(s)
       
 14321           * @for NodeList
       
 14322           * @method concat
       
 14323           * @param {NodeList | Array} valueN Arrays/NodeLists and/or values to
       
 14324           * concatenate to the resulting NodeList
       
 14325           * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
       
 14326           */
       
 14327         'concat': 1,
       
 14328         /** Removes the last from the NodeList and returns it.
       
 14329           * @for NodeList
       
 14330           * @method pop
       
 14331           * @return {Node | null} The last item in the NodeList, or null if the list is empty.
       
 14332           */
       
 14333         'pop': 0,
       
 14334         /** Adds the given Node(s) to the end of the NodeList.
       
 14335           * @for NodeList
       
 14336           * @method push
       
 14337           * @param {Node | DOMNode} nodes One or more nodes to add to the end of the NodeList.
       
 14338           */
       
 14339         'push': 0,
       
 14340         /** Removes the first item from the NodeList and returns it.
       
 14341           * @for NodeList
       
 14342           * @method shift
       
 14343           * @return {Node | null} The first item in the NodeList, or null if the NodeList is empty.
       
 14344           */
       
 14345         'shift': 0,
       
 14346         /** Returns a new NodeList comprising the Nodes in the given range.
       
 14347           * @for NodeList
       
 14348           * @method slice
       
 14349           * @param {Number} begin Zero-based index at which to begin extraction.
       
 14350           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.
       
 14351           * @param {Number} end Zero-based index at which to end extraction. slice extracts up to but not including end.
       
 14352           slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
       
 14353           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.
       
 14354           If end is omitted, slice extracts to the end of the sequence.
       
 14355           * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
       
 14356           */
       
 14357         'slice': 1,
       
 14358         /** Changes the content of the NodeList, adding new elements while removing old elements.
       
 14359           * @for NodeList
       
 14360           * @method splice
       
 14361           * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
       
 14362           * @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.
       
 14363           * {Node | DOMNode| element1, ..., elementN
       
 14364           The elements to add to the array. If you don't specify any elements, splice simply removes elements from the array.
       
 14365           * @return {NodeList} The element(s) removed.
       
 14366           */
       
 14367         'splice': 1,
       
 14368         /** Adds the given Node(s) to the beginning of the NodeList.
       
 14369           * @for NodeList
       
 14370           * @method unshift
       
 14371           * @param {Node | DOMNode} nodes One or more nodes to add to the NodeList.
       
 14372           */
       
 14373         'unshift': 0
       
 14374     };
       
 14375 
       
 14376 
       
 14377 Y.Object.each(ArrayMethods, function(returnNodeList, name) {
       
 14378     Y_NodeList.prototype[name] = function() {
       
 14379         var args = [],
       
 14380             i = 0,
       
 14381             arg,
       
 14382             ret;
       
 14383 
       
 14384         while (typeof (arg = arguments[i++]) != 'undefined') { // use DOM nodes/nodeLists
       
 14385             args.push(arg._node || arg._nodes || arg);
       
 14386         }
       
 14387 
       
 14388         ret = ArrayProto[name].apply(this._nodes, args);
       
 14389 
       
 14390         if (returnNodeList) {
       
 14391             ret = Y.all(ret);
       
 14392         } else {
       
 14393             ret = Y.Node.scrubVal(ret);
       
 14394         }
       
 14395 
       
 14396         return ret;
       
 14397     };
       
 14398 });
       
 14399 /**
       
 14400  * @module node
       
 14401  * @submodule node-core
       
 14402  */
       
 14403 
       
 14404 Y.Array.each([
       
 14405     /**
       
 14406      * Passes through to DOM method.
       
 14407      * @for Node
       
 14408      * @method removeChild
       
 14409      * @param {HTMLElement | Node} node Node to be removed
       
 14410      * @return {Node} The removed node
       
 14411      */
       
 14412     'removeChild',
       
 14413 
       
 14414     /**
       
 14415      * Passes through to DOM method.
       
 14416      * @method hasChildNodes
       
 14417      * @return {Boolean} Whether or not the node has any childNodes
       
 14418      */
       
 14419     'hasChildNodes',
       
 14420 
       
 14421     /**
       
 14422      * Passes through to DOM method.
       
 14423      * @method cloneNode
       
 14424      * @param {Boolean} deep Whether or not to perform a deep clone, which includes
       
 14425      * subtree and attributes
       
 14426      * @return {Node} The clone
       
 14427      */
       
 14428     'cloneNode',
       
 14429 
       
 14430     /**
       
 14431      * Passes through to DOM method.
       
 14432      * @method hasAttribute
       
 14433      * @param {String} attribute The attribute to test for
       
 14434      * @return {Boolean} Whether or not the attribute is present
       
 14435      */
       
 14436     'hasAttribute',
       
 14437 
       
 14438     /**
       
 14439      * Passes through to DOM method.
       
 14440      * @method scrollIntoView
       
 14441      * @chainable
       
 14442      */
       
 14443     'scrollIntoView',
       
 14444 
       
 14445     /**
       
 14446      * Passes through to DOM method.
       
 14447      * @method getElementsByTagName
       
 14448      * @param {String} tagName The tagName to collect
       
 14449      * @return {NodeList} A NodeList representing the HTMLCollection
       
 14450      */
       
 14451     'getElementsByTagName',
       
 14452 
       
 14453     /**
       
 14454      * Passes through to DOM method.
       
 14455      * @method focus
       
 14456      * @chainable
       
 14457      */
       
 14458     'focus',
       
 14459 
       
 14460     /**
       
 14461      * Passes through to DOM method.
       
 14462      * @method blur
       
 14463      * @chainable
       
 14464      */
       
 14465     'blur',
       
 14466 
       
 14467     /**
       
 14468      * Passes through to DOM method.
       
 14469      * Only valid on FORM elements
       
 14470      * @method submit
       
 14471      * @chainable
       
 14472      */
       
 14473     'submit',
       
 14474 
       
 14475     /**
       
 14476      * Passes through to DOM method.
       
 14477      * Only valid on FORM elements
       
 14478      * @method reset
       
 14479      * @chainable
       
 14480      */
       
 14481     'reset',
       
 14482 
       
 14483     /**
       
 14484      * Passes through to DOM method.
       
 14485      * @method select
       
 14486      * @chainable
       
 14487      */
       
 14488      'select',
       
 14489 
       
 14490     /**
       
 14491      * Passes through to DOM method.
       
 14492      * Only valid on TABLE elements
       
 14493      * @method createCaption
       
 14494      * @chainable
       
 14495      */
       
 14496     'createCaption'
       
 14497 
       
 14498 ], function(method) {
       
 14499     Y.log('adding: ' + method, 'info', 'node');
       
 14500     Y.Node.prototype[method] = function(arg1, arg2, arg3) {
       
 14501         var ret = this.invoke(method, arg1, arg2, arg3);
       
 14502         return ret;
       
 14503     };
       
 14504 });
       
 14505 
       
 14506 /**
       
 14507  * Passes through to DOM method.
       
 14508  * @method removeAttribute
       
 14509  * @param {String} attribute The attribute to be removed
       
 14510  * @chainable
       
 14511  */
       
 14512  // one-off implementation due to IE returning boolean, breaking chaining
       
 14513 Y.Node.prototype.removeAttribute = function(attr) {
       
 14514     var node = this._node;
       
 14515     if (node) {
       
 14516         node.removeAttribute(attr, 0); // comma zero for IE < 8 to force case-insensitive
       
 14517     }
       
 14518 
       
 14519     return this;
       
 14520 };
       
 14521 
       
 14522 Y.Node.importMethod(Y.DOM, [
       
 14523     /**
       
 14524      * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
       
 14525      * @method contains
       
 14526      * @param {Node | HTMLElement} needle The possible node or descendent
       
 14527      * @return {Boolean} Whether or not this node is the needle its ancestor
       
 14528      */
       
 14529     'contains',
       
 14530     /**
       
 14531      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
 14532      * This passes through to the DOM node, allowing for custom attributes.
       
 14533      * @method setAttribute
       
 14534      * @for Node
       
 14535      * @chainable
       
 14536      * @param {string} name The attribute name
       
 14537      * @param {string} value The value to set
       
 14538      */
       
 14539     'setAttribute',
       
 14540     /**
       
 14541      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
 14542      * This passes through to the DOM node, allowing for custom attributes.
       
 14543      * @method getAttribute
       
 14544      * @for Node
       
 14545      * @param {string} name The attribute name
       
 14546      * @return {string} The attribute value
       
 14547      */
       
 14548     'getAttribute',
       
 14549 
       
 14550     /**
       
 14551      * Wraps the given HTML around the node.
       
 14552      * @method wrap
       
 14553      * @param {String} html The markup to wrap around the node.
       
 14554      * @chainable
       
 14555      * @for Node
       
 14556      */
       
 14557     'wrap',
       
 14558 
       
 14559     /**
       
 14560      * Removes the node's parent node.
       
 14561      * @method unwrap
       
 14562      * @chainable
       
 14563      */
       
 14564     'unwrap',
       
 14565 
       
 14566     /**
       
 14567      * Applies a unique ID to the node if none exists
       
 14568      * @method generateID
       
 14569      * @return {String} The existing or generated ID
       
 14570      */
       
 14571     'generateID'
       
 14572 ]);
       
 14573 
       
 14574 Y.NodeList.importMethod(Y.Node.prototype, [
       
 14575 /**
       
 14576  * Allows getting attributes on DOM nodes, normalizing in some cases.
       
 14577  * This passes through to the DOM node, allowing for custom attributes.
       
 14578  * @method getAttribute
       
 14579  * @see Node
       
 14580  * @for NodeList
       
 14581  * @param {string} name The attribute name
       
 14582  * @return {string} The attribute value
       
 14583  */
       
 14584 
       
 14585     'getAttribute',
       
 14586 /**
       
 14587  * Allows setting attributes on DOM nodes, normalizing in some cases.
       
 14588  * This passes through to the DOM node, allowing for custom attributes.
       
 14589  * @method setAttribute
       
 14590  * @see Node
       
 14591  * @for NodeList
       
 14592  * @chainable
       
 14593  * @param {string} name The attribute name
       
 14594  * @param {string} value The value to set
       
 14595  */
       
 14596     'setAttribute',
       
 14597 
       
 14598 /**
       
 14599  * Allows for removing attributes on DOM nodes.
       
 14600  * This passes through to the DOM node, allowing for custom attributes.
       
 14601  * @method removeAttribute
       
 14602  * @see Node
       
 14603  * @for NodeList
       
 14604  * @param {string} name The attribute to remove
       
 14605  */
       
 14606     'removeAttribute',
       
 14607 /**
       
 14608  * Removes the parent node from node in the list.
       
 14609  * @method unwrap
       
 14610  * @chainable
       
 14611  */
       
 14612     'unwrap',
       
 14613 /**
       
 14614  * Wraps the given HTML around each node.
       
 14615  * @method wrap
       
 14616  * @param {String} html The markup to wrap around the node.
       
 14617  * @chainable
       
 14618  */
       
 14619     'wrap',
       
 14620 
       
 14621 /**
       
 14622  * Applies a unique ID to each node if none exists
       
 14623  * @method generateID
       
 14624  * @return {String} The existing or generated ID
       
 14625  */
       
 14626     'generateID'
       
 14627 ]);
       
 14628 
       
 14629 
       
 14630 }, '@VERSION@', {"requires": ["dom-core", "selector"]});
       
 14631 YUI.add('node-base', function (Y, NAME) {
       
 14632 
       
 14633 /**
       
 14634  * @module node
       
 14635  * @submodule node-base
       
 14636  */
       
 14637 
       
 14638 var methods = [
       
 14639 /**
       
 14640  * Determines whether each node has the given className.
       
 14641  * @method hasClass
       
 14642  * @for Node
       
 14643  * @param {String} className the class name to search for
       
 14644  * @return {Boolean} Whether or not the element has the specified class
       
 14645  */
       
 14646  'hasClass',
       
 14647 
       
 14648 /**
       
 14649  * Adds a class name to each node.
       
 14650  * @method addClass
       
 14651  * @param {String} className the class name to add to the node's class attribute
       
 14652  * @chainable
       
 14653  */
       
 14654  'addClass',
       
 14655 
       
 14656 /**
       
 14657  * Removes a class name from each node.
       
 14658  * @method removeClass
       
 14659  * @param {String} className the class name to remove from the node's class attribute
       
 14660  * @chainable
       
 14661  */
       
 14662  'removeClass',
       
 14663 
       
 14664 /**
       
 14665  * Replace a class with another class for each node.
       
 14666  * If no oldClassName is present, the newClassName is simply added.
       
 14667  * @method replaceClass
       
 14668  * @param {String} oldClassName the class name to be replaced
       
 14669  * @param {String} newClassName the class name that will be replacing the old class name
       
 14670  * @chainable
       
 14671  */
       
 14672  'replaceClass',
       
 14673 
       
 14674 /**
       
 14675  * If the className exists on the node it is removed, if it doesn't exist it is added.
       
 14676  * @method toggleClass
       
 14677  * @param {String} className the class name to be toggled
       
 14678  * @param {Boolean} force Option to force adding or removing the class.
       
 14679  * @chainable
       
 14680  */
       
 14681  'toggleClass'
       
 14682 ];
       
 14683 
       
 14684 Y.Node.importMethod(Y.DOM, methods);
       
 14685 /**
       
 14686  * Determines whether each node has the given className.
       
 14687  * @method hasClass
       
 14688  * @see Node.hasClass
       
 14689  * @for NodeList
       
 14690  * @param {String} className the class name to search for
       
 14691  * @return {Array} An array of booleans for each node bound to the NodeList.
       
 14692  */
       
 14693 
       
 14694 /**
       
 14695  * Adds a class name to each node.
       
 14696  * @method addClass
       
 14697  * @see Node.addClass
       
 14698  * @param {String} className the class name to add to the node's class attribute
       
 14699  * @chainable
       
 14700  */
       
 14701 
       
 14702 /**
       
 14703  * Removes a class name from each node.
       
 14704  * @method removeClass
       
 14705  * @see Node.removeClass
       
 14706  * @param {String} className the class name to remove from the node's class attribute
       
 14707  * @chainable
       
 14708  */
       
 14709 
       
 14710 /**
       
 14711  * Replace a class with another class for each node.
       
 14712  * If no oldClassName is present, the newClassName is simply added.
       
 14713  * @method replaceClass
       
 14714  * @see Node.replaceClass
       
 14715  * @param {String} oldClassName the class name to be replaced
       
 14716  * @param {String} newClassName the class name that will be replacing the old class name
       
 14717  * @chainable
       
 14718  */
       
 14719 
       
 14720 /**
       
 14721  * If the className exists on the node it is removed, if it doesn't exist it is added.
       
 14722  * @method toggleClass
       
 14723  * @see Node.toggleClass
       
 14724  * @param {String} className the class name to be toggled
       
 14725  * @chainable
       
 14726  */
       
 14727 Y.NodeList.importMethod(Y.Node.prototype, methods);
       
 14728 /**
       
 14729  * @module node
       
 14730  * @submodule node-base
       
 14731  */
       
 14732 
       
 14733 var Y_Node = Y.Node,
       
 14734     Y_DOM = Y.DOM;
       
 14735 
       
 14736 /**
       
 14737  * Returns a new dom node using the provided markup string.
       
 14738  * @method create
       
 14739  * @static
       
 14740  * @param {String} html The markup used to create the element
       
 14741  * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14742  * to escape html content.
       
 14743  * @param {HTMLDocument} doc An optional document context
       
 14744  * @return {Node} A Node instance bound to a DOM node or fragment
       
 14745  * @for Node
       
 14746  */
       
 14747 Y_Node.create = function(html, doc) {
       
 14748     if (doc && doc._node) {
       
 14749         doc = doc._node;
       
 14750     }
       
 14751     return Y.one(Y_DOM.create(html, doc));
       
 14752 };
       
 14753 
       
 14754 Y.mix(Y_Node.prototype, {
       
 14755     /**
       
 14756      * Creates a new Node using the provided markup string.
       
 14757      * @method create
       
 14758      * @param {String} html The markup used to create the element.
       
 14759      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14760      * to escape html content.
       
 14761      * @param {HTMLDocument} doc An optional document context
       
 14762      * @return {Node} A Node instance bound to a DOM node or fragment
       
 14763      */
       
 14764     create: Y_Node.create,
       
 14765 
       
 14766     /**
       
 14767      * Inserts the content before the reference node.
       
 14768      * @method insert
       
 14769      * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
 14770      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14771      * to escape html content.
       
 14772      * @param {Int | Node | HTMLElement | String} where The position to insert at.
       
 14773      * Possible "where" arguments
       
 14774      * <dl>
       
 14775      * <dt>Y.Node</dt>
       
 14776      * <dd>The Node to insert before</dd>
       
 14777      * <dt>HTMLElement</dt>
       
 14778      * <dd>The element to insert before</dd>
       
 14779      * <dt>Int</dt>
       
 14780      * <dd>The index of the child element to insert before</dd>
       
 14781      * <dt>"replace"</dt>
       
 14782      * <dd>Replaces the existing HTML</dd>
       
 14783      * <dt>"before"</dt>
       
 14784      * <dd>Inserts before the existing HTML</dd>
       
 14785      * <dt>"before"</dt>
       
 14786      * <dd>Inserts content before the node</dd>
       
 14787      * <dt>"after"</dt>
       
 14788      * <dd>Inserts content after the node</dd>
       
 14789      * </dl>
       
 14790      * @chainable
       
 14791      */
       
 14792     insert: function(content, where) {
       
 14793         this._insert(content, where);
       
 14794         return this;
       
 14795     },
       
 14796 
       
 14797     _insert: function(content, where) {
       
 14798         var node = this._node,
       
 14799             ret = null;
       
 14800 
       
 14801         if (typeof where == 'number') { // allow index
       
 14802             where = this._node.childNodes[where];
       
 14803         } else if (where && where._node) { // Node
       
 14804             where = where._node;
       
 14805         }
       
 14806 
       
 14807         if (content && typeof content != 'string') { // allow Node or NodeList/Array instances
       
 14808             content = content._node || content._nodes || content;
       
 14809         }
       
 14810         ret = Y_DOM.addHTML(node, content, where);
       
 14811 
       
 14812         return ret;
       
 14813     },
       
 14814 
       
 14815     /**
       
 14816      * Inserts the content as the firstChild of the node.
       
 14817      * @method prepend
       
 14818      * @param {String | Node | HTMLElement} content The content to insert
       
 14819      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14820      * to escape html content.
       
 14821      * @chainable
       
 14822      */
       
 14823     prepend: function(content) {
       
 14824         return this.insert(content, 0);
       
 14825     },
       
 14826 
       
 14827     /**
       
 14828      * Inserts the content as the lastChild of the node.
       
 14829      * @method append
       
 14830      * @param {String | Node | HTMLElement} content The content to insert
       
 14831      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14832      * to escape html content.
       
 14833      * @chainable
       
 14834      */
       
 14835     append: function(content) {
       
 14836         return this.insert(content, null);
       
 14837     },
       
 14838 
       
 14839     /**
       
 14840      * @method appendChild
       
 14841      * @param {String | HTMLElement | Node} node Node to be appended
       
 14842      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14843      * to escape html content.
       
 14844      * @return {Node} The appended node
       
 14845      */
       
 14846     appendChild: function(node) {
       
 14847         return Y_Node.scrubVal(this._insert(node));
       
 14848     },
       
 14849 
       
 14850     /**
       
 14851      * @method insertBefore
       
 14852      * @param {String | HTMLElement | Node} newNode Node to be appended
       
 14853      * @param {HTMLElement | Node} refNode Node to be inserted before
       
 14854      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14855      * to escape html content.
       
 14856      * @return {Node} The inserted node
       
 14857      */
       
 14858     insertBefore: function(newNode, refNode) {
       
 14859         return Y.Node.scrubVal(this._insert(newNode, refNode));
       
 14860     },
       
 14861 
       
 14862     /**
       
 14863      * Appends the node to the given node.
       
 14864      * @method appendTo
       
 14865      * @param {Node | HTMLElement} node The node to append to
       
 14866      * @chainable
       
 14867      */
       
 14868     appendTo: function(node) {
       
 14869         Y.one(node).append(this);
       
 14870         return this;
       
 14871     },
       
 14872 
       
 14873     /**
       
 14874      * Replaces the node's current content with the content.
       
 14875      * Note that this passes to innerHTML and is not escaped.
       
 14876      * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
       
 14877      * to escape html content or `set('text')` to add as text.
       
 14878      * @method setContent
       
 14879      * @deprecated Use setHTML
       
 14880      * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
 14881      * @chainable
       
 14882      */
       
 14883     setContent: function(content) {
       
 14884         this._insert(content, 'replace');
       
 14885         return this;
       
 14886     },
       
 14887 
       
 14888     /**
       
 14889      * Returns the node's current content (e.g. innerHTML)
       
 14890      * @method getContent
       
 14891      * @deprecated Use getHTML
       
 14892      * @return {String} The current content
       
 14893      */
       
 14894     getContent: function(content) {
       
 14895         return this.get('innerHTML');
       
 14896     }
       
 14897 });
       
 14898 
       
 14899 /**
       
 14900  * Replaces the node's current html content with the content provided.
       
 14901  * Note that this passes to innerHTML and is not escaped.
       
 14902  * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
 14903  * @method setHTML
       
 14904  * @param {String | HTML | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
       
 14905  * @chainable
       
 14906  */
       
 14907 Y.Node.prototype.setHTML = Y.Node.prototype.setContent;
       
 14908 
       
 14909 /**
       
 14910  * Returns the node's current html content (e.g. innerHTML)
       
 14911  * @method getHTML
       
 14912  * @return {String} The html content
       
 14913  */
       
 14914 Y.Node.prototype.getHTML = Y.Node.prototype.getContent;
       
 14915 
       
 14916 Y.NodeList.importMethod(Y.Node.prototype, [
       
 14917     /**
       
 14918      * Called on each Node instance
       
 14919      * @for NodeList
       
 14920      * @method append
       
 14921      * @see Node.append
       
 14922      */
       
 14923     'append',
       
 14924 
       
 14925     /**
       
 14926      * Called on each Node instance
       
 14927      * @for NodeList
       
 14928      * @method insert
       
 14929      * @see Node.insert
       
 14930      */
       
 14931     'insert',
       
 14932 
       
 14933     /**
       
 14934      * Called on each Node instance
       
 14935      * @for NodeList
       
 14936      * @method appendChild
       
 14937      * @see Node.appendChild
       
 14938      */
       
 14939     'appendChild',
       
 14940 
       
 14941     /**
       
 14942      * Called on each Node instance
       
 14943      * @for NodeList
       
 14944      * @method insertBefore
       
 14945      * @see Node.insertBefore
       
 14946      */
       
 14947     'insertBefore',
       
 14948 
       
 14949     /**
       
 14950      * Called on each Node instance
       
 14951      * @for NodeList
       
 14952      * @method prepend
       
 14953      * @see Node.prepend
       
 14954      */
       
 14955     'prepend',
       
 14956 
       
 14957     /**
       
 14958      * Called on each Node instance
       
 14959      * Note that this passes to innerHTML and is not escaped.
       
 14960      * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
 14961      * @for NodeList
       
 14962      * @method setContent
       
 14963      * @deprecated Use setHTML
       
 14964      */
       
 14965     'setContent',
       
 14966 
       
 14967     /**
       
 14968      * Called on each Node instance
       
 14969      * @for NodeList
       
 14970      * @method getContent
       
 14971      * @deprecated Use getHTML
       
 14972      */
       
 14973     'getContent',
       
 14974 
       
 14975     /**
       
 14976      * Called on each Node instance
       
 14977      * Note that this passes to innerHTML and is not escaped.
       
 14978      * Use `Y.Escape.html()` to escape HTML, or `set('text')` to add as text.
       
 14979      * @for NodeList
       
 14980      * @method setHTML
       
 14981      * @see Node.setHTML
       
 14982      */
       
 14983     'setHTML',
       
 14984 
       
 14985     /**
       
 14986      * Called on each Node instance
       
 14987      * @for NodeList
       
 14988      * @method getHTML
       
 14989      * @see Node.getHTML
       
 14990      */
       
 14991     'getHTML'
       
 14992 ]);
       
 14993 /**
       
 14994  * @module node
       
 14995  * @submodule node-base
       
 14996  */
       
 14997 
       
 14998 var Y_Node = Y.Node,
       
 14999     Y_DOM = Y.DOM;
       
 15000 
       
 15001 /**
       
 15002  * Static collection of configuration attributes for special handling
       
 15003  * @property ATTRS
       
 15004  * @static
       
 15005  * @type object
       
 15006  */
       
 15007 Y_Node.ATTRS = {
       
 15008     /**
       
 15009      * Allows for getting and setting the text of an element.
       
 15010      * Formatting is preserved and special characters are treated literally.
       
 15011      * @config text
       
 15012      * @type String
       
 15013      */
       
 15014     text: {
       
 15015         getter: function() {
       
 15016             return Y_DOM.getText(this._node);
       
 15017         },
       
 15018 
       
 15019         setter: function(content) {
       
 15020             Y_DOM.setText(this._node, content);
       
 15021             return content;
       
 15022         }
       
 15023     },
       
 15024 
       
 15025     /**
       
 15026      * Allows for getting and setting the text of an element.
       
 15027      * Formatting is preserved and special characters are treated literally.
       
 15028      * @config for
       
 15029      * @type String
       
 15030      */
       
 15031     'for': {
       
 15032         getter: function() {
       
 15033             return Y_DOM.getAttribute(this._node, 'for');
       
 15034         },
       
 15035 
       
 15036         setter: function(val) {
       
 15037             Y_DOM.setAttribute(this._node, 'for', val);
       
 15038             return val;
       
 15039         }
       
 15040     },
       
 15041 
       
 15042     'options': {
       
 15043         getter: function() {
       
 15044             return this._node.getElementsByTagName('option');
       
 15045         }
       
 15046     },
       
 15047 
       
 15048     /**
       
 15049      * Returns a NodeList instance of all HTMLElement children.
       
 15050      * @readOnly
       
 15051      * @config children
       
 15052      * @type NodeList
       
 15053      */
       
 15054     'children': {
       
 15055         getter: function() {
       
 15056             var node = this._node,
       
 15057                 children = node.children,
       
 15058                 childNodes, i, len;
       
 15059 
       
 15060             if (!children) {
       
 15061                 childNodes = node.childNodes;
       
 15062                 children = [];
       
 15063 
       
 15064                 for (i = 0, len = childNodes.length; i < len; ++i) {
       
 15065                     if (childNodes[i].tagName) {
       
 15066                         children[children.length] = childNodes[i];
       
 15067                     }
       
 15068                 }
       
 15069             }
       
 15070             return Y.all(children);
       
 15071         }
       
 15072     },
       
 15073 
       
 15074     value: {
       
 15075         getter: function() {
       
 15076             return Y_DOM.getValue(this._node);
       
 15077         },
       
 15078 
       
 15079         setter: function(val) {
       
 15080             Y_DOM.setValue(this._node, val);
       
 15081             return val;
       
 15082         }
       
 15083     }
       
 15084 };
       
 15085 
       
 15086 Y.Node.importMethod(Y.DOM, [
       
 15087     /**
       
 15088      * Allows setting attributes on DOM nodes, normalizing in some cases.
       
 15089      * This passes through to the DOM node, allowing for custom attributes.
       
 15090      * @method setAttribute
       
 15091      * @for Node
       
 15092      * @for NodeList
       
 15093      * @chainable
       
 15094      * @param {string} name The attribute name
       
 15095      * @param {string} value The value to set
       
 15096      */
       
 15097     'setAttribute',
       
 15098     /**
       
 15099      * Allows getting attributes on DOM nodes, normalizing in some cases.
       
 15100      * This passes through to the DOM node, allowing for custom attributes.
       
 15101      * @method getAttribute
       
 15102      * @for Node
       
 15103      * @for NodeList
       
 15104      * @param {string} name The attribute name
       
 15105      * @return {string} The attribute value
       
 15106      */
       
 15107     'getAttribute'
       
 15108 
       
 15109 ]);
       
 15110 /**
       
 15111  * @module node
       
 15112  * @submodule node-base
       
 15113  */
       
 15114 
       
 15115 var Y_Node = Y.Node;
       
 15116 var Y_NodeList = Y.NodeList;
       
 15117 /**
       
 15118  * List of events that route to DOM events
       
 15119  * @static
       
 15120  * @property DOM_EVENTS
       
 15121  * @for Node
       
 15122  */
       
 15123 
       
 15124 Y_Node.DOM_EVENTS = {
       
 15125     abort: 1,
       
 15126     beforeunload: 1,
       
 15127     blur: 1,
       
 15128     change: 1,
       
 15129     click: 1,
       
 15130     close: 1,
       
 15131     command: 1,
       
 15132     contextmenu: 1,
       
 15133     dblclick: 1,
       
 15134     DOMMouseScroll: 1,
       
 15135     drag: 1,
       
 15136     dragstart: 1,
       
 15137     dragenter: 1,
       
 15138     dragover: 1,
       
 15139     dragleave: 1,
       
 15140     dragend: 1,
       
 15141     drop: 1,
       
 15142     error: 1,
       
 15143     focus: 1,
       
 15144     key: 1,
       
 15145     keydown: 1,
       
 15146     keypress: 1,
       
 15147     keyup: 1,
       
 15148     load: 1,
       
 15149     message: 1,
       
 15150     mousedown: 1,
       
 15151     mouseenter: 1,
       
 15152     mouseleave: 1,
       
 15153     mousemove: 1,
       
 15154     mousemultiwheel: 1,
       
 15155     mouseout: 1,
       
 15156     mouseover: 1,
       
 15157     mouseup: 1,
       
 15158     mousewheel: 1,
       
 15159     orientationchange: 1,
       
 15160     reset: 1,
       
 15161     resize: 1,
       
 15162     select: 1,
       
 15163     selectstart: 1,
       
 15164     submit: 1,
       
 15165     scroll: 1,
       
 15166     textInput: 1,
       
 15167     unload: 1
       
 15168 };
       
 15169 
       
 15170 // Add custom event adaptors to this list.  This will make it so
       
 15171 // that delegate, key, available, contentready, etc all will
       
 15172 // be available through Node.on
       
 15173 Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
       
 15174 
       
 15175 Y.augment(Y_Node, Y.EventTarget);
       
 15176 
       
 15177 Y.mix(Y_Node.prototype, {
       
 15178     /**
       
 15179      * Removes event listeners from the node and (optionally) its subtree
       
 15180      * @method purge
       
 15181      * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
       
 15182      * node's subtree
       
 15183      * @param {String} type (optional) Only remove listeners of the specified type
       
 15184      * @chainable
       
 15185      *
       
 15186      */
       
 15187     purge: function(recurse, type) {
       
 15188         Y.Event.purgeElement(this._node, recurse, type);
       
 15189         return this;
       
 15190     }
       
 15191 
       
 15192 });
       
 15193 
       
 15194 Y.mix(Y.NodeList.prototype, {
       
 15195     _prepEvtArgs: function(type, fn, context) {
       
 15196         // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
       
 15197         var args = Y.Array(arguments, 0, true);
       
 15198 
       
 15199         if (args.length < 2) { // type only (event hash) just add nodes
       
 15200             args[2] = this._nodes;
       
 15201         } else {
       
 15202             args.splice(2, 0, this._nodes);
       
 15203         }
       
 15204 
       
 15205         args[3] = context || this; // default to NodeList instance as context
       
 15206 
       
 15207         return args;
       
 15208     },
       
 15209 
       
 15210     /**
       
 15211     Subscribe a callback function for each `Node` in the collection to execute
       
 15212     in response to a DOM event.
       
 15213 
       
 15214     NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in
       
 15215     favor of using event delegation from a parent Node.  See the Event user
       
 15216     guide for details.
       
 15217 
       
 15218     Most DOM events are associated with a preventable default behavior, such as
       
 15219     link clicks navigating to a new page.  Callbacks are passed a
       
 15220     `DOMEventFacade` object as their first argument (usually called `e`) that
       
 15221     can be used to prevent this default behavior with `e.preventDefault()`. See
       
 15222     the `DOMEventFacade` API for all available properties and methods on the
       
 15223     object.
       
 15224 
       
 15225     By default, the `this` object will be the `NodeList` that the subscription
       
 15226     came from, <em>not the `Node` that received the event</em>.  Use
       
 15227     `e.currentTarget` to refer to the `Node`.
       
 15228 
       
 15229     Returning `false` from a callback is supported as an alternative to calling
       
 15230     `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to
       
 15231     use the event methods.
       
 15232 
       
 15233     @example
       
 15234 
       
 15235         Y.all(".sku").on("keydown", function (e) {
       
 15236             if (e.keyCode === 13) {
       
 15237                 e.preventDefault();
       
 15238 
       
 15239                 // Use e.currentTarget to refer to the individual Node
       
 15240                 var item = Y.MyApp.searchInventory( e.currentTarget.get('value') );
       
 15241                 // etc ...
       
 15242             }
       
 15243         });
       
 15244 
       
 15245     @method on
       
 15246     @param {String} type The name of the event
       
 15247     @param {Function} fn The callback to execute in response to the event
       
 15248     @param {Object} [context] Override `this` object in callback
       
 15249     @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 15250     @return {EventHandle} A subscription handle capable of detaching that
       
 15251                           subscription
       
 15252     @for NodeList
       
 15253     **/
       
 15254     on: function(type, fn, context) {
       
 15255         return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 15256     },
       
 15257 
       
 15258     /**
       
 15259      * Applies an one-time event listener to each Node bound to the NodeList.
       
 15260      * @method once
       
 15261      * @param {String} type The event being listened for
       
 15262      * @param {Function} fn The handler to call when the event fires
       
 15263      * @param {Object} context The context to call the handler with.
       
 15264      * Default is the NodeList instance.
       
 15265      * @return {EventHandle} A subscription handle capable of detaching that
       
 15266      *                    subscription
       
 15267      * @for NodeList
       
 15268      */
       
 15269     once: function(type, fn, context) {
       
 15270         return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 15271     },
       
 15272 
       
 15273     /**
       
 15274      * Applies an event listener to each Node bound to the NodeList.
       
 15275      * The handler is called only after all on() handlers are called
       
 15276      * and the event is not prevented.
       
 15277      * @method after
       
 15278      * @param {String} type The event being listened for
       
 15279      * @param {Function} fn The handler to call when the event fires
       
 15280      * @param {Object} context The context to call the handler with.
       
 15281      * Default is the NodeList instance.
       
 15282      * @return {EventHandle} A subscription handle capable of detaching that
       
 15283      *                    subscription
       
 15284      * @for NodeList
       
 15285      */
       
 15286     after: function(type, fn, context) {
       
 15287         return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 15288     },
       
 15289 
       
 15290     /**
       
 15291      * Applies an one-time event listener to each Node bound to the NodeList
       
 15292      * that will be called only after all on() handlers are called and the
       
 15293      * event is not prevented.
       
 15294      *
       
 15295      * @method onceAfter
       
 15296      * @param {String} type The event being listened for
       
 15297      * @param {Function} fn The handler to call when the event fires
       
 15298      * @param {Object} context The context to call the handler with.
       
 15299      * Default is the NodeList instance.
       
 15300      * @return {EventHandle} A subscription handle capable of detaching that
       
 15301      *                    subscription
       
 15302      * @for NodeList
       
 15303      */
       
 15304     onceAfter: function(type, fn, context) {
       
 15305         return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
       
 15306     }
       
 15307 });
       
 15308 
       
 15309 Y_NodeList.importMethod(Y.Node.prototype, [
       
 15310     /**
       
 15311       * Called on each Node instance
       
 15312       * @method detach
       
 15313       * @see Node.detach
       
 15314       * @for NodeList
       
 15315       */
       
 15316     'detach',
       
 15317 
       
 15318     /** Called on each Node instance
       
 15319       * @method detachAll
       
 15320       * @see Node.detachAll
       
 15321       * @for NodeList
       
 15322       */
       
 15323     'detachAll'
       
 15324 ]);
       
 15325 
       
 15326 /**
       
 15327 Subscribe a callback function to execute in response to a DOM event or custom
       
 15328 event.
       
 15329 
       
 15330 Most DOM events are associated with a preventable default behavior such as
       
 15331 link clicks navigating to a new page.  Callbacks are passed a `DOMEventFacade`
       
 15332 object as their first argument (usually called `e`) that can be used to
       
 15333 prevent this default behavior with `e.preventDefault()`. See the
       
 15334 `DOMEventFacade` API for all available properties and methods on the object.
       
 15335 
       
 15336 If the event name passed as the first parameter is not a whitelisted DOM event,
       
 15337 it will be treated as a custom event subscriptions, allowing
       
 15338 `node.fire('customEventName')` later in the code.  Refer to the Event user guide
       
 15339 for the full DOM event whitelist.
       
 15340 
       
 15341 By default, the `this` object in the callback will refer to the subscribed
       
 15342 `Node`.
       
 15343 
       
 15344 Returning `false` from a callback is supported as an alternative to calling
       
 15345 `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to use
       
 15346 the event methods.
       
 15347 
       
 15348 @example
       
 15349 
       
 15350     Y.one("#my-form").on("submit", function (e) {
       
 15351         e.preventDefault();
       
 15352 
       
 15353         // proceed with ajax form submission instead...
       
 15354     });
       
 15355 
       
 15356 @method on
       
 15357 @param {String} type The name of the event
       
 15358 @param {Function} fn The callback to execute in response to the event
       
 15359 @param {Object} [context] Override `this` object in callback
       
 15360 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
       
 15361 @return {EventHandle} A subscription handle capable of detaching that
       
 15362                       subscription
       
 15363 @for Node
       
 15364 **/
       
 15365 
       
 15366 Y.mix(Y.Node.ATTRS, {
       
 15367     offsetHeight: {
       
 15368         setter: function(h) {
       
 15369             Y.DOM.setHeight(this._node, h);
       
 15370             return h;
       
 15371         },
       
 15372 
       
 15373         getter: function() {
       
 15374             return this._node.offsetHeight;
       
 15375         }
       
 15376     },
       
 15377 
       
 15378     offsetWidth: {
       
 15379         setter: function(w) {
       
 15380             Y.DOM.setWidth(this._node, w);
       
 15381             return w;
       
 15382         },
       
 15383 
       
 15384         getter: function() {
       
 15385             return this._node.offsetWidth;
       
 15386         }
       
 15387     }
       
 15388 });
       
 15389 
       
 15390 Y.mix(Y.Node.prototype, {
       
 15391     sizeTo: function(w, h) {
       
 15392         var node;
       
 15393         if (arguments.length < 2) {
       
 15394             node = Y.one(w);
       
 15395             w = node.get('offsetWidth');
       
 15396             h = node.get('offsetHeight');
       
 15397         }
       
 15398 
       
 15399         this.setAttrs({
       
 15400             offsetWidth: w,
       
 15401             offsetHeight: h
       
 15402         });
       
 15403     }
       
 15404 });
       
 15405 /**
       
 15406  * @module node
       
 15407  * @submodule node-base
       
 15408  */
       
 15409 
       
 15410 var Y_Node = Y.Node;
       
 15411 
       
 15412 Y.mix(Y_Node.prototype, {
       
 15413     /**
       
 15414      * Makes the node visible.
       
 15415      * If the "transition" module is loaded, show optionally
       
 15416      * animates the showing of the node using either the default
       
 15417      * transition effect ('fadeIn'), or the given named effect.
       
 15418      * @method show
       
 15419      * @for Node
       
 15420      * @param {String} name A named Transition effect to use as the show effect.
       
 15421      * @param {Object} config Options to use with the transition.
       
 15422      * @param {Function} callback An optional function to run after the transition completes.
       
 15423      * @chainable
       
 15424      */
       
 15425     show: function(callback) {
       
 15426         callback = arguments[arguments.length - 1];
       
 15427         this.toggleView(true, callback);
       
 15428         return this;
       
 15429     },
       
 15430 
       
 15431     /**
       
 15432      * The implementation for showing nodes.
       
 15433      * Default is to remove the hidden attribute and reset the CSS style.display property.
       
 15434      * @method _show
       
 15435      * @protected
       
 15436      * @chainable
       
 15437      */
       
 15438     _show: function() {
       
 15439         this.removeAttribute('hidden');
       
 15440 
       
 15441         // For back-compat we need to leave this in for browsers that
       
 15442         // do not visually hide a node via the hidden attribute
       
 15443         // and for users that check visibility based on style display.
       
 15444         this.setStyle('display', '');
       
 15445 
       
 15446     },
       
 15447 
       
 15448     _isHidden: function() {
       
 15449         return Y.DOM.getAttribute(this._node, 'hidden') === 'true';
       
 15450     },
       
 15451 
       
 15452     /**
       
 15453      * Displays or hides the node.
       
 15454      * If the "transition" module is loaded, toggleView optionally
       
 15455      * animates the toggling of the node using given named effect.
       
 15456      * @method toggleView
       
 15457      * @for Node
       
 15458      * @param {String} [name] An optional string value to use as transition effect.
       
 15459      * @param {Boolean} [on] An optional boolean value to force the node to be shown or hidden
       
 15460      * @param {Function} [callback] An optional function to run after the transition completes.
       
 15461      * @chainable
       
 15462      */
       
 15463     toggleView: function(on, callback) {
       
 15464         this._toggleView.apply(this, arguments);
       
 15465         return this;
       
 15466     },
       
 15467 
       
 15468     _toggleView: function(on, callback) {
       
 15469         callback = arguments[arguments.length - 1];
       
 15470 
       
 15471         // base on current state if not forcing
       
 15472         if (typeof on != 'boolean') {
       
 15473             on = (this._isHidden()) ? 1 : 0;
       
 15474         }
       
 15475 
       
 15476         if (on) {
       
 15477             this._show();
       
 15478         }  else {
       
 15479             this._hide();
       
 15480         }
       
 15481 
       
 15482         if (typeof callback == 'function') {
       
 15483             callback.call(this);
       
 15484         }
       
 15485 
       
 15486         return this;
       
 15487     },
       
 15488 
       
 15489     /**
       
 15490      * Hides the node.
       
 15491      * If the "transition" module is loaded, hide optionally
       
 15492      * animates the hiding of the node using either the default
       
 15493      * transition effect ('fadeOut'), or the given named effect.
       
 15494      * @method hide
       
 15495      * @param {String} name A named Transition effect to use as the show effect.
       
 15496      * @param {Object} config Options to use with the transition.
       
 15497      * @param {Function} callback An optional function to run after the transition completes.
       
 15498      * @chainable
       
 15499      */
       
 15500     hide: function(callback) {
       
 15501         callback = arguments[arguments.length - 1];
       
 15502         this.toggleView(false, callback);
       
 15503         return this;
       
 15504     },
       
 15505 
       
 15506     /**
       
 15507      * The implementation for hiding nodes.
       
 15508      * Default is to set the hidden attribute to true and set the CSS style.display to 'none'.
       
 15509      * @method _hide
       
 15510      * @protected
       
 15511      * @chainable
       
 15512      */
       
 15513     _hide: function() {
       
 15514         this.setAttribute('hidden', true);
       
 15515 
       
 15516         // For back-compat we need to leave this in for browsers that
       
 15517         // do not visually hide a node via the hidden attribute
       
 15518         // and for users that check visibility based on style display.
       
 15519         this.setStyle('display', 'none');
       
 15520     }
       
 15521 });
       
 15522 
       
 15523 Y.NodeList.importMethod(Y.Node.prototype, [
       
 15524     /**
       
 15525      * Makes each node visible.
       
 15526      * If the "transition" module is loaded, show optionally
       
 15527      * animates the showing of the node using either the default
       
 15528      * transition effect ('fadeIn'), or the given named effect.
       
 15529      * @method show
       
 15530      * @param {String} name A named Transition effect to use as the show effect.
       
 15531      * @param {Object} config Options to use with the transition.
       
 15532      * @param {Function} callback An optional function to run after the transition completes.
       
 15533      * @for NodeList
       
 15534      * @chainable
       
 15535      */
       
 15536     'show',
       
 15537 
       
 15538     /**
       
 15539      * Hides each node.
       
 15540      * If the "transition" module is loaded, hide optionally
       
 15541      * animates the hiding of the node using either the default
       
 15542      * transition effect ('fadeOut'), or the given named effect.
       
 15543      * @method hide
       
 15544      * @param {String} name A named Transition effect to use as the show effect.
       
 15545      * @param {Object} config Options to use with the transition.
       
 15546      * @param {Function} callback An optional function to run after the transition completes.
       
 15547      * @chainable
       
 15548      */
       
 15549     'hide',
       
 15550 
       
 15551     /**
       
 15552      * Displays or hides each node.
       
 15553      * If the "transition" module is loaded, toggleView optionally
       
 15554      * animates the toggling of the nodes using given named effect.
       
 15555      * @method toggleView
       
 15556      * @param {String} [name] An optional string value to use as transition effect.
       
 15557      * @param {Boolean} [on] An optional boolean value to force the nodes to be shown or hidden
       
 15558      * @param {Function} [callback] An optional function to run after the transition completes.
       
 15559      * @chainable
       
 15560      */
       
 15561     'toggleView'
       
 15562 ]);
       
 15563 
       
 15564 if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
       
 15565     Y.Node.prototype.hasAttribute = function(attr) {
       
 15566         if (attr === 'value') {
       
 15567             if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
       
 15568                 return true;
       
 15569             }
       
 15570         }
       
 15571         return !!(this._node.attributes[attr] &&
       
 15572                 this._node.attributes[attr].specified);
       
 15573     };
       
 15574 }
       
 15575 
       
 15576 // IE throws an error when calling focus() on an element that's invisible, not
       
 15577 // displayed, or disabled.
       
 15578 Y.Node.prototype.focus = function () {
       
 15579     try {
       
 15580         this._node.focus();
       
 15581     } catch (e) {
       
 15582         Y.log('error focusing node: ' + e.toString(), 'error', 'node');
       
 15583     }
       
 15584 
       
 15585     return this;
       
 15586 };
       
 15587 
       
 15588 // IE throws error when setting input.type = 'hidden',
       
 15589 // input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
       
 15590 Y.Node.ATTRS.type = {
       
 15591     setter: function(val) {
       
 15592         if (val === 'hidden') {
       
 15593             try {
       
 15594                 this._node.type = 'hidden';
       
 15595             } catch(e) {
       
 15596                 this.setStyle('display', 'none');
       
 15597                 this._inputType = 'hidden';
       
 15598             }
       
 15599         } else {
       
 15600             try { // IE errors when changing the type from "hidden'
       
 15601                 this._node.type = val;
       
 15602             } catch (e) {
       
 15603                 Y.log('error setting type: ' + val, 'info', 'node');
       
 15604             }
       
 15605         }
       
 15606         return val;
       
 15607     },
       
 15608 
       
 15609     getter: function() {
       
 15610         return this._inputType || this._node.type;
       
 15611     },
       
 15612 
       
 15613     _bypassProxy: true // don't update DOM when using with Attribute
       
 15614 };
       
 15615 
       
 15616 if (Y.config.doc.createElement('form').elements.nodeType) {
       
 15617     // IE: elements collection is also FORM node which trips up scrubVal.
       
 15618     Y.Node.ATTRS.elements = {
       
 15619             getter: function() {
       
 15620                 return this.all('input, textarea, button, select');
       
 15621             }
       
 15622     };
       
 15623 }
       
 15624 
       
 15625 /**
       
 15626  * Provides methods for managing custom Node data.
       
 15627  * 
       
 15628  * @module node
       
 15629  * @main node
       
 15630  * @submodule node-data
       
 15631  */
       
 15632 
       
 15633 Y.mix(Y.Node.prototype, {
       
 15634     _initData: function() {
       
 15635         if (! ('_data' in this)) {
       
 15636             this._data = {};
       
 15637         }
       
 15638     },
       
 15639 
       
 15640     /**
       
 15641     * @method getData
       
 15642     * @for Node
       
 15643     * @description Retrieves arbitrary data stored on a Node instance.
       
 15644     * If no data is associated with the Node, it will attempt to retrieve
       
 15645     * a value from the corresponding HTML data attribute. (e.g. node.getData('foo')
       
 15646     * will check node.getAttribute('data-foo')).
       
 15647     * @param {string} name Optional name of the data field to retrieve.
       
 15648     * If no name is given, all data is returned.
       
 15649     * @return {any | Object} Whatever is stored at the given field,
       
 15650     * or an object hash of all fields.
       
 15651     */
       
 15652     getData: function(name) {
       
 15653         this._initData();
       
 15654         var data = this._data,
       
 15655             ret = data;
       
 15656 
       
 15657         if (arguments.length) { // single field
       
 15658             if (name in data) {
       
 15659                 ret = data[name];
       
 15660             } else { // initialize from HTML attribute
       
 15661                 ret = this._getDataAttribute(name);
       
 15662             }
       
 15663         } else if (typeof data == 'object' && data !== null) { // all fields
       
 15664             ret = {};
       
 15665             Y.Object.each(data, function(v, n) {
       
 15666                 ret[n] = v;
       
 15667             });
       
 15668 
       
 15669             ret = this._getDataAttributes(ret);
       
 15670         }
       
 15671 
       
 15672         return ret;
       
 15673 
       
 15674     },
       
 15675 
       
 15676     _getDataAttributes: function(ret) {
       
 15677         ret = ret || {};
       
 15678         var i = 0,
       
 15679             attrs = this._node.attributes,
       
 15680             len = attrs.length,
       
 15681             prefix = this.DATA_PREFIX,
       
 15682             prefixLength = prefix.length,
       
 15683             name;
       
 15684 
       
 15685         while (i < len) {
       
 15686             name = attrs[i].name;
       
 15687             if (name.indexOf(prefix) === 0) {
       
 15688                 name = name.substr(prefixLength);
       
 15689                 if (!(name in ret)) { // only merge if not already stored
       
 15690                     ret[name] = this._getDataAttribute(name);
       
 15691                 }
       
 15692             }
       
 15693 
       
 15694             i += 1;
       
 15695         }
       
 15696 
       
 15697         return ret;
       
 15698     },
       
 15699 
       
 15700     _getDataAttribute: function(name) {
       
 15701         name = this.DATA_PREFIX + name;
       
 15702 
       
 15703         var node = this._node,
       
 15704             attrs = node.attributes,
       
 15705             data = attrs && attrs[name] && attrs[name].value;
       
 15706 
       
 15707         return data;
       
 15708     },
       
 15709 
       
 15710     /**
       
 15711     * @method setData
       
 15712     * @for Node
       
 15713     * @description Stores arbitrary data on a Node instance.
       
 15714     * This is not stored with the DOM node.
       
 15715     * @param {string} name The name of the field to set. If no val
       
 15716     * is given, name is treated as the data and overrides any existing data.
       
 15717     * @param {any} val The value to be assigned to the field.
       
 15718     * @chainable
       
 15719     */
       
 15720     setData: function(name, val) {
       
 15721         this._initData();
       
 15722         if (arguments.length > 1) {
       
 15723             this._data[name] = val;
       
 15724         } else {
       
 15725             this._data = name;
       
 15726         }
       
 15727 
       
 15728        return this;
       
 15729     },
       
 15730 
       
 15731     /**
       
 15732     * @method clearData
       
 15733     * @for Node
       
 15734     * @description Clears internally stored data.
       
 15735     * @param {string} name The name of the field to clear. If no name
       
 15736     * is given, all data is cleared.
       
 15737     * @chainable
       
 15738     */
       
 15739     clearData: function(name) {
       
 15740         if ('_data' in this) {
       
 15741             if (typeof name != 'undefined') {
       
 15742                 delete this._data[name];
       
 15743             } else {
       
 15744                 delete this._data;
       
 15745             }
       
 15746         }
       
 15747 
       
 15748         return this;
       
 15749     }
       
 15750 });
       
 15751 
       
 15752 Y.mix(Y.NodeList.prototype, {
       
 15753     /**
       
 15754     * @method getData
       
 15755     * @for NodeList
       
 15756     * @description Retrieves arbitrary data stored on each Node instance
       
 15757     * bound to the NodeList.
       
 15758     * @see Node
       
 15759     * @param {string} name Optional name of the data field to retrieve.
       
 15760     * If no name is given, all data is returned.
       
 15761     * @return {Array} An array containing all of the data for each Node instance. 
       
 15762     * or an object hash of all fields.
       
 15763     */
       
 15764     getData: function(name) {
       
 15765         var args = (arguments.length) ? [name] : [];
       
 15766         return this._invoke('getData', args, true);
       
 15767     },
       
 15768 
       
 15769     /**
       
 15770     * @method setData
       
 15771     * @for NodeList
       
 15772     * @description Stores arbitrary data on each Node instance bound to the
       
 15773     *  NodeList. This is not stored with the DOM node.
       
 15774     * @param {string} name The name of the field to set. If no name
       
 15775     * is given, name is treated as the data and overrides any existing data.
       
 15776     * @param {any} val The value to be assigned to the field.
       
 15777     * @chainable
       
 15778     */
       
 15779     setData: function(name, val) {
       
 15780         var args = (arguments.length > 1) ? [name, val] : [name];
       
 15781         return this._invoke('setData', args);
       
 15782     },
       
 15783 
       
 15784     /**
       
 15785     * @method clearData
       
 15786     * @for NodeList
       
 15787     * @description Clears data on all Node instances bound to the NodeList.
       
 15788     * @param {string} name The name of the field to clear. If no name
       
 15789     * is given, all data is cleared.
       
 15790     * @chainable
       
 15791     */
       
 15792     clearData: function(name) {
       
 15793         var args = (arguments.length) ? [name] : [];
       
 15794         return this._invoke('clearData', [name]);
       
 15795     }
       
 15796 });
       
 15797 
       
 15798 
       
 15799 }, '@VERSION@', {"requires": ["event-base", "node-core", "dom-base"]});
       
 15800 (function () {
       
 15801 var GLOBAL_ENV = YUI.Env;
       
 15802 
       
 15803 if (!GLOBAL_ENV._ready) {
       
 15804     GLOBAL_ENV._ready = function() {
       
 15805         GLOBAL_ENV.DOMReady = true;
       
 15806         GLOBAL_ENV.remove(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
       
 15807     };
       
 15808 
       
 15809     GLOBAL_ENV.add(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
       
 15810 }
       
 15811 })();
       
 15812 YUI.add('event-base', function (Y, NAME) {
       
 15813 
       
 15814 /*
       
 15815  * DOM event listener abstraction layer
       
 15816  * @module event
       
 15817  * @submodule event-base
       
 15818  */
       
 15819 
       
 15820 /**
       
 15821  * The domready event fires at the moment the browser's DOM is
       
 15822  * usable. In most cases, this is before images are fully
       
 15823  * downloaded, allowing you to provide a more responsive user
       
 15824  * interface.
       
 15825  *
       
 15826  * In YUI 3, domready subscribers will be notified immediately if
       
 15827  * that moment has already passed when the subscription is created.
       
 15828  *
       
 15829  * One exception is if the yui.js file is dynamically injected into
       
 15830  * the page.  If this is done, you must tell the YUI instance that
       
 15831  * you did this in order for DOMReady (and window load events) to
       
 15832  * fire normally.  That configuration option is 'injected' -- set
       
 15833  * it to true if the yui.js script is not included inline.
       
 15834  *
       
 15835  * This method is part of the 'event-ready' module, which is a
       
 15836  * submodule of 'event'.
       
 15837  *
       
 15838  * @event domready
       
 15839  * @for YUI
       
 15840  */
       
 15841 Y.publish('domready', {
       
 15842     fireOnce: true,
       
 15843     async: true
       
 15844 });
       
 15845 
       
 15846 if (YUI.Env.DOMReady) {
       
 15847     Y.fire('domready');
       
 15848 } else {
       
 15849     Y.Do.before(function() { Y.fire('domready'); }, YUI.Env, '_ready');
       
 15850 }
       
 15851 
       
 15852 /**
       
 15853  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 15854  * events.
       
 15855  * @module event
       
 15856  * @submodule event-base
       
 15857  */
       
 15858 
       
 15859 /**
       
 15860  * Wraps a DOM event, properties requiring browser abstraction are
       
 15861  * fixed here.  Provids a security layer when required.
       
 15862  * @class DOMEventFacade
       
 15863  * @param ev {Event} the DOM event
       
 15864  * @param currentTarget {HTMLElement} the element the listener was attached to
       
 15865  * @param wrapper {Event.Custom} the custom event wrapper for this DOM event
       
 15866  */
       
 15867 
       
 15868     var ua = Y.UA,
       
 15869 
       
 15870     EMPTY = {},
       
 15871 
       
 15872     /**
       
 15873      * webkit key remapping required for Safari < 3.1
       
 15874      * @property webkitKeymap
       
 15875      * @private
       
 15876      */
       
 15877     webkitKeymap = {
       
 15878         63232: 38, // up
       
 15879         63233: 40, // down
       
 15880         63234: 37, // left
       
 15881         63235: 39, // right
       
 15882         63276: 33, // page up
       
 15883         63277: 34, // page down
       
 15884         25:     9, // SHIFT-TAB (Safari provides a different key code in
       
 15885                    // this case, even though the shiftKey modifier is set)
       
 15886         63272: 46, // delete
       
 15887         63273: 36, // home
       
 15888         63275: 35  // end
       
 15889     },
       
 15890 
       
 15891     /**
       
 15892      * Returns a wrapped node.  Intended to be used on event targets,
       
 15893      * so it will return the node's parent if the target is a text
       
 15894      * node.
       
 15895      *
       
 15896      * If accessing a property of the node throws an error, this is
       
 15897      * probably the anonymous div wrapper Gecko adds inside text
       
 15898      * nodes.  This likely will only occur when attempting to access
       
 15899      * the relatedTarget.  In this case, we now return null because
       
 15900      * the anonymous div is completely useless and we do not know
       
 15901      * what the related target was because we can't even get to
       
 15902      * the element's parent node.
       
 15903      *
       
 15904      * @method resolve
       
 15905      * @private
       
 15906      */
       
 15907     resolve = function(n) {
       
 15908         if (!n) {
       
 15909             return n;
       
 15910         }
       
 15911         try {
       
 15912             if (n && 3 == n.nodeType) {
       
 15913                 n = n.parentNode;
       
 15914             }
       
 15915         } catch(e) {
       
 15916             return null;
       
 15917         }
       
 15918 
       
 15919         return Y.one(n);
       
 15920     },
       
 15921 
       
 15922     DOMEventFacade = function(ev, currentTarget, wrapper) {
       
 15923         this._event = ev;
       
 15924         this._currentTarget = currentTarget;
       
 15925         this._wrapper = wrapper || EMPTY;
       
 15926 
       
 15927         // if not lazy init
       
 15928         this.init();
       
 15929     };
       
 15930 
       
 15931 Y.extend(DOMEventFacade, Object, {
       
 15932 
       
 15933     init: function() {
       
 15934 
       
 15935         var e = this._event,
       
 15936             overrides = this._wrapper.overrides,
       
 15937             x = e.pageX,
       
 15938             y = e.pageY,
       
 15939             c,
       
 15940             currentTarget = this._currentTarget;
       
 15941 
       
 15942         this.altKey   = e.altKey;
       
 15943         this.ctrlKey  = e.ctrlKey;
       
 15944         this.metaKey  = e.metaKey;
       
 15945         this.shiftKey = e.shiftKey;
       
 15946         this.type     = (overrides && overrides.type) || e.type;
       
 15947         this.clientX  = e.clientX;
       
 15948         this.clientY  = e.clientY;
       
 15949 
       
 15950         this.pageX = x;
       
 15951         this.pageY = y;
       
 15952 
       
 15953         // charCode is unknown in keyup, keydown. keyCode is unknown in keypress.
       
 15954         // FF 3.6 - 8+? pass 0 for keyCode in keypress events.
       
 15955         // Webkit, FF 3.6-8+?, and IE9+? pass 0 for charCode in keydown, keyup.
       
 15956         // Webkit and IE9+? duplicate charCode in keyCode.
       
 15957         // Opera never sets charCode, always keyCode (though with the charCode).
       
 15958         // IE6-8 don't set charCode or which.
       
 15959         // All browsers other than IE6-8 set which=keyCode in keydown, keyup, and
       
 15960         // which=charCode in keypress.
       
 15961         //
       
 15962         // Moral of the story: (e.which || e.keyCode) will always return the
       
 15963         // known code for that key event phase. e.keyCode is often different in
       
 15964         // keypress from keydown and keyup.
       
 15965         c = e.keyCode || e.charCode;
       
 15966 
       
 15967         if (ua.webkit && (c in webkitKeymap)) {
       
 15968             c = webkitKeymap[c];
       
 15969         }
       
 15970 
       
 15971         this.keyCode = c;
       
 15972         this.charCode = c;
       
 15973         // Fill in e.which for IE - implementers should always use this over
       
 15974         // e.keyCode or e.charCode.
       
 15975         this.which = e.which || e.charCode || c;
       
 15976         // this.button = e.button;
       
 15977         this.button = this.which;
       
 15978 
       
 15979         this.target = resolve(e.target);
       
 15980         this.currentTarget = resolve(currentTarget);
       
 15981         this.relatedTarget = resolve(e.relatedTarget);
       
 15982 
       
 15983         if (e.type == "mousewheel" || e.type == "DOMMouseScroll") {
       
 15984             this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
       
 15985         }
       
 15986 
       
 15987         if (this._touch) {
       
 15988             this._touch(e, currentTarget, this._wrapper);
       
 15989         }
       
 15990     },
       
 15991 
       
 15992     stopPropagation: function() {
       
 15993         this._event.stopPropagation();
       
 15994         this._wrapper.stopped = 1;
       
 15995         this.stopped = 1;
       
 15996     },
       
 15997 
       
 15998     stopImmediatePropagation: function() {
       
 15999         var e = this._event;
       
 16000         if (e.stopImmediatePropagation) {
       
 16001             e.stopImmediatePropagation();
       
 16002         } else {
       
 16003             this.stopPropagation();
       
 16004         }
       
 16005         this._wrapper.stopped = 2;
       
 16006         this.stopped = 2;
       
 16007     },
       
 16008 
       
 16009     preventDefault: function(returnValue) {
       
 16010         var e = this._event;
       
 16011         e.preventDefault();
       
 16012         e.returnValue = returnValue || false;
       
 16013         this._wrapper.prevented = 1;
       
 16014         this.prevented = 1;
       
 16015     },
       
 16016 
       
 16017     halt: function(immediate) {
       
 16018         if (immediate) {
       
 16019             this.stopImmediatePropagation();
       
 16020         } else {
       
 16021             this.stopPropagation();
       
 16022         }
       
 16023 
       
 16024         this.preventDefault();
       
 16025     }
       
 16026 
       
 16027 });
       
 16028 
       
 16029 DOMEventFacade.resolve = resolve;
       
 16030 Y.DOM2EventFacade = DOMEventFacade;
       
 16031 Y.DOMEventFacade = DOMEventFacade;
       
 16032 
       
 16033     /**
       
 16034      * The native event
       
 16035      * @property _event
       
 16036      * @type {Native DOM Event}
       
 16037      * @private
       
 16038      */
       
 16039 
       
 16040     /**
       
 16041     The name of the event (e.g. "click")
       
 16042 
       
 16043     @property type
       
 16044     @type {String}
       
 16045     **/
       
 16046 
       
 16047     /**
       
 16048     `true` if the "alt" or "option" key is pressed.
       
 16049 
       
 16050     @property altKey
       
 16051     @type {Boolean}
       
 16052     **/
       
 16053 
       
 16054     /**
       
 16055     `true` if the shift key is pressed.
       
 16056 
       
 16057     @property shiftKey
       
 16058     @type {Boolean}
       
 16059     **/
       
 16060 
       
 16061     /**
       
 16062     `true` if the "Windows" key on a Windows keyboard, "command" key on an
       
 16063     Apple keyboard, or "meta" key on other keyboards is pressed.
       
 16064 
       
 16065     @property metaKey
       
 16066     @type {Boolean}
       
 16067     **/
       
 16068 
       
 16069     /**
       
 16070     `true` if the "Ctrl" or "control" key is pressed.
       
 16071 
       
 16072     @property ctrlKey
       
 16073     @type {Boolean}
       
 16074     **/
       
 16075 
       
 16076     /**
       
 16077      * The X location of the event on the page (including scroll)
       
 16078      * @property pageX
       
 16079      * @type {Number}
       
 16080      */
       
 16081 
       
 16082     /**
       
 16083      * The Y location of the event on the page (including scroll)
       
 16084      * @property pageY
       
 16085      * @type {Number}
       
 16086      */
       
 16087 
       
 16088     /**
       
 16089      * The X location of the event in the viewport
       
 16090      * @property clientX
       
 16091      * @type {Number}
       
 16092      */
       
 16093 
       
 16094     /**
       
 16095      * The Y location of the event in the viewport
       
 16096      * @property clientY
       
 16097      * @type {Number}
       
 16098      */
       
 16099 
       
 16100     /**
       
 16101      * The keyCode for key events.  Uses charCode if keyCode is not available
       
 16102      * @property keyCode
       
 16103      * @type {Number}
       
 16104      */
       
 16105 
       
 16106     /**
       
 16107      * The charCode for key events.  Same as keyCode
       
 16108      * @property charCode
       
 16109      * @type {Number}
       
 16110      */
       
 16111 
       
 16112     /**
       
 16113      * The button that was pushed. 1 for left click, 2 for middle click, 3 for
       
 16114      * right click.  This is only reliably populated on `mouseup` events.
       
 16115      * @property button
       
 16116      * @type {Number}
       
 16117      */
       
 16118 
       
 16119     /**
       
 16120      * The button that was pushed.  Same as button.
       
 16121      * @property which
       
 16122      * @type {Number}
       
 16123      */
       
 16124 
       
 16125     /**
       
 16126      * Node reference for the targeted element
       
 16127      * @property target
       
 16128      * @type {Node}
       
 16129      */
       
 16130 
       
 16131     /**
       
 16132      * Node reference for the element that the listener was attached to.
       
 16133      * @property currentTarget
       
 16134      * @type {Node}
       
 16135      */
       
 16136 
       
 16137     /**
       
 16138      * Node reference to the relatedTarget
       
 16139      * @property relatedTarget
       
 16140      * @type {Node}
       
 16141      */
       
 16142 
       
 16143     /**
       
 16144      * Number representing the direction and velocity of the movement of the mousewheel.
       
 16145      * Negative is down, the higher the number, the faster.  Applies to the mousewheel event.
       
 16146      * @property wheelDelta
       
 16147      * @type {Number}
       
 16148      */
       
 16149 
       
 16150     /**
       
 16151      * Stops the propagation to the next bubble target
       
 16152      * @method stopPropagation
       
 16153      */
       
 16154 
       
 16155     /**
       
 16156      * Stops the propagation to the next bubble target and
       
 16157      * prevents any additional listeners from being exectued
       
 16158      * on the current target.
       
 16159      * @method stopImmediatePropagation
       
 16160      */
       
 16161 
       
 16162     /**
       
 16163      * Prevents the event's default behavior
       
 16164      * @method preventDefault
       
 16165      * @param returnValue {string} sets the returnValue of the event to this value
       
 16166      * (rather than the default false value).  This can be used to add a customized
       
 16167      * confirmation query to the beforeunload event).
       
 16168      */
       
 16169 
       
 16170     /**
       
 16171      * Stops the event propagation and prevents the default
       
 16172      * event behavior.
       
 16173      * @method halt
       
 16174      * @param immediate {boolean} if true additional listeners
       
 16175      * on the current target will not be executed
       
 16176      */
       
 16177 (function() {
       
 16178 
       
 16179 /**
       
 16180  * The event utility provides functions to add and remove event listeners,
       
 16181  * event cleansing.  It also tries to automatically remove listeners it
       
 16182  * registers during the unload event.
       
 16183  * @module event
       
 16184  * @main event
       
 16185  * @submodule event-base
       
 16186  */
       
 16187 
       
 16188 /**
       
 16189  * The event utility provides functions to add and remove event listeners,
       
 16190  * event cleansing.  It also tries to automatically remove listeners it
       
 16191  * registers during the unload event.
       
 16192  *
       
 16193  * @class Event
       
 16194  * @static
       
 16195  */
       
 16196 
       
 16197 Y.Env.evt.dom_wrappers = {};
       
 16198 Y.Env.evt.dom_map = {};
       
 16199 
       
 16200 var _eventenv = Y.Env.evt,
       
 16201     config = Y.config,
       
 16202     win = config.win,
       
 16203     add = YUI.Env.add,
       
 16204     remove = YUI.Env.remove,
       
 16205 
       
 16206     onLoad = function() {
       
 16207         YUI.Env.windowLoaded = true;
       
 16208         Y.Event._load();
       
 16209         remove(win, "load", onLoad);
       
 16210     },
       
 16211 
       
 16212     onUnload = function() {
       
 16213         Y.Event._unload();
       
 16214     },
       
 16215 
       
 16216     EVENT_READY = 'domready',
       
 16217 
       
 16218     COMPAT_ARG = '~yui|2|compat~',
       
 16219 
       
 16220     shouldIterate = function(o) {
       
 16221         try {
       
 16222             // TODO: See if there's a more performant way to return true early on this, for the common case
       
 16223             return (o && typeof o !== "string" && Y.Lang.isNumber(o.length) && !o.tagName && !Y.DOM.isWindow(o));
       
 16224         } catch(ex) {
       
 16225             Y.log("collection check failure", "warn", "event");
       
 16226             return false;
       
 16227         }
       
 16228     },
       
 16229 
       
 16230     // aliases to support DOM event subscription clean up when the last
       
 16231     // subscriber is detached. deleteAndClean overrides the DOM event's wrapper
       
 16232     // CustomEvent _delete method.
       
 16233     _ceProtoDelete = Y.CustomEvent.prototype._delete,
       
 16234     _deleteAndClean = function(s) {
       
 16235         var ret = _ceProtoDelete.apply(this, arguments);
       
 16236 
       
 16237         if (!this.hasSubs()) {
       
 16238             Y.Event._clean(this);
       
 16239         }
       
 16240 
       
 16241         return ret;
       
 16242     },
       
 16243 
       
 16244 Event = function() {
       
 16245 
       
 16246     /**
       
 16247      * True after the onload event has fired
       
 16248      * @property _loadComplete
       
 16249      * @type boolean
       
 16250      * @static
       
 16251      * @private
       
 16252      */
       
 16253     var _loadComplete =  false,
       
 16254 
       
 16255     /**
       
 16256      * The number of times to poll after window.onload.  This number is
       
 16257      * increased if additional late-bound handlers are requested after
       
 16258      * the page load.
       
 16259      * @property _retryCount
       
 16260      * @static
       
 16261      * @private
       
 16262      */
       
 16263     _retryCount = 0,
       
 16264 
       
 16265     /**
       
 16266      * onAvailable listeners
       
 16267      * @property _avail
       
 16268      * @static
       
 16269      * @private
       
 16270      */
       
 16271     _avail = [],
       
 16272 
       
 16273     /**
       
 16274      * Custom event wrappers for DOM events.  Key is
       
 16275      * 'event:' + Element uid stamp + event type
       
 16276      * @property _wrappers
       
 16277      * @type Y.Event.Custom
       
 16278      * @static
       
 16279      * @private
       
 16280      */
       
 16281     _wrappers = _eventenv.dom_wrappers,
       
 16282 
       
 16283     _windowLoadKey = null,
       
 16284 
       
 16285     /**
       
 16286      * Custom event wrapper map DOM events.  Key is
       
 16287      * Element uid stamp.  Each item is a hash of custom event
       
 16288      * wrappers as provided in the _wrappers collection.  This
       
 16289      * provides the infrastructure for getListeners.
       
 16290      * @property _el_events
       
 16291      * @static
       
 16292      * @private
       
 16293      */
       
 16294     _el_events = _eventenv.dom_map;
       
 16295 
       
 16296     return {
       
 16297 
       
 16298         /**
       
 16299          * The number of times we should look for elements that are not
       
 16300          * in the DOM at the time the event is requested after the document
       
 16301          * has been loaded.  The default is 1000@amp;40 ms, so it will poll
       
 16302          * for 40 seconds or until all outstanding handlers are bound
       
 16303          * (whichever comes first).
       
 16304          * @property POLL_RETRYS
       
 16305          * @type int
       
 16306          * @static
       
 16307          * @final
       
 16308          */
       
 16309         POLL_RETRYS: 1000,
       
 16310 
       
 16311         /**
       
 16312          * The poll interval in milliseconds
       
 16313          * @property POLL_INTERVAL
       
 16314          * @type int
       
 16315          * @static
       
 16316          * @final
       
 16317          */
       
 16318         POLL_INTERVAL: 40,
       
 16319 
       
 16320         /**
       
 16321          * addListener/removeListener can throw errors in unexpected scenarios.
       
 16322          * These errors are suppressed, the method returns false, and this property
       
 16323          * is set
       
 16324          * @property lastError
       
 16325          * @static
       
 16326          * @type Error
       
 16327          */
       
 16328         lastError: null,
       
 16329 
       
 16330 
       
 16331         /**
       
 16332          * poll handle
       
 16333          * @property _interval
       
 16334          * @static
       
 16335          * @private
       
 16336          */
       
 16337         _interval: null,
       
 16338 
       
 16339         /**
       
 16340          * document readystate poll handle
       
 16341          * @property _dri
       
 16342          * @static
       
 16343          * @private
       
 16344          */
       
 16345          _dri: null,
       
 16346 
       
 16347         /**
       
 16348          * True when the document is initially usable
       
 16349          * @property DOMReady
       
 16350          * @type boolean
       
 16351          * @static
       
 16352          */
       
 16353         DOMReady: false,
       
 16354 
       
 16355         /**
       
 16356          * @method startInterval
       
 16357          * @static
       
 16358          * @private
       
 16359          */
       
 16360         startInterval: function() {
       
 16361             if (!Event._interval) {
       
 16362 Event._interval = setInterval(Event._poll, Event.POLL_INTERVAL);
       
 16363             }
       
 16364         },
       
 16365 
       
 16366         /**
       
 16367          * Executes the supplied callback when the item with the supplied
       
 16368          * id is found.  This is meant to be used to execute behavior as
       
 16369          * soon as possible as the page loads.  If you use this after the
       
 16370          * initial page load it will poll for a fixed time for the element.
       
 16371          * The number of times it will poll and the frequency are
       
 16372          * configurable.  By default it will poll for 10 seconds.
       
 16373          *
       
 16374          * <p>The callback is executed with a single parameter:
       
 16375          * the custom object parameter, if provided.</p>
       
 16376          *
       
 16377          * @method onAvailable
       
 16378          *
       
 16379          * @param {string||string[]}   id the id of the element, or an array
       
 16380          * of ids to look for.
       
 16381          * @param {function} fn what to execute when the element is found.
       
 16382          * @param {object}   p_obj an optional object to be passed back as
       
 16383          *                   a parameter to fn.
       
 16384          * @param {boolean|object}  p_override If set to true, fn will execute
       
 16385          *                   in the context of p_obj, if set to an object it
       
 16386          *                   will execute in the context of that object
       
 16387          * @param checkContent {boolean} check child node readiness (onContentReady)
       
 16388          * @static
       
 16389          * @deprecated Use Y.on("available")
       
 16390          */
       
 16391         // @TODO fix arguments
       
 16392         onAvailable: function(id, fn, p_obj, p_override, checkContent, compat) {
       
 16393 
       
 16394             var a = Y.Array(id), i, availHandle;
       
 16395 
       
 16396             // Y.log('onAvailable registered for: ' + id);
       
 16397 
       
 16398             for (i=0; i<a.length; i=i+1) {
       
 16399                 _avail.push({
       
 16400                     id:         a[i],
       
 16401                     fn:         fn,
       
 16402                     obj:        p_obj,
       
 16403                     override:   p_override,
       
 16404                     checkReady: checkContent,
       
 16405                     compat:     compat
       
 16406                 });
       
 16407             }
       
 16408             _retryCount = this.POLL_RETRYS;
       
 16409 
       
 16410             // We want the first test to be immediate, but async
       
 16411             setTimeout(Event._poll, 0);
       
 16412 
       
 16413             availHandle = new Y.EventHandle({
       
 16414 
       
 16415                 _delete: function() {
       
 16416                     // set by the event system for lazy DOM listeners
       
 16417                     if (availHandle.handle) {
       
 16418                         availHandle.handle.detach();
       
 16419                         return;
       
 16420                     }
       
 16421 
       
 16422                     var i, j;
       
 16423 
       
 16424                     // otherwise try to remove the onAvailable listener(s)
       
 16425                     for (i = 0; i < a.length; i++) {
       
 16426                         for (j = 0; j < _avail.length; j++) {
       
 16427                             if (a[i] === _avail[j].id) {
       
 16428                                 _avail.splice(j, 1);
       
 16429                             }
       
 16430                         }
       
 16431                     }
       
 16432                 }
       
 16433 
       
 16434             });
       
 16435 
       
 16436             return availHandle;
       
 16437         },
       
 16438 
       
 16439         /**
       
 16440          * Works the same way as onAvailable, but additionally checks the
       
 16441          * state of sibling elements to determine if the content of the
       
 16442          * available element is safe to modify.
       
 16443          *
       
 16444          * <p>The callback is executed with a single parameter:
       
 16445          * the custom object parameter, if provided.</p>
       
 16446          *
       
 16447          * @method onContentReady
       
 16448          *
       
 16449          * @param {string}   id the id of the element to look for.
       
 16450          * @param {function} fn what to execute when the element is ready.
       
 16451          * @param {object}   obj an optional object to be passed back as
       
 16452          *                   a parameter to fn.
       
 16453          * @param {boolean|object}  override If set to true, fn will execute
       
 16454          *                   in the context of p_obj.  If an object, fn will
       
 16455          *                   exectute in the context of that object
       
 16456          *
       
 16457          * @static
       
 16458          * @deprecated Use Y.on("contentready")
       
 16459          */
       
 16460         // @TODO fix arguments
       
 16461         onContentReady: function(id, fn, obj, override, compat) {
       
 16462             return Event.onAvailable(id, fn, obj, override, true, compat);
       
 16463         },
       
 16464 
       
 16465         /**
       
 16466          * Adds an event listener
       
 16467          *
       
 16468          * @method attach
       
 16469          *
       
 16470          * @param {String}   type     The type of event to append
       
 16471          * @param {Function} fn        The method the event invokes
       
 16472          * @param {String|HTMLElement|Array|NodeList} el An id, an element
       
 16473          *  reference, or a collection of ids and/or elements to assign the
       
 16474          *  listener to.
       
 16475          * @param {Object}   context optional context object
       
 16476          * @param {Boolean|object}  args 0..n arguments to pass to the callback
       
 16477          * @return {EventHandle} an object to that can be used to detach the listener
       
 16478          *
       
 16479          * @static
       
 16480          */
       
 16481 
       
 16482         attach: function(type, fn, el, context) {
       
 16483             return Event._attach(Y.Array(arguments, 0, true));
       
 16484         },
       
 16485 
       
 16486         _createWrapper: function (el, type, capture, compat, facade) {
       
 16487 
       
 16488             var cewrapper,
       
 16489                 ek  = Y.stamp(el),
       
 16490                 key = 'event:' + ek + type;
       
 16491 
       
 16492             if (false === facade) {
       
 16493                 key += 'native';
       
 16494             }
       
 16495             if (capture) {
       
 16496                 key += 'capture';
       
 16497             }
       
 16498 
       
 16499 
       
 16500             cewrapper = _wrappers[key];
       
 16501 
       
 16502 
       
 16503             if (!cewrapper) {
       
 16504                 // create CE wrapper
       
 16505                 cewrapper = Y.publish(key, {
       
 16506                     silent: true,
       
 16507                     bubbles: false,
       
 16508                     emitFacade:false,
       
 16509                     contextFn: function() {
       
 16510                         if (compat) {
       
 16511                             return cewrapper.el;
       
 16512                         } else {
       
 16513                             cewrapper.nodeRef = cewrapper.nodeRef || Y.one(cewrapper.el);
       
 16514                             return cewrapper.nodeRef;
       
 16515                         }
       
 16516                     }
       
 16517                 });
       
 16518 
       
 16519                 cewrapper.overrides = {};
       
 16520 
       
 16521                 // for later removeListener calls
       
 16522                 cewrapper.el = el;
       
 16523                 cewrapper.key = key;
       
 16524                 cewrapper.domkey = ek;
       
 16525                 cewrapper.type = type;
       
 16526                 cewrapper.fn = function(e) {
       
 16527                     cewrapper.fire(Event.getEvent(e, el, (compat || (false === facade))));
       
 16528                 };
       
 16529                 cewrapper.capture = capture;
       
 16530 
       
 16531                 if (el == win && type == "load") {
       
 16532                     // window load happens once
       
 16533                     cewrapper.fireOnce = true;
       
 16534                     _windowLoadKey = key;
       
 16535                 }
       
 16536                 cewrapper._delete = _deleteAndClean;
       
 16537 
       
 16538                 _wrappers[key] = cewrapper;
       
 16539                 _el_events[ek] = _el_events[ek] || {};
       
 16540                 _el_events[ek][key] = cewrapper;
       
 16541 
       
 16542                 add(el, type, cewrapper.fn, capture);
       
 16543             }
       
 16544 
       
 16545             return cewrapper;
       
 16546 
       
 16547         },
       
 16548 
       
 16549         _attach: function(args, conf) {
       
 16550 
       
 16551             var compat,
       
 16552                 handles, oEl, cewrapper, context,
       
 16553                 fireNow = false, ret,
       
 16554                 type = args[0],
       
 16555                 fn = args[1],
       
 16556                 el = args[2] || win,
       
 16557                 facade = conf && conf.facade,
       
 16558                 capture = conf && conf.capture,
       
 16559                 overrides = conf && conf.overrides;
       
 16560 
       
 16561             if (args[args.length-1] === COMPAT_ARG) {
       
 16562                 compat = true;
       
 16563             }
       
 16564 
       
 16565             if (!fn || !fn.call) {
       
 16566 // throw new TypeError(type + " attach call failed, callback undefined");
       
 16567 Y.log(type + " attach call failed, invalid callback", "error", "event");
       
 16568                 return false;
       
 16569             }
       
 16570 
       
 16571             // The el argument can be an array of elements or element ids.
       
 16572             if (shouldIterate(el)) {
       
 16573 
       
 16574                 handles=[];
       
 16575 
       
 16576                 Y.each(el, function(v, k) {
       
 16577                     args[2] = v;
       
 16578                     handles.push(Event._attach(args.slice(), conf));
       
 16579                 });
       
 16580 
       
 16581                 // return (handles.length === 1) ? handles[0] : handles;
       
 16582                 return new Y.EventHandle(handles);
       
 16583 
       
 16584             // If the el argument is a string, we assume it is
       
 16585             // actually the id of the element.  If the page is loaded
       
 16586             // we convert el to the actual element, otherwise we
       
 16587             // defer attaching the event until the element is
       
 16588             // ready
       
 16589             } else if (Y.Lang.isString(el)) {
       
 16590 
       
 16591                 // oEl = (compat) ? Y.DOM.byId(el) : Y.Selector.query(el);
       
 16592 
       
 16593                 if (compat) {
       
 16594                     oEl = Y.DOM.byId(el);
       
 16595                 } else {
       
 16596 
       
 16597                     oEl = Y.Selector.query(el);
       
 16598 
       
 16599                     switch (oEl.length) {
       
 16600                         case 0:
       
 16601                             oEl = null;
       
 16602                             break;
       
 16603                         case 1:
       
 16604                             oEl = oEl[0];
       
 16605                             break;
       
 16606                         default:
       
 16607                             args[2] = oEl;
       
 16608                             return Event._attach(args, conf);
       
 16609                     }
       
 16610                 }
       
 16611 
       
 16612                 if (oEl) {
       
 16613 
       
 16614                     el = oEl;
       
 16615 
       
 16616                 // Not found = defer adding the event until the element is available
       
 16617                 } else {
       
 16618 
       
 16619                     // Y.log(el + ' not found');
       
 16620                     ret = Event.onAvailable(el, function() {
       
 16621                         // Y.log('lazy attach: ' + args);
       
 16622 
       
 16623                         ret.handle = Event._attach(args, conf);
       
 16624 
       
 16625                     }, Event, true, false, compat);
       
 16626 
       
 16627                     return ret;
       
 16628 
       
 16629                 }
       
 16630             }
       
 16631 
       
 16632             // Element should be an html element or node
       
 16633             if (!el) {
       
 16634                 Y.log("unable to attach event " + type, "warn", "event");
       
 16635                 return false;
       
 16636             }
       
 16637 
       
 16638             if (Y.Node && Y.instanceOf(el, Y.Node)) {
       
 16639                 el = Y.Node.getDOMNode(el);
       
 16640             }
       
 16641 
       
 16642             cewrapper = Event._createWrapper(el, type, capture, compat, facade);
       
 16643             if (overrides) {
       
 16644                 Y.mix(cewrapper.overrides, overrides);
       
 16645             }
       
 16646 
       
 16647             if (el == win && type == "load") {
       
 16648 
       
 16649                 // if the load is complete, fire immediately.
       
 16650                 // all subscribers, including the current one
       
 16651                 // will be notified.
       
 16652                 if (YUI.Env.windowLoaded) {
       
 16653                     fireNow = true;
       
 16654                 }
       
 16655             }
       
 16656 
       
 16657             if (compat) {
       
 16658                 args.pop();
       
 16659             }
       
 16660 
       
 16661             context = args[3];
       
 16662 
       
 16663             // set context to the Node if not specified
       
 16664             // ret = cewrapper.on.apply(cewrapper, trimmedArgs);
       
 16665             ret = cewrapper._on(fn, context, (args.length > 4) ? args.slice(4) : null);
       
 16666 
       
 16667             if (fireNow) {
       
 16668                 cewrapper.fire();
       
 16669             }
       
 16670 
       
 16671             return ret;
       
 16672 
       
 16673         },
       
 16674 
       
 16675         /**
       
 16676          * Removes an event listener.  Supports the signature the event was bound
       
 16677          * with, but the preferred way to remove listeners is using the handle
       
 16678          * that is returned when using Y.on
       
 16679          *
       
 16680          * @method detach
       
 16681          *
       
 16682          * @param {String} type the type of event to remove.
       
 16683          * @param {Function} fn the method the event invokes.  If fn is
       
 16684          * undefined, then all event handlers for the type of event are
       
 16685          * removed.
       
 16686          * @param {String|HTMLElement|Array|NodeList|EventHandle} el An
       
 16687          * event handle, an id, an element reference, or a collection
       
 16688          * of ids and/or elements to remove the listener from.
       
 16689          * @return {boolean} true if the unbind was successful, false otherwise.
       
 16690          * @static
       
 16691          */
       
 16692         detach: function(type, fn, el, obj) {
       
 16693 
       
 16694             var args=Y.Array(arguments, 0, true), compat, l, ok, i,
       
 16695                 id, ce;
       
 16696 
       
 16697             if (args[args.length-1] === COMPAT_ARG) {
       
 16698                 compat = true;
       
 16699                 // args.pop();
       
 16700             }
       
 16701 
       
 16702             if (type && type.detach) {
       
 16703                 return type.detach();
       
 16704             }
       
 16705 
       
 16706             // The el argument can be a string
       
 16707             if (typeof el == "string") {
       
 16708 
       
 16709                 // el = (compat) ? Y.DOM.byId(el) : Y.all(el);
       
 16710                 if (compat) {
       
 16711                     el = Y.DOM.byId(el);
       
 16712                 } else {
       
 16713                     el = Y.Selector.query(el);
       
 16714                     l = el.length;
       
 16715                     if (l < 1) {
       
 16716                         el = null;
       
 16717                     } else if (l == 1) {
       
 16718                         el = el[0];
       
 16719                     }
       
 16720                 }
       
 16721                 // return Event.detach.apply(Event, args);
       
 16722             }
       
 16723 
       
 16724             if (!el) {
       
 16725                 return false;
       
 16726             }
       
 16727 
       
 16728             if (el.detach) {
       
 16729                 args.splice(2, 1);
       
 16730                 return el.detach.apply(el, args);
       
 16731             // The el argument can be an array of elements or element ids.
       
 16732             } else if (shouldIterate(el)) {
       
 16733                 ok = true;
       
 16734                 for (i=0, l=el.length; i<l; ++i) {
       
 16735                     args[2] = el[i];
       
 16736                     ok = ( Y.Event.detach.apply(Y.Event, args) && ok );
       
 16737                 }
       
 16738 
       
 16739                 return ok;
       
 16740             }
       
 16741 
       
 16742             if (!type || !fn || !fn.call) {
       
 16743                 return Event.purgeElement(el, false, type);
       
 16744             }
       
 16745 
       
 16746             id = 'event:' + Y.stamp(el) + type;
       
 16747             ce = _wrappers[id];
       
 16748 
       
 16749             if (ce) {
       
 16750                 return ce.detach(fn);
       
 16751             } else {
       
 16752                 return false;
       
 16753             }
       
 16754 
       
 16755         },
       
 16756 
       
 16757         /**
       
 16758          * Finds the event in the window object, the caller's arguments, or
       
 16759          * in the arguments of another method in the callstack.  This is
       
 16760          * executed automatically for events registered through the event
       
 16761          * manager, so the implementer should not normally need to execute
       
 16762          * this function at all.
       
 16763          * @method getEvent
       
 16764          * @param {Event} e the event parameter from the handler
       
 16765          * @param {HTMLElement} el the element the listener was attached to
       
 16766          * @return {Event} the event
       
 16767          * @static
       
 16768          */
       
 16769         getEvent: function(e, el, noFacade) {
       
 16770             var ev = e || win.event;
       
 16771 
       
 16772             return (noFacade) ? ev :
       
 16773                 new Y.DOMEventFacade(ev, el, _wrappers['event:' + Y.stamp(el) + e.type]);
       
 16774         },
       
 16775 
       
 16776         /**
       
 16777          * Generates an unique ID for the element if it does not already
       
 16778          * have one.
       
 16779          * @method generateId
       
 16780          * @param el the element to create the id for
       
 16781          * @return {string} the resulting id of the element
       
 16782          * @static
       
 16783          */
       
 16784         generateId: function(el) {
       
 16785             return Y.DOM.generateID(el);
       
 16786         },
       
 16787 
       
 16788         /**
       
 16789          * We want to be able to use getElementsByTagName as a collection
       
 16790          * to attach a group of events to.  Unfortunately, different
       
 16791          * browsers return different types of collections.  This function
       
 16792          * tests to determine if the object is array-like.  It will also
       
 16793          * fail if the object is an array, but is empty.
       
 16794          * @method _isValidCollection
       
 16795          * @param o the object to test
       
 16796          * @return {boolean} true if the object is array-like and populated
       
 16797          * @deprecated was not meant to be used directly
       
 16798          * @static
       
 16799          * @private
       
 16800          */
       
 16801         _isValidCollection: shouldIterate,
       
 16802 
       
 16803         /**
       
 16804          * hook up any deferred listeners
       
 16805          * @method _load
       
 16806          * @static
       
 16807          * @private
       
 16808          */
       
 16809         _load: function(e) {
       
 16810             if (!_loadComplete) {
       
 16811                 // Y.log('Load Complete', 'info', 'event');
       
 16812                 _loadComplete = true;
       
 16813 
       
 16814                 // Just in case DOMReady did not go off for some reason
       
 16815                 // E._ready();
       
 16816                 if (Y.fire) {
       
 16817                     Y.fire(EVENT_READY);
       
 16818                 }
       
 16819 
       
 16820                 // Available elements may not have been detected before the
       
 16821                 // window load event fires. Try to find them now so that the
       
 16822                 // the user is more likely to get the onAvailable notifications
       
 16823                 // before the window load notification
       
 16824                 Event._poll();
       
 16825             }
       
 16826         },
       
 16827 
       
 16828         /**
       
 16829          * Polling function that runs before the onload event fires,
       
 16830          * attempting to attach to DOM Nodes as soon as they are
       
 16831          * available
       
 16832          * @method _poll
       
 16833          * @static
       
 16834          * @private
       
 16835          */
       
 16836         _poll: function() {
       
 16837             if (Event.locked) {
       
 16838                 return;
       
 16839             }
       
 16840 
       
 16841             if (Y.UA.ie && !YUI.Env.DOMReady) {
       
 16842                 // Hold off if DOMReady has not fired and check current
       
 16843                 // readyState to protect against the IE operation aborted
       
 16844                 // issue.
       
 16845                 Event.startInterval();
       
 16846                 return;
       
 16847             }
       
 16848 
       
 16849             Event.locked = true;
       
 16850 
       
 16851             // Y.log.debug("poll");
       
 16852             // keep trying until after the page is loaded.  We need to
       
 16853             // check the page load state prior to trying to bind the
       
 16854             // elements so that we can be certain all elements have been
       
 16855             // tested appropriately
       
 16856             var i, len, item, el, notAvail, executeItem,
       
 16857                 tryAgain = !_loadComplete;
       
 16858 
       
 16859             if (!tryAgain) {
       
 16860                 tryAgain = (_retryCount > 0);
       
 16861             }
       
 16862 
       
 16863             // onAvailable
       
 16864             notAvail = [];
       
 16865 
       
 16866             executeItem = function (el, item) {
       
 16867                 var context, ov = item.override;
       
 16868                 try {
       
 16869                     if (item.compat) {
       
 16870                         if (item.override) {
       
 16871                             if (ov === true) {
       
 16872                                 context = item.obj;
       
 16873                             } else {
       
 16874                                 context = ov;
       
 16875                             }
       
 16876                         } else {
       
 16877                             context = el;
       
 16878                         }
       
 16879                         item.fn.call(context, item.obj);
       
 16880                     } else {
       
 16881                         context = item.obj || Y.one(el);
       
 16882                         item.fn.apply(context, (Y.Lang.isArray(ov)) ? ov : []);
       
 16883                     }
       
 16884                 } catch (e) {
       
 16885                     Y.log("Error in available or contentReady callback", 'error', 'event');
       
 16886                 }
       
 16887             };
       
 16888 
       
 16889             // onAvailable
       
 16890             for (i=0,len=_avail.length; i<len; ++i) {
       
 16891                 item = _avail[i];
       
 16892                 if (item && !item.checkReady) {
       
 16893 
       
 16894                     // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
       
 16895                     el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
       
 16896 
       
 16897                     if (el) {
       
 16898                         // Y.log('avail: ' + el);
       
 16899                         executeItem(el, item);
       
 16900                         _avail[i] = null;
       
 16901                     } else {
       
 16902                         // Y.log('NOT avail: ' + el);
       
 16903                         notAvail.push(item);
       
 16904                     }
       
 16905                 }
       
 16906             }
       
 16907 
       
 16908             // onContentReady
       
 16909             for (i=0,len=_avail.length; i<len; ++i) {
       
 16910                 item = _avail[i];
       
 16911                 if (item && item.checkReady) {
       
 16912 
       
 16913                     // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
       
 16914                     el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
       
 16915 
       
 16916                     if (el) {
       
 16917                         // The element is available, but not necessarily ready
       
 16918                         // @todo should we test parentNode.nextSibling?
       
 16919                         if (_loadComplete || (el.get && el.get('nextSibling')) || el.nextSibling) {
       
 16920                             executeItem(el, item);
       
 16921                             _avail[i] = null;
       
 16922                         }
       
 16923                     } else {
       
 16924                         notAvail.push(item);
       
 16925                     }
       
 16926                 }
       
 16927             }
       
 16928 
       
 16929             _retryCount = (notAvail.length === 0) ? 0 : _retryCount - 1;
       
 16930 
       
 16931             if (tryAgain) {
       
 16932                 // we may need to strip the nulled out items here
       
 16933                 Event.startInterval();
       
 16934             } else {
       
 16935                 clearInterval(Event._interval);
       
 16936                 Event._interval = null;
       
 16937             }
       
 16938 
       
 16939             Event.locked = false;
       
 16940 
       
 16941             return;
       
 16942 
       
 16943         },
       
 16944 
       
 16945         /**
       
 16946          * Removes all listeners attached to the given element via addListener.
       
 16947          * Optionally, the node's children can also be purged.
       
 16948          * Optionally, you can specify a specific type of event to remove.
       
 16949          * @method purgeElement
       
 16950          * @param {HTMLElement} el the element to purge
       
 16951          * @param {boolean} recurse recursively purge this element's children
       
 16952          * as well.  Use with caution.
       
 16953          * @param {string} type optional type of listener to purge. If
       
 16954          * left out, all listeners will be removed
       
 16955          * @static
       
 16956          */
       
 16957         purgeElement: function(el, recurse, type) {
       
 16958             // var oEl = (Y.Lang.isString(el)) ? Y.one(el) : el,
       
 16959             var oEl = (Y.Lang.isString(el)) ?  Y.Selector.query(el, null, true) : el,
       
 16960                 lis = Event.getListeners(oEl, type), i, len, children, child;
       
 16961 
       
 16962             if (recurse && oEl) {
       
 16963                 lis = lis || [];
       
 16964                 children = Y.Selector.query('*', oEl);
       
 16965                 len = children.length;
       
 16966                 for (i = 0; i < len; ++i) {
       
 16967                     child = Event.getListeners(children[i], type);
       
 16968                     if (child) {
       
 16969                         lis = lis.concat(child);
       
 16970                     }
       
 16971                 }
       
 16972             }
       
 16973 
       
 16974             if (lis) {
       
 16975                 for (i = 0, len = lis.length; i < len; ++i) {
       
 16976                     lis[i].detachAll();
       
 16977                 }
       
 16978             }
       
 16979 
       
 16980         },
       
 16981 
       
 16982         /**
       
 16983          * Removes all object references and the DOM proxy subscription for
       
 16984          * a given event for a DOM node.
       
 16985          *
       
 16986          * @method _clean
       
 16987          * @param wrapper {CustomEvent} Custom event proxy for the DOM
       
 16988          *                  subscription
       
 16989          * @private
       
 16990          * @static
       
 16991          * @since 3.4.0
       
 16992          */
       
 16993         _clean: function (wrapper) {
       
 16994             var key    = wrapper.key,
       
 16995                 domkey = wrapper.domkey;
       
 16996 
       
 16997             remove(wrapper.el, wrapper.type, wrapper.fn, wrapper.capture);
       
 16998             delete _wrappers[key];
       
 16999             delete Y._yuievt.events[key];
       
 17000             if (_el_events[domkey]) {
       
 17001                 delete _el_events[domkey][key];
       
 17002                 if (!Y.Object.size(_el_events[domkey])) {
       
 17003                     delete _el_events[domkey];
       
 17004                 }
       
 17005             }
       
 17006         },
       
 17007 
       
 17008         /**
       
 17009          * Returns all listeners attached to the given element via addListener.
       
 17010          * Optionally, you can specify a specific type of event to return.
       
 17011          * @method getListeners
       
 17012          * @param el {HTMLElement|string} the element or element id to inspect
       
 17013          * @param type {string} optional type of listener to return. If
       
 17014          * left out, all listeners will be returned
       
 17015          * @return {CustomEvent} the custom event wrapper for the DOM event(s)
       
 17016          * @static
       
 17017          */
       
 17018         getListeners: function(el, type) {
       
 17019             var ek = Y.stamp(el, true), evts = _el_events[ek],
       
 17020                 results=[] , key = (type) ? 'event:' + ek + type : null,
       
 17021                 adapters = _eventenv.plugins;
       
 17022 
       
 17023             if (!evts) {
       
 17024                 return null;
       
 17025             }
       
 17026 
       
 17027             if (key) {
       
 17028                 // look for synthetic events
       
 17029                 if (adapters[type] && adapters[type].eventDef) {
       
 17030                     key += '_synth';
       
 17031                 }
       
 17032 
       
 17033                 if (evts[key]) {
       
 17034                     results.push(evts[key]);
       
 17035                 }
       
 17036 
       
 17037                 // get native events as well
       
 17038                 key += 'native';
       
 17039                 if (evts[key]) {
       
 17040                     results.push(evts[key]);
       
 17041                 }
       
 17042 
       
 17043             } else {
       
 17044                 Y.each(evts, function(v, k) {
       
 17045                     results.push(v);
       
 17046                 });
       
 17047             }
       
 17048 
       
 17049             return (results.length) ? results : null;
       
 17050         },
       
 17051 
       
 17052         /**
       
 17053          * Removes all listeners registered by pe.event.  Called
       
 17054          * automatically during the unload event.
       
 17055          * @method _unload
       
 17056          * @static
       
 17057          * @private
       
 17058          */
       
 17059         _unload: function(e) {
       
 17060             Y.each(_wrappers, function(v, k) {
       
 17061                 if (v.type == 'unload') {
       
 17062                     v.fire(e);
       
 17063                 }
       
 17064                 v.detachAll();
       
 17065             });
       
 17066             remove(win, "unload", onUnload);
       
 17067         },
       
 17068 
       
 17069         /**
       
 17070          * Adds a DOM event directly without the caching, cleanup, context adj, etc
       
 17071          *
       
 17072          * @method nativeAdd
       
 17073          * @param {HTMLElement} el      the element to bind the handler to
       
 17074          * @param {string}      type   the type of event handler
       
 17075          * @param {function}    fn      the callback to invoke
       
 17076          * @param {boolen}      capture capture or bubble phase
       
 17077          * @static
       
 17078          * @private
       
 17079          */
       
 17080         nativeAdd: add,
       
 17081 
       
 17082         /**
       
 17083          * Basic remove listener
       
 17084          *
       
 17085          * @method nativeRemove
       
 17086          * @param {HTMLElement} el      the element to bind the handler to
       
 17087          * @param {string}      type   the type of event handler
       
 17088          * @param {function}    fn      the callback to invoke
       
 17089          * @param {boolen}      capture capture or bubble phase
       
 17090          * @static
       
 17091          * @private
       
 17092          */
       
 17093         nativeRemove: remove
       
 17094     };
       
 17095 
       
 17096 }();
       
 17097 
       
 17098 Y.Event = Event;
       
 17099 
       
 17100 if (config.injected || YUI.Env.windowLoaded) {
       
 17101     onLoad();
       
 17102 } else {
       
 17103     add(win, "load", onLoad);
       
 17104 }
       
 17105 
       
 17106 // Process onAvailable/onContentReady items when when the DOM is ready in IE
       
 17107 if (Y.UA.ie) {
       
 17108     Y.on(EVENT_READY, Event._poll);
       
 17109 }
       
 17110 
       
 17111 try {
       
 17112     add(win, "unload", onUnload);
       
 17113 } catch(e) {
       
 17114     /*jshint maxlen:300*/
       
 17115     Y.log("Registering unload listener failed. This is known to happen in Chrome Packaged Apps and Extensions, which don't support unload, and don't provide a way to test for support", "warn", "event-base");
       
 17116 }
       
 17117 
       
 17118 Event.Custom = Y.CustomEvent;
       
 17119 Event.Subscriber = Y.Subscriber;
       
 17120 Event.Target = Y.EventTarget;
       
 17121 Event.Handle = Y.EventHandle;
       
 17122 Event.Facade = Y.EventFacade;
       
 17123 
       
 17124 Event._poll();
       
 17125 
       
 17126 }());
       
 17127 
       
 17128 /**
       
 17129  * DOM event listener abstraction layer
       
 17130  * @module event
       
 17131  * @submodule event-base
       
 17132  */
       
 17133 
       
 17134 /**
       
 17135  * Executes the callback as soon as the specified element
       
 17136  * is detected in the DOM.  This function expects a selector
       
 17137  * string for the element(s) to detect.  If you already have
       
 17138  * an element reference, you don't need this event.
       
 17139  * @event available
       
 17140  * @param type {string} 'available'
       
 17141  * @param fn {function} the callback function to execute.
       
 17142  * @param el {string} an selector for the element(s) to attach
       
 17143  * @param context optional argument that specifies what 'this' refers to.
       
 17144  * @param args* 0..n additional arguments to pass on to the callback function.
       
 17145  * These arguments will be added after the event object.
       
 17146  * @return {EventHandle} the detach handle
       
 17147  * @for YUI
       
 17148  */
       
 17149 Y.Env.evt.plugins.available = {
       
 17150     on: function(type, fn, id, o) {
       
 17151         var a = arguments.length > 4 ?  Y.Array(arguments, 4, true) : null;
       
 17152         return Y.Event.onAvailable.call(Y.Event, id, fn, o, a);
       
 17153     }
       
 17154 };
       
 17155 
       
 17156 /**
       
 17157  * Executes the callback as soon as the specified element
       
 17158  * is detected in the DOM with a nextSibling property
       
 17159  * (indicating that the element's children are available).
       
 17160  * This function expects a selector
       
 17161  * string for the element(s) to detect.  If you already have
       
 17162  * an element reference, you don't need this event.
       
 17163  * @event contentready
       
 17164  * @param type {string} 'contentready'
       
 17165  * @param fn {function} the callback function to execute.
       
 17166  * @param el {string} an selector for the element(s) to attach.
       
 17167  * @param context optional argument that specifies what 'this' refers to.
       
 17168  * @param args* 0..n additional arguments to pass on to the callback function.
       
 17169  * These arguments will be added after the event object.
       
 17170  * @return {EventHandle} the detach handle
       
 17171  * @for YUI
       
 17172  */
       
 17173 Y.Env.evt.plugins.contentready = {
       
 17174     on: function(type, fn, id, o) {
       
 17175         var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
       
 17176         return Y.Event.onContentReady.call(Y.Event, id, fn, o, a);
       
 17177     }
       
 17178 };
       
 17179 
       
 17180 
       
 17181 }, '@VERSION@', {"requires": ["event-custom-base"]});
       
 17182 (function() {
       
 17183 
       
 17184 var stateChangeListener,
       
 17185     GLOBAL_ENV   = YUI.Env,
       
 17186     config       = YUI.config,
       
 17187     doc          = config.doc,
       
 17188     docElement   = doc && doc.documentElement,
       
 17189     EVENT_NAME   = 'onreadystatechange',
       
 17190     pollInterval = config.pollInterval || 40;
       
 17191 
       
 17192 if (docElement.doScroll && !GLOBAL_ENV._ieready) {
       
 17193     GLOBAL_ENV._ieready = function() {
       
 17194         GLOBAL_ENV._ready();
       
 17195     };
       
 17196 
       
 17197 /*! DOMReady: based on work by: Dean Edwards/John Resig/Matthias Miller/Diego Perini */
       
 17198 // Internet Explorer: use the doScroll() method on the root element.
       
 17199 // This isolates what appears to be a safe moment to manipulate the
       
 17200 // DOM prior to when the document's readyState suggests it is safe to do so.
       
 17201     if (self !== self.top) {
       
 17202         stateChangeListener = function() {
       
 17203             if (doc.readyState == 'complete') {
       
 17204                 GLOBAL_ENV.remove(doc, EVENT_NAME, stateChangeListener);
       
 17205                 GLOBAL_ENV.ieready();
       
 17206             }
       
 17207         };
       
 17208         GLOBAL_ENV.add(doc, EVENT_NAME, stateChangeListener);
       
 17209     } else {
       
 17210         GLOBAL_ENV._dri = setInterval(function() {
       
 17211             try {
       
 17212                 docElement.doScroll('left');
       
 17213                 clearInterval(GLOBAL_ENV._dri);
       
 17214                 GLOBAL_ENV._dri = null;
       
 17215                 GLOBAL_ENV._ieready();
       
 17216             } catch (domNotReady) { }
       
 17217         }, pollInterval);
       
 17218     }
       
 17219 }
       
 17220 
       
 17221 })();
       
 17222 YUI.add('event-base-ie', function (Y, NAME) {
       
 17223 
       
 17224 /*
       
 17225  * Custom event engine, DOM event listener abstraction layer, synthetic DOM
       
 17226  * events.
       
 17227  * @module event
       
 17228  * @submodule event-base
       
 17229  */
       
 17230 
       
 17231 function IEEventFacade() {
       
 17232     // IEEventFacade.superclass.constructor.apply(this, arguments);
       
 17233     Y.DOM2EventFacade.apply(this, arguments);
       
 17234 }
       
 17235 
       
 17236 /*
       
 17237  * (intentially left out of API docs)
       
 17238  * Alternate Facade implementation that is based on Object.defineProperty, which
       
 17239  * is partially supported in IE8.  Properties that involve setup work are
       
 17240  * deferred to temporary getters using the static _define method.
       
 17241  */
       
 17242 function IELazyFacade(e) {
       
 17243     var proxy = Y.config.doc.createEventObject(e),
       
 17244         proto = IELazyFacade.prototype;
       
 17245 
       
 17246     // TODO: necessary?
       
 17247     proxy.hasOwnProperty = function () { return true; };
       
 17248 
       
 17249     proxy.init = proto.init;
       
 17250     proxy.halt = proto.halt;
       
 17251     proxy.preventDefault           = proto.preventDefault;
       
 17252     proxy.stopPropagation          = proto.stopPropagation;
       
 17253     proxy.stopImmediatePropagation = proto.stopImmediatePropagation;
       
 17254 
       
 17255     Y.DOM2EventFacade.apply(proxy, arguments);
       
 17256 
       
 17257     return proxy;
       
 17258 }
       
 17259 
       
 17260 
       
 17261 var imp = Y.config.doc && Y.config.doc.implementation,
       
 17262     useLazyFacade = Y.config.lazyEventFacade,
       
 17263 
       
 17264     buttonMap = {
       
 17265         0: 1, // left click
       
 17266         4: 2, // middle click
       
 17267         2: 3  // right click
       
 17268     },
       
 17269     relatedTargetMap = {
       
 17270         mouseout: 'toElement',
       
 17271         mouseover: 'fromElement'
       
 17272     },
       
 17273 
       
 17274     resolve = Y.DOM2EventFacade.resolve,
       
 17275 
       
 17276     proto = {
       
 17277         init: function() {
       
 17278 
       
 17279             IEEventFacade.superclass.init.apply(this, arguments);
       
 17280 
       
 17281             var e = this._event,
       
 17282                 x, y, d, b, de, t;
       
 17283 
       
 17284             this.target = resolve(e.srcElement);
       
 17285 
       
 17286             if (('clientX' in e) && (!x) && (0 !== x)) {
       
 17287                 x = e.clientX;
       
 17288                 y = e.clientY;
       
 17289 
       
 17290                 d = Y.config.doc;
       
 17291                 b = d.body;
       
 17292                 de = d.documentElement;
       
 17293 
       
 17294                 x += (de.scrollLeft || (b && b.scrollLeft) || 0);
       
 17295                 y += (de.scrollTop  || (b && b.scrollTop)  || 0);
       
 17296 
       
 17297                 this.pageX = x;
       
 17298                 this.pageY = y;
       
 17299             }
       
 17300 
       
 17301             if (e.type == "mouseout") {
       
 17302                 t = e.toElement;
       
 17303             } else if (e.type == "mouseover") {
       
 17304                 t = e.fromElement;
       
 17305             }
       
 17306 
       
 17307             // fallback to t.relatedTarget to support simulated events.
       
 17308             // IE doesn't support setting toElement or fromElement on generic
       
 17309             // events, so Y.Event.simulate sets relatedTarget instead.
       
 17310             this.relatedTarget = resolve(t || e.relatedTarget);
       
 17311 
       
 17312             // which should contain the unicode key code if this is a key event.
       
 17313             // For click events, which is normalized for which mouse button was
       
 17314             // clicked.
       
 17315             this.which = // chained assignment
       
 17316             this.button = e.keyCode || buttonMap[e.button] || e.button;
       
 17317         },
       
 17318 
       
 17319         stopPropagation: function() {
       
 17320             this._event.cancelBubble = true;
       
 17321             this._wrapper.stopped = 1;
       
 17322             this.stopped = 1;
       
 17323         },
       
 17324 
       
 17325         stopImmediatePropagation: function() {
       
 17326             this.stopPropagation();
       
 17327             this._wrapper.stopped = 2;
       
 17328             this.stopped = 2;
       
 17329         },
       
 17330 
       
 17331         preventDefault: function(returnValue) {
       
 17332             this._event.returnValue = returnValue || false;
       
 17333             this._wrapper.prevented = 1;
       
 17334             this.prevented = 1;
       
 17335         }
       
 17336     };
       
 17337 
       
 17338 Y.extend(IEEventFacade, Y.DOM2EventFacade, proto);
       
 17339 
       
 17340 Y.extend(IELazyFacade, Y.DOM2EventFacade, proto);
       
 17341 IELazyFacade.prototype.init = function () {
       
 17342     var e         = this._event,
       
 17343         overrides = this._wrapper.overrides,
       
 17344         define    = IELazyFacade._define,
       
 17345         lazyProperties = IELazyFacade._lazyProperties,
       
 17346         prop;
       
 17347 
       
 17348     this.altKey   = e.altKey;
       
 17349     this.ctrlKey  = e.ctrlKey;
       
 17350     this.metaKey  = e.metaKey;
       
 17351     this.shiftKey = e.shiftKey;
       
 17352     this.type     = (overrides && overrides.type) || e.type;
       
 17353     this.clientX  = e.clientX;
       
 17354     this.clientY  = e.clientY;
       
 17355     this.keyCode  = // chained assignment
       
 17356     this.charCode = e.keyCode;
       
 17357     this.which    = // chained assignment
       
 17358     this.button   = e.keyCode || buttonMap[e.button] || e.button;
       
 17359 
       
 17360     for (prop in lazyProperties) {
       
 17361         if (lazyProperties.hasOwnProperty(prop)) {
       
 17362             define(this, prop, lazyProperties[prop]);
       
 17363         }
       
 17364     }
       
 17365 
       
 17366     if (this._touch) {
       
 17367         this._touch(e, this._currentTarget, this._wrapper);
       
 17368     }
       
 17369 };
       
 17370 
       
 17371 IELazyFacade._lazyProperties = {
       
 17372     target: function () {
       
 17373         return resolve(this._event.srcElement);
       
 17374     },
       
 17375     relatedTarget: function () {
       
 17376         var e = this._event,
       
 17377             targetProp = relatedTargetMap[e.type] || 'relatedTarget';
       
 17378 
       
 17379         // fallback to t.relatedTarget to support simulated events.
       
 17380         // IE doesn't support setting toElement or fromElement on generic
       
 17381         // events, so Y.Event.simulate sets relatedTarget instead.
       
 17382         return resolve(e[targetProp] || e.relatedTarget);
       
 17383     },
       
 17384     currentTarget: function () {
       
 17385         return resolve(this._currentTarget);
       
 17386     },
       
 17387 
       
 17388     wheelDelta: function () {
       
 17389         var e = this._event;
       
 17390 
       
 17391         if (e.type === "mousewheel" || e.type === "DOMMouseScroll") {
       
 17392             return (e.detail) ?
       
 17393                 (e.detail * -1) :
       
 17394                 // wheelDelta between -80 and 80 result in -1 or 1
       
 17395                 Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
       
 17396         }
       
 17397     },
       
 17398 
       
 17399     pageX: function () {
       
 17400         var e = this._event,
       
 17401             val = e.pageX,
       
 17402             doc, bodyScroll, docScroll;
       
 17403 
       
 17404         if (val === undefined) {
       
 17405             doc = Y.config.doc;
       
 17406             bodyScroll = doc.body && doc.body.scrollLeft;
       
 17407             docScroll = doc.documentElement.scrollLeft;
       
 17408 
       
 17409             val = e.clientX + (docScroll || bodyScroll || 0);
       
 17410         }
       
 17411 
       
 17412         return val;
       
 17413     },
       
 17414     pageY: function () {
       
 17415         var e = this._event,
       
 17416             val = e.pageY,
       
 17417             doc, bodyScroll, docScroll;
       
 17418 
       
 17419         if (val === undefined) {
       
 17420             doc = Y.config.doc;
       
 17421             bodyScroll = doc.body && doc.body.scrollTop;
       
 17422             docScroll = doc.documentElement.scrollTop;
       
 17423 
       
 17424             val = e.clientY + (docScroll || bodyScroll || 0);
       
 17425         }
       
 17426 
       
 17427         return val;
       
 17428     }
       
 17429 };
       
 17430 
       
 17431 
       
 17432 /**
       
 17433  * Wrapper function for Object.defineProperty that creates a property whose
       
 17434  * value will be calulated only when asked for.  After calculating the value,
       
 17435  * the getter wll be removed, so it will behave as a normal property beyond that
       
 17436  * point.  A setter is also assigned so assigning to the property will clear
       
 17437  * the getter, so foo.prop = 'a'; foo.prop; won't trigger the getter,
       
 17438  * overwriting value 'a'.
       
 17439  *
       
 17440  * Used only by the DOMEventFacades used by IE8 when the YUI configuration
       
 17441  * <code>lazyEventFacade</code> is set to true.
       
 17442  *
       
 17443  * @method _define
       
 17444  * @param o {DOMObject} A DOM object to add the property to
       
 17445  * @param prop {String} The name of the new property
       
 17446  * @param valueFn {Function} The function that will return the initial, default
       
 17447  *                  value for the property.
       
 17448  * @static
       
 17449  * @private
       
 17450  */
       
 17451 IELazyFacade._define = function (o, prop, valueFn) {
       
 17452     function val(v) {
       
 17453         var ret = (arguments.length) ? v : valueFn.call(this);
       
 17454 
       
 17455         delete o[prop];
       
 17456         Object.defineProperty(o, prop, {
       
 17457             value: ret,
       
 17458             configurable: true,
       
 17459             writable: true
       
 17460         });
       
 17461         return ret;
       
 17462     }
       
 17463     Object.defineProperty(o, prop, {
       
 17464         get: val,
       
 17465         set: val,
       
 17466         configurable: true
       
 17467     });
       
 17468 };
       
 17469 
       
 17470 if (imp && (!imp.hasFeature('Events', '2.0'))) {
       
 17471     if (useLazyFacade) {
       
 17472         // Make sure we can use the lazy facade logic
       
 17473         try {
       
 17474             Object.defineProperty(Y.config.doc.createEventObject(), 'z', {});
       
 17475         } catch (e) {
       
 17476             useLazyFacade = false;
       
 17477         }
       
 17478     }
       
 17479 
       
 17480     Y.DOMEventFacade = (useLazyFacade) ? IELazyFacade : IEEventFacade;
       
 17481 }
       
 17482 
       
 17483 
       
 17484 }, '@VERSION@', {"requires": ["node-base"]});
       
 17485 YUI.add('pluginhost-base', function (Y, NAME) {
       
 17486 
       
 17487     /**
       
 17488      * Provides the augmentable PluginHost interface, which can be added to any class.
       
 17489      * @module pluginhost
       
 17490      */
       
 17491 
       
 17492     /**
       
 17493      * Provides the augmentable PluginHost interface, which can be added to any class.
       
 17494      * @module pluginhost-base
       
 17495      */
       
 17496 
       
 17497     /**
       
 17498      * <p>
       
 17499      * An augmentable class, which provides the augmented class with the ability to host plugins.
       
 17500      * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can 
       
 17501      * be used to add or remove plugins from instances of the class.
       
 17502      * </p>
       
 17503      *
       
 17504      * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using
       
 17505      * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method. 
       
 17506      * 
       
 17507      * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
       
 17508      * <xmp>
       
 17509      * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
       
 17510      * </xmp>
       
 17511      * </p>
       
 17512      * <p>
       
 17513      * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a> 
       
 17514      * methods should be invoked by the host class at the appropriate point in the host's lifecyle.  
       
 17515      * </p>
       
 17516      *
       
 17517      * @class Plugin.Host
       
 17518      */
       
 17519 
       
 17520     var L = Y.Lang;
       
 17521 
       
 17522     function PluginHost() {
       
 17523         this._plugins = {};
       
 17524     }
       
 17525 
       
 17526     PluginHost.prototype = {
       
 17527 
       
 17528         /**
       
 17529          * Adds a plugin to the host object. This will instantiate the 
       
 17530          * plugin and attach it to the configured namespace on the host object.
       
 17531          *
       
 17532          * @method plug
       
 17533          * @chainable
       
 17534          * @param P {Function | Object |Array} Accepts the plugin class, or an 
       
 17535          * object with a "fn" property specifying the plugin class and 
       
 17536          * a "cfg" property specifying the configuration for the Plugin.
       
 17537          * <p>
       
 17538          * Additionally an Array can also be passed in, with the above function or 
       
 17539          * object values, allowing the user to add multiple plugins in a single call.
       
 17540          * </p>
       
 17541          * @param config (Optional) If the first argument is the plugin class, the second argument
       
 17542          * can be the configuration for the plugin.
       
 17543          * @return {Base} A reference to the host object
       
 17544          */
       
 17545         plug: function(Plugin, config) {
       
 17546             var i, ln, ns;
       
 17547 
       
 17548             if (L.isArray(Plugin)) {
       
 17549                 for (i = 0, ln = Plugin.length; i < ln; i++) {
       
 17550                     this.plug(Plugin[i]);
       
 17551                 }
       
 17552             } else {
       
 17553                 if (Plugin && !L.isFunction(Plugin)) {
       
 17554                     config = Plugin.cfg;
       
 17555                     Plugin = Plugin.fn;
       
 17556                 }
       
 17557 
       
 17558                 // Plugin should be fn by now
       
 17559                 if (Plugin && Plugin.NS) {
       
 17560                     ns = Plugin.NS;
       
 17561         
       
 17562                     config = config || {};
       
 17563                     config.host = this;
       
 17564         
       
 17565                     if (this.hasPlugin(ns)) {
       
 17566                         // Update config
       
 17567                         if (this[ns].setAttrs) {
       
 17568                             this[ns].setAttrs(config);
       
 17569                         }
       
 17570                         else { Y.log("Attempt to replug an already attached plugin, and we can't setAttrs, because it's not Attribute based: " + ns); }
       
 17571                     } else {
       
 17572                         // Create new instance
       
 17573                         this[ns] = new Plugin(config);
       
 17574                         this._plugins[ns] = Plugin;
       
 17575                     }
       
 17576                 }
       
 17577                 else { Y.log("Attempt to plug in an invalid plugin. Host:" + this + ", Plugin:" + Plugin); }
       
 17578             }
       
 17579             return this;
       
 17580         },
       
 17581 
       
 17582         /**
       
 17583          * Removes a plugin from the host object. This will destroy the 
       
 17584          * plugin instance and delete the namespace from the host object. 
       
 17585          *
       
 17586          * @method unplug
       
 17587          * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
       
 17588          * all registered plugins are unplugged.
       
 17589          * @return {Base} A reference to the host object
       
 17590          * @chainable
       
 17591          */
       
 17592         unplug: function(plugin) {
       
 17593             var ns = plugin, 
       
 17594                 plugins = this._plugins;
       
 17595             
       
 17596             if (plugin) {
       
 17597                 if (L.isFunction(plugin)) {
       
 17598                     ns = plugin.NS;
       
 17599                     if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
       
 17600                         ns = null;
       
 17601                     }
       
 17602                 }
       
 17603         
       
 17604                 if (ns) {
       
 17605                     if (this[ns]) {
       
 17606                         if (this[ns].destroy) {
       
 17607                             this[ns].destroy();
       
 17608                         }
       
 17609                         delete this[ns];
       
 17610                     }
       
 17611                     if (plugins[ns]) {
       
 17612                         delete plugins[ns];
       
 17613                     }
       
 17614                 }
       
 17615             } else {
       
 17616                 for (ns in this._plugins) {
       
 17617                     if (this._plugins.hasOwnProperty(ns)) {
       
 17618                         this.unplug(ns);
       
 17619                     }
       
 17620                 }
       
 17621             }
       
 17622             return this;
       
 17623         },
       
 17624 
       
 17625         /**
       
 17626          * Determines if a plugin has plugged into this host.
       
 17627          *
       
 17628          * @method hasPlugin
       
 17629          * @param {String} ns The plugin's namespace
       
 17630          * @return {Plugin} Returns a truthy value (the plugin instance) if present, or undefined if not.
       
 17631          */
       
 17632         hasPlugin : function(ns) {
       
 17633             return (this._plugins[ns] && this[ns]);
       
 17634         },
       
 17635 
       
 17636         /**
       
 17637          * Initializes static plugins registered on the host (using the
       
 17638          * Base.plug static method) and any plugins passed to the 
       
 17639          * instance through the "plugins" configuration property.
       
 17640          *
       
 17641          * @method _initPlugins
       
 17642          * @param {Config} config The configuration object with property name/value pairs.
       
 17643          * @private
       
 17644          */
       
 17645         
       
 17646         _initPlugins: function(config) {
       
 17647             this._plugins = this._plugins || {};
       
 17648 
       
 17649             if (this._initConfigPlugins) {
       
 17650                 this._initConfigPlugins(config);
       
 17651             }
       
 17652         },
       
 17653 
       
 17654         /**
       
 17655          * Unplugs and destroys all plugins on the host
       
 17656          * @method _destroyPlugins
       
 17657          * @private
       
 17658          */
       
 17659         _destroyPlugins: function() {
       
 17660             this.unplug();
       
 17661         }
       
 17662     };
       
 17663 
       
 17664     Y.namespace("Plugin").Host = PluginHost;
       
 17665 
       
 17666 
       
 17667 }, '@VERSION@', {"requires": ["yui-base"]});
       
 17668 YUI.add('pluginhost-config', function (Y, NAME) {
       
 17669 
       
 17670     /**
       
 17671      * Adds pluginhost constructor configuration and static configuration support
       
 17672      * @submodule pluginhost-config
       
 17673      */
       
 17674 
       
 17675     var PluginHost = Y.Plugin.Host,
       
 17676         L = Y.Lang;
       
 17677 
       
 17678     /**
       
 17679      * A protected initialization method, used by the host class to initialize
       
 17680      * plugin configurations passed the constructor, through the config object.
       
 17681      * 
       
 17682      * Host objects should invoke this method at the appropriate time in their
       
 17683      * construction lifecycle.
       
 17684      * 
       
 17685      * @method _initConfigPlugins
       
 17686      * @param {Object} config The configuration object passed to the constructor
       
 17687      * @protected
       
 17688      * @for Plugin.Host
       
 17689      */
       
 17690     PluginHost.prototype._initConfigPlugins = function(config) {
       
 17691 
       
 17692         // Class Configuration
       
 17693         var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
       
 17694             plug = [],
       
 17695             unplug = {},
       
 17696             constructor, i, classPlug, classUnplug, pluginClassName;
       
 17697 
       
 17698         // TODO: Room for optimization. Can we apply statically/unplug in same pass?
       
 17699         for (i = classes.length - 1; i >= 0; i--) {
       
 17700             constructor = classes[i];
       
 17701 
       
 17702             classUnplug = constructor._UNPLUG;
       
 17703             if (classUnplug) {
       
 17704                 // subclasses over-write
       
 17705                 Y.mix(unplug, classUnplug, true);
       
 17706             }
       
 17707 
       
 17708             classPlug = constructor._PLUG;
       
 17709             if (classPlug) {
       
 17710                 // subclasses over-write
       
 17711                 Y.mix(plug, classPlug, true);
       
 17712             }
       
 17713         }
       
 17714 
       
 17715         for (pluginClassName in plug) {
       
 17716             if (plug.hasOwnProperty(pluginClassName)) {
       
 17717                 if (!unplug[pluginClassName]) {
       
 17718                     this.plug(plug[pluginClassName]);
       
 17719                 }
       
 17720             }
       
 17721         }
       
 17722 
       
 17723         // User Configuration
       
 17724         if (config && config.plugins) {
       
 17725             this.plug(config.plugins);
       
 17726         }
       
 17727     };
       
 17728     
       
 17729     /**
       
 17730      * Registers plugins to be instantiated at the class level (plugins 
       
 17731      * which should be plugged into every instance of the class by default).
       
 17732      *
       
 17733      * @method plug
       
 17734      * @static
       
 17735      *
       
 17736      * @param {Function} hostClass The host class on which to register the plugins
       
 17737      * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
       
 17738      * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
       
 17739      * @for Plugin.Host
       
 17740      */
       
 17741     PluginHost.plug = function(hostClass, plugin, config) {
       
 17742         // Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
       
 17743         var p, i, l, name;
       
 17744     
       
 17745         if (hostClass !== Y.Base) {
       
 17746             hostClass._PLUG = hostClass._PLUG || {};
       
 17747     
       
 17748             if (!L.isArray(plugin)) {
       
 17749                 if (config) {
       
 17750                     plugin = {fn:plugin, cfg:config};
       
 17751                 }
       
 17752                 plugin = [plugin];
       
 17753             }
       
 17754     
       
 17755             for (i = 0, l = plugin.length; i < l;i++) {
       
 17756                 p = plugin[i];
       
 17757                 name = p.NAME || p.fn.NAME;
       
 17758                 hostClass._PLUG[name] = p;
       
 17759             }
       
 17760         }
       
 17761     };
       
 17762 
       
 17763     /**
       
 17764      * Unregisters any class level plugins which have been registered by the host class, or any
       
 17765      * other class in the hierarchy.
       
 17766      *
       
 17767      * @method unplug
       
 17768      * @static
       
 17769      *
       
 17770      * @param {Function} hostClass The host class from which to unregister the plugins
       
 17771      * @param {Function | Array} plugin The plugin class, or an array of plugin classes
       
 17772      * @for Plugin.Host
       
 17773      */
       
 17774     PluginHost.unplug = function(hostClass, plugin) {
       
 17775         var p, i, l, name;
       
 17776     
       
 17777         if (hostClass !== Y.Base) {
       
 17778             hostClass._UNPLUG = hostClass._UNPLUG || {};
       
 17779     
       
 17780             if (!L.isArray(plugin)) {
       
 17781                 plugin = [plugin];
       
 17782             }
       
 17783     
       
 17784             for (i = 0, l = plugin.length; i < l; i++) {
       
 17785                 p = plugin[i];
       
 17786                 name = p.NAME;
       
 17787                 if (!hostClass._PLUG[name]) {
       
 17788                     hostClass._UNPLUG[name] = p;
       
 17789                 } else {
       
 17790                     delete hostClass._PLUG[name];
       
 17791                 }
       
 17792             }
       
 17793         }
       
 17794     };
       
 17795 
       
 17796 
       
 17797 }, '@VERSION@', {"requires": ["pluginhost-base"]});
       
 17798 YUI.add('event-delegate', function (Y, NAME) {
       
 17799 
       
 17800 /**
       
 17801  * Adds event delegation support to the library.
       
 17802  *
       
 17803  * @module event
       
 17804  * @submodule event-delegate
       
 17805  */
       
 17806 
       
 17807 var toArray          = Y.Array,
       
 17808     YLang            = Y.Lang,
       
 17809     isString         = YLang.isString,
       
 17810     isObject         = YLang.isObject,
       
 17811     isArray          = YLang.isArray,
       
 17812     selectorTest     = Y.Selector.test,
       
 17813     detachCategories = Y.Env.evt.handles;
       
 17814 
       
 17815 /**
       
 17816  * <p>Sets up event delegation on a container element.  The delegated event
       
 17817  * will use a supplied selector or filtering function to test if the event
       
 17818  * references at least one node that should trigger the subscription
       
 17819  * callback.</p>
       
 17820  *
       
 17821  * <p>Selector string filters will trigger the callback if the event originated
       
 17822  * from a node that matches it or is contained in a node that matches it.
       
 17823  * Function filters are called for each Node up the parent axis to the
       
 17824  * subscribing container node, and receive at each level the Node and the event
       
 17825  * object.  The function should return true (or a truthy value) if that Node
       
 17826  * should trigger the subscription callback.  Note, it is possible for filters
       
 17827  * to match multiple Nodes for a single event.  In this case, the delegate
       
 17828  * callback will be executed for each matching Node.</p>
       
 17829  *
       
 17830  * <p>For each matching Node, the callback will be executed with its 'this'
       
 17831  * object set to the Node matched by the filter (unless a specific context was
       
 17832  * provided during subscription), and the provided event's
       
 17833  * <code>currentTarget</code> will also be set to the matching Node.  The
       
 17834  * containing Node from which the subscription was originally made can be
       
 17835  * referenced as <code>e.container</code>.
       
 17836  *
       
 17837  * @method delegate
       
 17838  * @param type {String} the event type to delegate
       
 17839  * @param fn {Function} the callback function to execute.  This function
       
 17840  *              will be provided the event object for the delegated event.
       
 17841  * @param el {String|node} the element that is the delegation container
       
 17842  * @param filter {string|Function} a selector that must match the target of the
       
 17843  *              event or a function to test target and its parents for a match
       
 17844  * @param context optional argument that specifies what 'this' refers to.
       
 17845  * @param args* 0..n additional arguments to pass on to the callback function.
       
 17846  *              These arguments will be added after the event object.
       
 17847  * @return {EventHandle} the detach handle
       
 17848  * @static
       
 17849  * @for Event
       
 17850  */
       
 17851 function delegate(type, fn, el, filter) {
       
 17852     var args     = toArray(arguments, 0, true),
       
 17853         query    = isString(el) ? el : null,
       
 17854         typeBits, synth, container, categories, cat, i, len, handles, handle;
       
 17855 
       
 17856     // Support Y.delegate({ click: fnA, key: fnB }, el, filter, ...);
       
 17857     // and Y.delegate(['click', 'key'], fn, el, filter, ...);
       
 17858     if (isObject(type)) {
       
 17859         handles = [];
       
 17860 
       
 17861         if (isArray(type)) {
       
 17862             for (i = 0, len = type.length; i < len; ++i) {
       
 17863                 args[0] = type[i];
       
 17864                 handles.push(Y.delegate.apply(Y, args));
       
 17865             }
       
 17866         } else {
       
 17867             // Y.delegate({'click', fn}, el, filter) =>
       
 17868             // Y.delegate('click', fn, el, filter)
       
 17869             args.unshift(null); // one arg becomes two; need to make space
       
 17870 
       
 17871             for (i in type) {
       
 17872                 if (type.hasOwnProperty(i)) {
       
 17873                     args[0] = i;
       
 17874                     args[1] = type[i];
       
 17875                     handles.push(Y.delegate.apply(Y, args));
       
 17876                 }
       
 17877             }
       
 17878         }
       
 17879 
       
 17880         return new Y.EventHandle(handles);
       
 17881     }
       
 17882 
       
 17883     typeBits = type.split(/\|/);
       
 17884 
       
 17885     if (typeBits.length > 1) {
       
 17886         cat  = typeBits.shift();
       
 17887         args[0] = type = typeBits.shift();
       
 17888     }
       
 17889 
       
 17890     synth = Y.Node.DOM_EVENTS[type];
       
 17891 
       
 17892     if (isObject(synth) && synth.delegate) {
       
 17893         handle = synth.delegate.apply(synth, arguments);
       
 17894     }
       
 17895 
       
 17896     if (!handle) {
       
 17897         if (!type || !fn || !el || !filter) {
       
 17898             Y.log("delegate requires type, callback, parent, & filter", "warn");
       
 17899             return;
       
 17900         }
       
 17901 
       
 17902         container = (query) ? Y.Selector.query(query, null, true) : el;
       
 17903 
       
 17904         if (!container && isString(el)) {
       
 17905             handle = Y.on('available', function () {
       
 17906                 Y.mix(handle, Y.delegate.apply(Y, args), true);
       
 17907             }, el);
       
 17908         }
       
 17909 
       
 17910         if (!handle && container) {
       
 17911             args.splice(2, 2, container); // remove the filter
       
 17912 
       
 17913             handle = Y.Event._attach(args, { facade: false });
       
 17914             handle.sub.filter  = filter;
       
 17915             handle.sub._notify = delegate.notifySub;
       
 17916         }
       
 17917     }
       
 17918 
       
 17919     if (handle && cat) {
       
 17920         categories = detachCategories[cat]  || (detachCategories[cat] = {});
       
 17921         categories = categories[type] || (categories[type] = []);
       
 17922         categories.push(handle);
       
 17923     }
       
 17924 
       
 17925     return handle;
       
 17926 }
       
 17927 
       
 17928 /**
       
 17929 Overrides the <code>_notify</code> method on the normal DOM subscription to
       
 17930 inject the filtering logic and only proceed in the case of a match.
       
 17931 
       
 17932 This method is hosted as a private property of the `delegate` method
       
 17933 (e.g. `Y.delegate.notifySub`)
       
 17934 
       
 17935 @method notifySub
       
 17936 @param thisObj {Object} default 'this' object for the callback
       
 17937 @param args {Array} arguments passed to the event's <code>fire()</code>
       
 17938 @param ce {CustomEvent} the custom event managing the DOM subscriptions for
       
 17939              the subscribed event on the subscribing node.
       
 17940 @return {Boolean} false if the event was stopped
       
 17941 @private
       
 17942 @static
       
 17943 @since 3.2.0
       
 17944 **/
       
 17945 delegate.notifySub = function (thisObj, args, ce) {
       
 17946     // Preserve args for other subscribers
       
 17947     args = args.slice();
       
 17948     if (this.args) {
       
 17949         args.push.apply(args, this.args);
       
 17950     }
       
 17951 
       
 17952     // Only notify subs if the event occurred on a targeted element
       
 17953     var currentTarget = delegate._applyFilter(this.filter, args, ce),
       
 17954         //container     = e.currentTarget,
       
 17955         e, i, len, ret;
       
 17956 
       
 17957     if (currentTarget) {
       
 17958         // Support multiple matches up the the container subtree
       
 17959         currentTarget = toArray(currentTarget);
       
 17960 
       
 17961         // The second arg is the currentTarget, but we'll be reusing this
       
 17962         // facade, replacing the currentTarget for each use, so it doesn't
       
 17963         // matter what element we seed it with.
       
 17964         e = args[0] = new Y.DOMEventFacade(args[0], ce.el, ce);
       
 17965 
       
 17966         e.container = Y.one(ce.el);
       
 17967 
       
 17968         for (i = 0, len = currentTarget.length; i < len && !e.stopped; ++i) {
       
 17969             e.currentTarget = Y.one(currentTarget[i]);
       
 17970 
       
 17971             ret = this.fn.apply(this.context || e.currentTarget, args);
       
 17972 
       
 17973             if (ret === false) { // stop further notifications
       
 17974                 break;
       
 17975             }
       
 17976         }
       
 17977 
       
 17978         return ret;
       
 17979     }
       
 17980 };
       
 17981 
       
 17982 /**
       
 17983 Compiles a selector string into a filter function to identify whether
       
 17984 Nodes along the parent axis of an event's target should trigger event
       
 17985 notification.
       
 17986 
       
 17987 This function is memoized, so previously compiled filter functions are
       
 17988 returned if the same selector string is provided.
       
 17989 
       
 17990 This function may be useful when defining synthetic events for delegate
       
 17991 handling.
       
 17992 
       
 17993 Hosted as a property of the `delegate` method (e.g. `Y.delegate.compileFilter`).
       
 17994 
       
 17995 @method compileFilter
       
 17996 @param selector {String} the selector string to base the filtration on
       
 17997 @return {Function}
       
 17998 @since 3.2.0
       
 17999 @static
       
 18000 **/
       
 18001 delegate.compileFilter = Y.cached(function (selector) {
       
 18002     return function (target, e) {
       
 18003         return selectorTest(target._node, selector,
       
 18004             (e.currentTarget === e.target) ? null : e.currentTarget._node);
       
 18005     };
       
 18006 });
       
 18007 
       
 18008 /**
       
 18009 Regex to test for disabled elements during filtering. This is only relevant to
       
 18010 IE to normalize behavior with other browsers, which swallow events that occur
       
 18011 to disabled elements. IE fires the event from the parent element instead of the
       
 18012 original target, though it does preserve `event.srcElement` as the disabled
       
 18013 element. IE also supports disabled on `<a>`, but the event still bubbles, so it
       
 18014 acts more like `e.preventDefault()` plus styling. That issue is not handled here
       
 18015 because other browsers fire the event on the `<a>`, so delegate is supported in
       
 18016 both cases.
       
 18017 
       
 18018 @property _disabledRE
       
 18019 @type {RegExp}
       
 18020 @protected
       
 18021 @since 3.8.1
       
 18022 **/
       
 18023 delegate._disabledRE = /^(?:button|input|select|textarea)$/i;
       
 18024 
       
 18025 /**
       
 18026 Walks up the parent axis of an event's target, and tests each element
       
 18027 against a supplied filter function.  If any Nodes, including the container,
       
 18028 satisfy the filter, the delegated callback will be triggered for each.
       
 18029 
       
 18030 Hosted as a protected property of the `delegate` method (e.g.
       
 18031 `Y.delegate._applyFilter`).
       
 18032 
       
 18033 @method _applyFilter
       
 18034 @param filter {Function} boolean function to test for inclusion in event
       
 18035                  notification
       
 18036 @param args {Array} the arguments that would be passed to subscribers
       
 18037 @param ce   {CustomEvent} the DOM event wrapper
       
 18038 @return {Node|Node[]|undefined} The Node or Nodes that satisfy the filter
       
 18039 @protected
       
 18040 **/
       
 18041 delegate._applyFilter = function (filter, args, ce) {
       
 18042     var e         = args[0],
       
 18043         container = ce.el, // facadeless events in IE, have no e.currentTarget
       
 18044         target    = e.target || e.srcElement,
       
 18045         match     = [],
       
 18046         isContainer = false;
       
 18047 
       
 18048     // Resolve text nodes to their containing element
       
 18049     if (target.nodeType === 3) {
       
 18050         target = target.parentNode;
       
 18051     }
       
 18052 
       
 18053     // For IE. IE propagates events from the parent element of disabled
       
 18054     // elements, where other browsers swallow the event entirely. To normalize
       
 18055     // this in IE, filtering for matching elements should abort if the target
       
 18056     // is a disabled form control.
       
 18057     if (target.disabled && delegate._disabledRE.test(target.nodeName)) {
       
 18058         return match;
       
 18059     }
       
 18060 
       
 18061     // passing target as the first arg rather than leaving well enough alone
       
 18062     // making 'this' in the filter function refer to the target.  This is to
       
 18063     // support bound filter functions.
       
 18064     args.unshift(target);
       
 18065 
       
 18066     if (isString(filter)) {
       
 18067         while (target) {
       
 18068             isContainer = (target === container);
       
 18069             if (selectorTest(target, filter, (isContainer ? null: container))) {
       
 18070                 match.push(target);
       
 18071             }
       
 18072 
       
 18073             if (isContainer) {
       
 18074                 break;
       
 18075             }
       
 18076 
       
 18077             target = target.parentNode;
       
 18078         }
       
 18079     } else {
       
 18080         // filter functions are implementer code and should receive wrappers
       
 18081         args[0] = Y.one(target);
       
 18082         args[1] = new Y.DOMEventFacade(e, container, ce);
       
 18083 
       
 18084         while (target) {
       
 18085             // filter(target, e, extra args...) - this === target
       
 18086             if (filter.apply(args[0], args)) {
       
 18087                 match.push(target);
       
 18088             }
       
 18089 
       
 18090             if (target === container) {
       
 18091                 break;
       
 18092             }
       
 18093 
       
 18094             target = target.parentNode;
       
 18095             args[0] = Y.one(target);
       
 18096         }
       
 18097         args[1] = e; // restore the raw DOM event
       
 18098     }
       
 18099 
       
 18100     if (match.length <= 1) {
       
 18101         match = match[0]; // single match or undefined
       
 18102     }
       
 18103 
       
 18104     // remove the target
       
 18105     args.shift();
       
 18106 
       
 18107     return match;
       
 18108 };
       
 18109 
       
 18110 /**
       
 18111  * Sets up event delegation on a container element.  The delegated event
       
 18112  * will use a supplied filter to test if the callback should be executed.
       
 18113  * This filter can be either a selector string or a function that returns
       
 18114  * a Node to use as the currentTarget for the event.
       
 18115  *
       
 18116  * The event object for the delegated event is supplied to the callback
       
 18117  * function.  It is modified slightly in order to support all properties
       
 18118  * that may be needed for event delegation.  'currentTarget' is set to
       
 18119  * the element that matched the selector string filter or the Node returned
       
 18120  * from the filter function.  'container' is set to the element that the
       
 18121  * listener is delegated from (this normally would be the 'currentTarget').
       
 18122  *
       
 18123  * Filter functions will be called with the arguments that would be passed to
       
 18124  * the callback function, including the event object as the first parameter.
       
 18125  * The function should return false (or a falsey value) if the success criteria
       
 18126  * aren't met, and the Node to use as the event's currentTarget and 'this'
       
 18127  * object if they are.
       
 18128  *
       
 18129  * @method delegate
       
 18130  * @param type {string} the event type to delegate
       
 18131  * @param fn {function} the callback function to execute.  This function
       
 18132  * will be provided the event object for the delegated event.
       
 18133  * @param el {string|node} the element that is the delegation container
       
 18134  * @param filter {string|function} a selector that must match the target of the
       
 18135  * event or a function that returns a Node or false.
       
 18136  * @param context optional argument that specifies what 'this' refers to.
       
 18137  * @param args* 0..n additional arguments to pass on to the callback function.
       
 18138  * These arguments will be added after the event object.
       
 18139  * @return {EventHandle} the detach handle
       
 18140  * @for YUI
       
 18141  */
       
 18142 Y.delegate = Y.Event.delegate = delegate;
       
 18143 
       
 18144 
       
 18145 }, '@VERSION@', {"requires": ["node-base"]});
       
 18146 YUI.add('node-event-delegate', function (Y, NAME) {
       
 18147 
       
 18148 /**
       
 18149  * Functionality to make the node a delegated event container
       
 18150  * @module node
       
 18151  * @submodule node-event-delegate
       
 18152  */
       
 18153 
       
 18154 /**
       
 18155  * <p>Sets up a delegation listener for an event occurring inside the Node.
       
 18156  * The delegated event will be verified against a supplied selector or
       
 18157  * filtering function to test if the event references at least one node that
       
 18158  * should trigger the subscription callback.</p>
       
 18159  *
       
 18160  * <p>Selector string filters will trigger the callback if the event originated
       
 18161  * from a node that matches it or is contained in a node that matches it.
       
 18162  * Function filters are called for each Node up the parent axis to the
       
 18163  * subscribing container node, and receive at each level the Node and the event
       
 18164  * object.  The function should return true (or a truthy value) if that Node
       
 18165  * should trigger the subscription callback.  Note, it is possible for filters
       
 18166  * to match multiple Nodes for a single event.  In this case, the delegate
       
 18167  * callback will be executed for each matching Node.</p>
       
 18168  *
       
 18169  * <p>For each matching Node, the callback will be executed with its 'this'
       
 18170  * object set to the Node matched by the filter (unless a specific context was
       
 18171  * provided during subscription), and the provided event's
       
 18172  * <code>currentTarget</code> will also be set to the matching Node.  The
       
 18173  * containing Node from which the subscription was originally made can be
       
 18174  * referenced as <code>e.container</code>.
       
 18175  *
       
 18176  * @method delegate
       
 18177  * @param type {String} the event type to delegate
       
 18178  * @param fn {Function} the callback function to execute.  This function
       
 18179  *              will be provided the event object for the delegated event.
       
 18180  * @param spec {String|Function} a selector that must match the target of the
       
 18181  *              event or a function to test target and its parents for a match
       
 18182  * @param context {Object} optional argument that specifies what 'this' refers to.
       
 18183  * @param args* {any} 0..n additional arguments to pass on to the callback function.
       
 18184  *              These arguments will be added after the event object.
       
 18185  * @return {EventHandle} the detach handle
       
 18186  * @for Node
       
 18187  */
       
 18188 Y.Node.prototype.delegate = function(type) {
       
 18189 
       
 18190     var args = Y.Array(arguments, 0, true),
       
 18191         index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2;
       
 18192 
       
 18193     args.splice(index, 0, this._node);
       
 18194 
       
 18195     return Y.delegate.apply(Y, args);
       
 18196 };
       
 18197 
       
 18198 
       
 18199 }, '@VERSION@', {"requires": ["node-base", "event-delegate"]});
       
 18200 YUI.add('node-pluginhost', function (Y, NAME) {
       
 18201 
       
 18202 /**
       
 18203  * @module node
       
 18204  * @submodule node-pluginhost
       
 18205  */
       
 18206 
       
 18207 /**
       
 18208  * Registers plugins to be instantiated at the class level (plugins
       
 18209  * which should be plugged into every instance of Node by default).
       
 18210  *
       
 18211  * @method plug
       
 18212  * @static
       
 18213  * @for Node
       
 18214  * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
       
 18215  * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
       
 18216  */
       
 18217 Y.Node.plug = function() {
       
 18218     var args = Y.Array(arguments);
       
 18219     args.unshift(Y.Node);
       
 18220     Y.Plugin.Host.plug.apply(Y.Base, args);
       
 18221     return Y.Node;
       
 18222 };
       
 18223 
       
 18224 /**
       
 18225  * Unregisters any class level plugins which have been registered by the Node
       
 18226  *
       
 18227  * @method unplug
       
 18228  * @static
       
 18229  *
       
 18230  * @param {Function | Array} plugin The plugin class, or an array of plugin classes
       
 18231  */
       
 18232 Y.Node.unplug = function() {
       
 18233     var args = Y.Array(arguments);
       
 18234     args.unshift(Y.Node);
       
 18235     Y.Plugin.Host.unplug.apply(Y.Base, args);
       
 18236     return Y.Node;
       
 18237 };
       
 18238 
       
 18239 Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
       
 18240 
       
 18241 // allow batching of plug/unplug via NodeList
       
 18242 // doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
       
 18243 /**
       
 18244  * Adds a plugin to each node in the NodeList.
       
 18245  * This will instantiate the plugin and attach it to the configured namespace on each node
       
 18246  * @method plug
       
 18247  * @for NodeList
       
 18248  * @param P {Function | Object |Array} Accepts the plugin class, or an 
       
 18249  * object with a "fn" property specifying the plugin class and 
       
 18250  * a "cfg" property specifying the configuration for the Plugin.
       
 18251  * <p>
       
 18252  * Additionally an Array can also be passed in, with the above function or 
       
 18253  * object values, allowing the user to add multiple plugins in a single call.
       
 18254  * </p>
       
 18255  * @param config (Optional) If the first argument is the plugin class, the second argument
       
 18256  * can be the configuration for the plugin.
       
 18257  * @chainable
       
 18258  */
       
 18259 Y.NodeList.prototype.plug = function() {
       
 18260     var args = arguments;
       
 18261     Y.NodeList.each(this, function(node) {
       
 18262         Y.Node.prototype.plug.apply(Y.one(node), args);
       
 18263     });
       
 18264     return this;
       
 18265 };
       
 18266 
       
 18267 /**
       
 18268  * Removes a plugin from all nodes in the NodeList. This will destroy the 
       
 18269  * plugin instance and delete the namespace each node. 
       
 18270  * @method unplug
       
 18271  * @for NodeList
       
 18272  * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
       
 18273  * all registered plugins are unplugged.
       
 18274  * @chainable
       
 18275  */
       
 18276 Y.NodeList.prototype.unplug = function() {
       
 18277     var args = arguments;
       
 18278     Y.NodeList.each(this, function(node) {
       
 18279         Y.Node.prototype.unplug.apply(Y.one(node), args);
       
 18280     });
       
 18281     return this;
       
 18282 };
       
 18283 
       
 18284 
       
 18285 }, '@VERSION@', {"requires": ["node-base", "pluginhost"]});
       
 18286 YUI.add('node-screen', function (Y, NAME) {
       
 18287 
       
 18288 /**
       
 18289  * Extended Node interface for managing regions and screen positioning.
       
 18290  * Adds support for positioning elements and normalizes window size and scroll detection. 
       
 18291  * @module node
       
 18292  * @submodule node-screen
       
 18293  */
       
 18294 
       
 18295 // these are all "safe" returns, no wrapping required
       
 18296 Y.each([
       
 18297     /**
       
 18298      * Returns the inner width of the viewport (exludes scrollbar). 
       
 18299      * @config winWidth
       
 18300      * @for Node
       
 18301      * @type {Int}
       
 18302      */
       
 18303     'winWidth',
       
 18304 
       
 18305     /**
       
 18306      * Returns the inner height of the viewport (exludes scrollbar). 
       
 18307      * @config winHeight
       
 18308      * @type {Int}
       
 18309      */
       
 18310     'winHeight',
       
 18311 
       
 18312     /**
       
 18313      * Document width 
       
 18314      * @config docWidth
       
 18315      * @type {Int}
       
 18316      */
       
 18317     'docWidth',
       
 18318 
       
 18319     /**
       
 18320      * Document height 
       
 18321      * @config docHeight
       
 18322      * @type {Int}
       
 18323      */
       
 18324     'docHeight',
       
 18325 
       
 18326     /**
       
 18327      * Pixel distance the page has been scrolled horizontally 
       
 18328      * @config docScrollX
       
 18329      * @type {Int}
       
 18330      */
       
 18331     'docScrollX',
       
 18332 
       
 18333     /**
       
 18334      * Pixel distance the page has been scrolled vertically 
       
 18335      * @config docScrollY
       
 18336      * @type {Int}
       
 18337      */
       
 18338     'docScrollY'
       
 18339     ],
       
 18340     function(name) {
       
 18341         Y.Node.ATTRS[name] = {
       
 18342             getter: function() {
       
 18343                 var args = Array.prototype.slice.call(arguments);
       
 18344                 args.unshift(Y.Node.getDOMNode(this));
       
 18345 
       
 18346                 return Y.DOM[name].apply(this, args);
       
 18347             }
       
 18348         };
       
 18349     }
       
 18350 );
       
 18351 
       
 18352 Y.Node.ATTRS.scrollLeft = {
       
 18353     getter: function() {
       
 18354         var node = Y.Node.getDOMNode(this);
       
 18355         return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
       
 18356     },
       
 18357 
       
 18358     setter: function(val) {
       
 18359         var node = Y.Node.getDOMNode(this);
       
 18360         if (node) {
       
 18361             if ('scrollLeft' in node) {
       
 18362                 node.scrollLeft = val;
       
 18363             } else if (node.document || node.nodeType === 9) {
       
 18364                 Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
       
 18365             }
       
 18366         } else {
       
 18367             Y.log('unable to set scrollLeft for ' + node, 'error', 'Node');
       
 18368         }
       
 18369     }
       
 18370 };
       
 18371 
       
 18372 Y.Node.ATTRS.scrollTop = {
       
 18373     getter: function() {
       
 18374         var node = Y.Node.getDOMNode(this);
       
 18375         return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
       
 18376     },
       
 18377 
       
 18378     setter: function(val) {
       
 18379         var node = Y.Node.getDOMNode(this);
       
 18380         if (node) {
       
 18381             if ('scrollTop' in node) {
       
 18382                 node.scrollTop = val;
       
 18383             } else if (node.document || node.nodeType === 9) {
       
 18384                 Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
       
 18385             }
       
 18386         } else {
       
 18387             Y.log('unable to set scrollTop for ' + node, 'error', 'Node');
       
 18388         }
       
 18389     }
       
 18390 };
       
 18391 
       
 18392 Y.Node.importMethod(Y.DOM, [
       
 18393 /**
       
 18394  * Gets the current position of the node in page coordinates. 
       
 18395  * @method getXY
       
 18396  * @for Node
       
 18397  * @return {Array} The XY position of the node
       
 18398 */
       
 18399     'getXY',
       
 18400 
       
 18401 /**
       
 18402  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
 18403  * @method setXY
       
 18404  * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
       
 18405  * @chainable
       
 18406  */
       
 18407     'setXY',
       
 18408 
       
 18409 /**
       
 18410  * Gets the current position of the node in page coordinates. 
       
 18411  * @method getX
       
 18412  * @return {Int} The X position of the node
       
 18413 */
       
 18414     'getX',
       
 18415 
       
 18416 /**
       
 18417  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
 18418  * @method setX
       
 18419  * @param {Int} x X value for new position (coordinates are page-based)
       
 18420  * @chainable
       
 18421  */
       
 18422     'setX',
       
 18423 
       
 18424 /**
       
 18425  * Gets the current position of the node in page coordinates. 
       
 18426  * @method getY
       
 18427  * @return {Int} The Y position of the node
       
 18428 */
       
 18429     'getY',
       
 18430 
       
 18431 /**
       
 18432  * Set the position of the node in page coordinates, regardless of how the node is positioned.
       
 18433  * @method setY
       
 18434  * @param {Int} y Y value for new position (coordinates are page-based)
       
 18435  * @chainable
       
 18436  */
       
 18437     'setY',
       
 18438 
       
 18439 /**
       
 18440  * Swaps the XY position of this node with another node. 
       
 18441  * @method swapXY
       
 18442  * @param {Node | HTMLElement} otherNode The node to swap with.
       
 18443  * @chainable
       
 18444  */
       
 18445     'swapXY'
       
 18446 ]);
       
 18447 
       
 18448 /**
       
 18449  * @module node
       
 18450  * @submodule node-screen
       
 18451  */
       
 18452 
       
 18453 /**
       
 18454  * Returns a region object for the node
       
 18455  * @config region
       
 18456  * @for Node
       
 18457  * @type Node
       
 18458  */
       
 18459 Y.Node.ATTRS.region = {
       
 18460     getter: function() {
       
 18461         var node = this.getDOMNode(),
       
 18462             region;
       
 18463 
       
 18464         if (node && !node.tagName) {
       
 18465             if (node.nodeType === 9) { // document
       
 18466                 node = node.documentElement;
       
 18467             }
       
 18468         }
       
 18469         if (Y.DOM.isWindow(node)) {
       
 18470             region = Y.DOM.viewportRegion(node);
       
 18471         } else {
       
 18472             region = Y.DOM.region(node);
       
 18473         }
       
 18474         return region;
       
 18475     }
       
 18476 };
       
 18477 
       
 18478 /**
       
 18479  * Returns a region object for the node's viewport
       
 18480  * @config viewportRegion
       
 18481  * @type Node
       
 18482  */
       
 18483 Y.Node.ATTRS.viewportRegion = {
       
 18484     getter: function() {
       
 18485         return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
       
 18486     }
       
 18487 };
       
 18488 
       
 18489 Y.Node.importMethod(Y.DOM, 'inViewportRegion');
       
 18490 
       
 18491 // these need special treatment to extract 2nd node arg
       
 18492 /**
       
 18493  * Compares the intersection of the node with another node or region
       
 18494  * @method intersect
       
 18495  * @for Node
       
 18496  * @param {Node|Object} node2 The node or region to compare with.
       
 18497  * @param {Object} altRegion An alternate region to use (rather than this node's).
       
 18498  * @return {Object} An object representing the intersection of the regions.
       
 18499  */
       
 18500 Y.Node.prototype.intersect = function(node2, altRegion) {
       
 18501     var node1 = Y.Node.getDOMNode(this);
       
 18502     if (Y.instanceOf(node2, Y.Node)) { // might be a region object
       
 18503         node2 = Y.Node.getDOMNode(node2);
       
 18504     }
       
 18505     return Y.DOM.intersect(node1, node2, altRegion);
       
 18506 };
       
 18507 
       
 18508 /**
       
 18509  * Determines whether or not the node is within the giving region.
       
 18510  * @method inRegion
       
 18511  * @param {Node|Object} node2 The node or region to compare with.
       
 18512  * @param {Boolean} all Whether or not all of the node must be in the region.
       
 18513  * @param {Object} altRegion An alternate region to use (rather than this node's).
       
 18514  * @return {Boolean} True if in region, false if not.
       
 18515  */
       
 18516 Y.Node.prototype.inRegion = function(node2, all, altRegion) {
       
 18517     var node1 = Y.Node.getDOMNode(this);
       
 18518     if (Y.instanceOf(node2, Y.Node)) { // might be a region object
       
 18519         node2 = Y.Node.getDOMNode(node2);
       
 18520     }
       
 18521     return Y.DOM.inRegion(node1, node2, all, altRegion);
       
 18522 };
       
 18523 
       
 18524 
       
 18525 }, '@VERSION@', {"requires": ["dom-screen", "node-base"]});
       
 18526 YUI.add('node-style', function (Y, NAME) {
       
 18527 
       
 18528 (function(Y) {
       
 18529 /**
       
 18530  * Extended Node interface for managing node styles.
       
 18531  * @module node
       
 18532  * @submodule node-style
       
 18533  */
       
 18534 
       
 18535 Y.mix(Y.Node.prototype, {
       
 18536     /**
       
 18537      * Sets a style property of the node.
       
 18538      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18539      * @method setStyle
       
 18540      * @param {String} attr The style attribute to set. 
       
 18541      * @param {String|Number} val The value. 
       
 18542      * @chainable
       
 18543      */
       
 18544     setStyle: function(attr, val) {
       
 18545         Y.DOM.setStyle(this._node, attr, val);
       
 18546         return this;
       
 18547     },
       
 18548 
       
 18549     /**
       
 18550      * Sets multiple style properties on the node.
       
 18551      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18552      * @method setStyles
       
 18553      * @param {Object} hash An object literal of property:value pairs. 
       
 18554      * @chainable
       
 18555      */
       
 18556     setStyles: function(hash) {
       
 18557         Y.DOM.setStyles(this._node, hash);
       
 18558         return this;
       
 18559     },
       
 18560 
       
 18561     /**
       
 18562      * Returns the style's current value.
       
 18563      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18564      * @method getStyle
       
 18565      * @for Node
       
 18566      * @param {String} attr The style attribute to retrieve. 
       
 18567      * @return {String} The current value of the style property for the element.
       
 18568      */
       
 18569 
       
 18570      getStyle: function(attr) {
       
 18571         return Y.DOM.getStyle(this._node, attr);
       
 18572      },
       
 18573 
       
 18574     /**
       
 18575      * Returns the computed value for the given style property.
       
 18576      * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18577      * @method getComputedStyle
       
 18578      * @param {String} attr The style attribute to retrieve. 
       
 18579      * @return {String} The computed value of the style property for the element.
       
 18580      */
       
 18581      getComputedStyle: function(attr) {
       
 18582         return Y.DOM.getComputedStyle(this._node, attr);
       
 18583      }
       
 18584 });
       
 18585 
       
 18586 /**
       
 18587  * Returns an array of values for each node.
       
 18588  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18589  * @method getStyle
       
 18590  * @for NodeList
       
 18591  * @see Node.getStyle
       
 18592  * @param {String} attr The style attribute to retrieve. 
       
 18593  * @return {Array} The current values of the style property for the element.
       
 18594  */
       
 18595 
       
 18596 /**
       
 18597  * Returns an array of the computed value for each node.
       
 18598  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18599  * @method getComputedStyle
       
 18600  * @see Node.getComputedStyle
       
 18601  * @param {String} attr The style attribute to retrieve. 
       
 18602  * @return {Array} The computed values for each node.
       
 18603  */
       
 18604 
       
 18605 /**
       
 18606  * Sets a style property on each node.
       
 18607  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18608  * @method setStyle
       
 18609  * @see Node.setStyle
       
 18610  * @param {String} attr The style attribute to set. 
       
 18611  * @param {String|Number} val The value. 
       
 18612  * @chainable
       
 18613  */
       
 18614 
       
 18615 /**
       
 18616  * Sets multiple style properties on each node.
       
 18617  * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
       
 18618  * @method setStyles
       
 18619  * @see Node.setStyles
       
 18620  * @param {Object} hash An object literal of property:value pairs. 
       
 18621  * @chainable
       
 18622  */
       
 18623 
       
 18624 // These are broken out to handle undefined return (avoid false positive for
       
 18625 // chainable)
       
 18626 
       
 18627 Y.NodeList.importMethod(Y.Node.prototype, ['getStyle', 'getComputedStyle', 'setStyle', 'setStyles']);
       
 18628 })(Y);
       
 18629 
       
 18630 
       
 18631 }, '@VERSION@', {"requires": ["dom-style", "node-base"]});
       
 18632 YUI.add('querystring-stringify-simple', function (Y, NAME) {
       
 18633 
       
 18634 /*global Y */
       
 18635 /**
       
 18636  * <p>Provides Y.QueryString.stringify method for converting objects to Query Strings.
       
 18637  * This is a subset implementation of the full querystring-stringify.</p>
       
 18638  * <p>This module provides the bare minimum functionality (encoding a hash of simple values),
       
 18639  * without the additional support for nested data structures.  Every key-value pair is
       
 18640  * encoded by encodeURIComponent.</p>
       
 18641  * <p>This module provides a minimalistic way for io to handle  single-level objects
       
 18642  * as transaction data.</p>
       
 18643  *
       
 18644  * @module querystring
       
 18645  * @submodule querystring-stringify-simple
       
 18646  */
       
 18647 
       
 18648 var QueryString = Y.namespace("QueryString"),
       
 18649     EUC = encodeURIComponent;
       
 18650 
       
 18651 
       
 18652 QueryString.stringify = function (obj, c) {
       
 18653     var qs = [],
       
 18654         // Default behavior is false; standard key notation.
       
 18655         s = c && c.arrayKey ? true : false,
       
 18656         key, i, l;
       
 18657 
       
 18658     for (key in obj) {
       
 18659         if (obj.hasOwnProperty(key)) {
       
 18660             if (Y.Lang.isArray(obj[key])) {
       
 18661                 for (i = 0, l = obj[key].length; i < l; i++) {
       
 18662                     qs.push(EUC(s ? key + '[]' : key) + '=' + EUC(obj[key][i]));
       
 18663                 }
       
 18664             }
       
 18665             else {
       
 18666                 qs.push(EUC(key) + '=' + EUC(obj[key]));
       
 18667             }
       
 18668         }
       
 18669     }
       
 18670 
       
 18671     return qs.join('&');
       
 18672 };
       
 18673 
       
 18674 
       
 18675 }, '@VERSION@', {"requires": ["yui-base"]});
       
 18676 YUI.add('io-base', function (Y, NAME) {
       
 18677 
       
 18678 /**
       
 18679 Base IO functionality. Provides basic XHR transport support.
       
 18680 
       
 18681 @module io
       
 18682 @submodule io-base
       
 18683 @for IO
       
 18684 **/
       
 18685 
       
 18686 var // List of events that comprise the IO event lifecycle.
       
 18687     EVENTS = ['start', 'complete', 'end', 'success', 'failure', 'progress'],
       
 18688 
       
 18689     // Whitelist of used XHR response object properties.
       
 18690     XHR_PROPS = ['status', 'statusText', 'responseText', 'responseXML'],
       
 18691 
       
 18692     win = Y.config.win,
       
 18693     uid = 0;
       
 18694 
       
 18695 /**
       
 18696 The IO class is a utility that brokers HTTP requests through a simplified
       
 18697 interface.  Specifically, it allows JavaScript to make HTTP requests to
       
 18698 a resource without a page reload.  The underlying transport for making
       
 18699 same-domain requests is the XMLHttpRequest object.  IO can also use
       
 18700 Flash, if specified as a transport, for cross-domain requests.
       
 18701 
       
 18702 @class IO
       
 18703 @constructor
       
 18704 @param {Object} config Object of EventTarget's publish method configurations
       
 18705                     used to configure IO's events.
       
 18706 **/
       
 18707 function IO (config) {
       
 18708     var io = this;
       
 18709 
       
 18710     io._uid = 'io:' + uid++;
       
 18711     io._init(config);
       
 18712     Y.io._map[io._uid] = io;
       
 18713 }
       
 18714 
       
 18715 IO.prototype = {
       
 18716     //--------------------------------------
       
 18717     //  Properties
       
 18718     //--------------------------------------
       
 18719 
       
 18720    /**
       
 18721     * A counter that increments for each transaction.
       
 18722     *
       
 18723     * @property _id
       
 18724     * @private
       
 18725     * @type {Number}
       
 18726     */
       
 18727     _id: 0,
       
 18728 
       
 18729    /**
       
 18730     * Object of IO HTTP headers sent with each transaction.
       
 18731     *
       
 18732     * @property _headers
       
 18733     * @private
       
 18734     * @type {Object}
       
 18735     */
       
 18736     _headers: {
       
 18737         'X-Requested-With' : 'XMLHttpRequest'
       
 18738     },
       
 18739 
       
 18740    /**
       
 18741     * Object that stores timeout values for any transaction with a defined
       
 18742     * "timeout" configuration property.
       
 18743     *
       
 18744     * @property _timeout
       
 18745     * @private
       
 18746     * @type {Object}
       
 18747     */
       
 18748     _timeout: {},
       
 18749 
       
 18750     //--------------------------------------
       
 18751     //  Methods
       
 18752     //--------------------------------------
       
 18753 
       
 18754     _init: function(config) {
       
 18755         var io = this, i, len;
       
 18756 
       
 18757         io.cfg = config || {};
       
 18758 
       
 18759         Y.augment(io, Y.EventTarget);
       
 18760         for (i = 0, len = EVENTS.length; i < len; ++i) {
       
 18761             // Publish IO global events with configurations, if any.
       
 18762             // IO global events are set to broadcast by default.
       
 18763             // These events use the "io:" namespace.
       
 18764             io.publish('io:' + EVENTS[i], Y.merge({ broadcast: 1 }, config));
       
 18765             // Publish IO transaction events with configurations, if
       
 18766             // any.  These events use the "io-trn:" namespace.
       
 18767             io.publish('io-trn:' + EVENTS[i], config);
       
 18768         }
       
 18769     },
       
 18770 
       
 18771    /**
       
 18772     * Method that creates a unique transaction object for each request.
       
 18773     *
       
 18774     * @method _create
       
 18775     * @private
       
 18776     * @param {Object} cfg Configuration object subset to determine if
       
 18777     *                 the transaction is an XDR or file upload,
       
 18778     *                 requiring an alternate transport.
       
 18779     * @param {Number} id Transaction id
       
 18780     * @return {Object} The transaction object
       
 18781     */
       
 18782     _create: function(config, id) {
       
 18783         var io = this,
       
 18784             transaction = {
       
 18785                 id : Y.Lang.isNumber(id) ? id : io._id++,
       
 18786                 uid: io._uid
       
 18787             },
       
 18788             alt = config.xdr ? config.xdr.use : null,
       
 18789             form = config.form && config.form.upload ? 'iframe' : null,
       
 18790             use;
       
 18791 
       
 18792         if (alt === 'native') {
       
 18793             // Non-IE and IE >= 10  can use XHR level 2 and not rely on an
       
 18794             // external transport.
       
 18795             alt = Y.UA.ie && !SUPPORTS_CORS ? 'xdr' : null;
       
 18796 
       
 18797             // Prevent "pre-flight" OPTIONS request by removing the
       
 18798             // `X-Requested-With` HTTP header from CORS requests. This header
       
 18799             // can be added back on a per-request basis, if desired.
       
 18800             io.setHeader('X-Requested-With');
       
 18801         }
       
 18802 
       
 18803         use = alt || form;
       
 18804         transaction = use ? Y.merge(Y.IO.customTransport(use), transaction) :
       
 18805                             Y.merge(Y.IO.defaultTransport(), transaction);
       
 18806 
       
 18807         if (transaction.notify) {
       
 18808             config.notify = function (e, t, c) { io.notify(e, t, c); };
       
 18809         }
       
 18810 
       
 18811         if (!use) {
       
 18812             if (win && win.FormData && config.data instanceof win.FormData) {
       
 18813                 transaction.c.upload.onprogress = function (e) {
       
 18814                     io.progress(transaction, e, config);
       
 18815                 };
       
 18816                 transaction.c.onload = function (e) {
       
 18817                     io.load(transaction, e, config);
       
 18818                 };
       
 18819                 transaction.c.onerror = function (e) {
       
 18820                     io.error(transaction, e, config);
       
 18821                 };
       
 18822                 transaction.upload = true;
       
 18823             }
       
 18824         }
       
 18825 
       
 18826         return transaction;
       
 18827     },
       
 18828 
       
 18829     _destroy: function(transaction) {
       
 18830         if (win && !transaction.notify && !transaction.xdr) {
       
 18831             if (XHR && !transaction.upload) {
       
 18832                 transaction.c.onreadystatechange = null;
       
 18833             } else if (transaction.upload) {
       
 18834                 transaction.c.upload.onprogress = null;
       
 18835                 transaction.c.onload = null;
       
 18836                 transaction.c.onerror = null;
       
 18837             } else if (Y.UA.ie && !transaction.e) {
       
 18838                 // IE, when using XMLHttpRequest as an ActiveX Object, will throw
       
 18839                 // a "Type Mismatch" error if the event handler is set to "null".
       
 18840                 transaction.c.abort();
       
 18841             }
       
 18842         }
       
 18843 
       
 18844         transaction = transaction.c = null;
       
 18845     },
       
 18846 
       
 18847    /**
       
 18848     * Method for creating and firing events.
       
 18849     *
       
 18850     * @method _evt
       
 18851     * @private
       
 18852     * @param {String} eventName Event to be published.
       
 18853     * @param {Object} transaction Transaction object.
       
 18854     * @param {Object} config Configuration data subset for event subscription.
       
 18855     */
       
 18856     _evt: function(eventName, transaction, config) {
       
 18857         var io          = this, params,
       
 18858             args        = config['arguments'],
       
 18859             emitFacade  = io.cfg.emitFacade,
       
 18860             globalEvent = "io:" + eventName,
       
 18861             trnEvent    = "io-trn:" + eventName;
       
 18862 
       
 18863         // Workaround for #2532107
       
 18864         this.detach(trnEvent);
       
 18865 
       
 18866         if (transaction.e) {
       
 18867             transaction.c = { status: 0, statusText: transaction.e };
       
 18868         }
       
 18869 
       
 18870         // Fire event with parameters or an Event Facade.
       
 18871         params = [ emitFacade ?
       
 18872             {
       
 18873                 id: transaction.id,
       
 18874                 data: transaction.c,
       
 18875                 cfg: config,
       
 18876                 'arguments': args
       
 18877             } :
       
 18878             transaction.id
       
 18879         ];
       
 18880 
       
 18881         if (!emitFacade) {
       
 18882             if (eventName === EVENTS[0] || eventName === EVENTS[2]) {
       
 18883                 if (args) {
       
 18884                     params.push(args);
       
 18885                 }
       
 18886             } else {
       
 18887                 if (transaction.evt) {
       
 18888                     params.push(transaction.evt);
       
 18889                 } else {
       
 18890                     params.push(transaction.c);
       
 18891                 }
       
 18892                 if (args) {
       
 18893                     params.push(args);
       
 18894                 }
       
 18895             }
       
 18896         }
       
 18897 
       
 18898         params.unshift(globalEvent);
       
 18899         // Fire global events.
       
 18900         io.fire.apply(io, params);
       
 18901         // Fire transaction events, if receivers are defined.
       
 18902         if (config.on) {
       
 18903             params[0] = trnEvent;
       
 18904             io.once(trnEvent, config.on[eventName], config.context || Y);
       
 18905             io.fire.apply(io, params);
       
 18906         }
       
 18907     },
       
 18908 
       
 18909    /**
       
 18910     * Fires event "io:start" and creates, fires a transaction-specific
       
 18911     * start event, if `config.on.start` is defined.
       
 18912     *
       
 18913     * @method start
       
 18914     * @param {Object} transaction Transaction object.
       
 18915     * @param {Object} config Configuration object for the transaction.
       
 18916     */
       
 18917     start: function(transaction, config) {
       
 18918        /**
       
 18919         * Signals the start of an IO request.
       
 18920         * @event io:start
       
 18921         */
       
 18922         this._evt(EVENTS[0], transaction, config);
       
 18923     },
       
 18924 
       
 18925    /**
       
 18926     * Fires event "io:complete" and creates, fires a
       
 18927     * transaction-specific "complete" event, if config.on.complete is
       
 18928     * defined.
       
 18929     *
       
 18930     * @method complete
       
 18931     * @param {Object} transaction Transaction object.
       
 18932     * @param {Object} config Configuration object for the transaction.
       
 18933     */
       
 18934     complete: function(transaction, config) {
       
 18935        /**
       
 18936         * Signals the completion of the request-response phase of a
       
 18937         * transaction. Response status and data are accessible, if
       
 18938         * available, in this event.
       
 18939         * @event io:complete
       
 18940         */
       
 18941         this._evt(EVENTS[1], transaction, config);
       
 18942     },
       
 18943 
       
 18944    /**
       
 18945     * Fires event "io:end" and creates, fires a transaction-specific "end"
       
 18946     * event, if config.on.end is defined.
       
 18947     *
       
 18948     * @method end
       
 18949     * @param {Object} transaction Transaction object.
       
 18950     * @param {Object} config Configuration object for the transaction.
       
 18951     */
       
 18952     end: function(transaction, config) {
       
 18953        /**
       
 18954         * Signals the end of the transaction lifecycle.
       
 18955         * @event io:end
       
 18956         */
       
 18957         this._evt(EVENTS[2], transaction, config);
       
 18958         this._destroy(transaction);
       
 18959     },
       
 18960 
       
 18961    /**
       
 18962     * Fires event "io:success" and creates, fires a transaction-specific
       
 18963     * "success" event, if config.on.success is defined.
       
 18964     *
       
 18965     * @method success
       
 18966     * @param {Object} transaction Transaction object.
       
 18967     * @param {Object} config Configuration object for the transaction.
       
 18968     */
       
 18969     success: function(transaction, config) {
       
 18970        /**
       
 18971         * Signals an HTTP response with status in the 2xx range.
       
 18972         * Fires after io:complete.
       
 18973         * @event io:success
       
 18974         */
       
 18975         this._evt(EVENTS[3], transaction, config);
       
 18976         this.end(transaction, config);
       
 18977     },
       
 18978 
       
 18979    /**
       
 18980     * Fires event "io:failure" and creates, fires a transaction-specific
       
 18981     * "failure" event, if config.on.failure is defined.
       
 18982     *
       
 18983     * @method failure
       
 18984     * @param {Object} transaction Transaction object.
       
 18985     * @param {Object} config Configuration object for the transaction.
       
 18986     */
       
 18987     failure: function(transaction, config) {
       
 18988        /**
       
 18989         * Signals an HTTP response with status outside of the 2xx range.
       
 18990         * Fires after io:complete.
       
 18991         * @event io:failure
       
 18992         */
       
 18993         this._evt(EVENTS[4], transaction, config);
       
 18994         this.end(transaction, config);
       
 18995     },
       
 18996 
       
 18997    /**
       
 18998     * Fires event "io:progress" and creates, fires a transaction-specific
       
 18999     * "progress" event -- for XMLHttpRequest file upload -- if
       
 19000     * config.on.progress is defined.
       
 19001     *
       
 19002     * @method progress
       
 19003     * @param {Object} transaction Transaction object.
       
 19004     * @param {Object} progress event.
       
 19005     * @param {Object} config Configuration object for the transaction.
       
 19006     */
       
 19007     progress: function(transaction, e, config) {
       
 19008        /**
       
 19009         * Signals the interactive state during a file upload transaction.
       
 19010         * This event fires after io:start and before io:complete.
       
 19011         * @event io:progress
       
 19012         */
       
 19013         transaction.evt = e;
       
 19014         this._evt(EVENTS[5], transaction, config);
       
 19015     },
       
 19016 
       
 19017    /**
       
 19018     * Fires event "io:complete" and creates, fires a transaction-specific
       
 19019     * "complete" event -- for XMLHttpRequest file upload -- if
       
 19020     * config.on.complete is defined.
       
 19021     *
       
 19022     * @method load
       
 19023     * @param {Object} transaction Transaction object.
       
 19024     * @param {Object} load event.
       
 19025     * @param {Object} config Configuration object for the transaction.
       
 19026     */
       
 19027     load: function (transaction, e, config) {
       
 19028         transaction.evt = e.target;
       
 19029         this._evt(EVENTS[1], transaction, config);
       
 19030     },
       
 19031 
       
 19032    /**
       
 19033     * Fires event "io:failure" and creates, fires a transaction-specific
       
 19034     * "failure" event -- for XMLHttpRequest file upload -- if
       
 19035     * config.on.failure is defined.
       
 19036     *
       
 19037     * @method error
       
 19038     * @param {Object} transaction Transaction object.
       
 19039     * @param {Object} error event.
       
 19040     * @param {Object} config Configuration object for the transaction.
       
 19041     */
       
 19042     error: function (transaction, e, config) {
       
 19043         transaction.evt = e;
       
 19044         this._evt(EVENTS[4], transaction, config);
       
 19045     },
       
 19046 
       
 19047    /**
       
 19048     * Retry an XDR transaction, using the Flash tranport, if the native
       
 19049     * transport fails.
       
 19050     *
       
 19051     * @method _retry
       
 19052     * @private
       
 19053     * @param {Object} transaction Transaction object.
       
 19054     * @param {String} uri Qualified path to transaction resource.
       
 19055     * @param {Object} config Configuration object for the transaction.
       
 19056     */
       
 19057     _retry: function(transaction, uri, config) {
       
 19058         this._destroy(transaction);
       
 19059         config.xdr.use = 'flash';
       
 19060         return this.send(uri, config, transaction.id);
       
 19061     },
       
 19062 
       
 19063    /**
       
 19064     * Method that concatenates string data for HTTP GET transactions.
       
 19065     *
       
 19066     * @method _concat
       
 19067     * @private
       
 19068     * @param {String} uri URI or root data.
       
 19069     * @param {String} data Data to be concatenated onto URI.
       
 19070     * @return {String}
       
 19071     */
       
 19072     _concat: function(uri, data) {
       
 19073         uri += (uri.indexOf('?') === -1 ? '?' : '&') + data;
       
 19074         return uri;
       
 19075     },
       
 19076 
       
 19077    /**
       
 19078     * Stores default client headers for all transactions. If a label is
       
 19079     * passed with no value argument, the header will be deleted.
       
 19080     *
       
 19081     * @method setHeader
       
 19082     * @param {String} name HTTP header
       
 19083     * @param {String} value HTTP header value
       
 19084     */
       
 19085     setHeader: function(name, value) {
       
 19086         if (value) {
       
 19087             this._headers[name] = value;
       
 19088         } else {
       
 19089             delete this._headers[name];
       
 19090         }
       
 19091     },
       
 19092 
       
 19093    /**
       
 19094     * Method that sets all HTTP headers to be sent in a transaction.
       
 19095     *
       
 19096     * @method _setHeaders
       
 19097     * @private
       
 19098     * @param {Object} transaction - XHR instance for the specific transaction.
       
 19099     * @param {Object} headers - HTTP headers for the specific transaction, as
       
 19100     *                    defined in the configuration object passed to YUI.io().
       
 19101     */
       
 19102     _setHeaders: function(transaction, headers) {
       
 19103         headers = Y.merge(this._headers, headers);
       
 19104         Y.Object.each(headers, function(value, name) {
       
 19105             if (value !== 'disable') {
       
 19106                 transaction.setRequestHeader(name, headers[name]);
       
 19107             }
       
 19108         });
       
 19109     },
       
 19110 
       
 19111    /**
       
 19112     * Starts timeout count if the configuration object has a defined
       
 19113     * timeout property.
       
 19114     *
       
 19115     * @method _startTimeout
       
 19116     * @private
       
 19117     * @param {Object} transaction Transaction object generated by _create().
       
 19118     * @param {Object} timeout Timeout in milliseconds.
       
 19119     */
       
 19120     _startTimeout: function(transaction, timeout) {
       
 19121         var io = this;
       
 19122 
       
 19123         io._timeout[transaction.id] = setTimeout(function() {
       
 19124             io._abort(transaction, 'timeout');
       
 19125         }, timeout);
       
 19126     },
       
 19127 
       
 19128    /**
       
 19129     * Clears the timeout interval started by _startTimeout().
       
 19130     *
       
 19131     * @method _clearTimeout
       
 19132     * @private
       
 19133     * @param {Number} id - Transaction id.
       
 19134     */
       
 19135     _clearTimeout: function(id) {
       
 19136         clearTimeout(this._timeout[id]);
       
 19137         delete this._timeout[id];
       
 19138     },
       
 19139 
       
 19140    /**
       
 19141     * Method that determines if a transaction response qualifies as success
       
 19142     * or failure, based on the response HTTP status code, and fires the
       
 19143     * appropriate success or failure events.
       
 19144     *
       
 19145     * @method _result
       
 19146     * @private
       
 19147     * @static
       
 19148     * @param {Object} transaction Transaction object generated by _create().
       
 19149     * @param {Object} config Configuration object passed to io().
       
 19150     */
       
 19151     _result: function(transaction, config) {
       
 19152         var status;
       
 19153         // Firefox will throw an exception if attempting to access
       
 19154         // an XHR object's status property, after a request is aborted.
       
 19155         try {
       
 19156             status = transaction.c.status;
       
 19157         } catch(e) {
       
 19158             status = 0;
       
 19159         }
       
 19160 
       
 19161         // IE reports HTTP 204 as HTTP 1223.
       
 19162         if (status >= 200 && status < 300 || status === 304 || status === 1223) {
       
 19163             this.success(transaction, config);
       
 19164         } else {
       
 19165             this.failure(transaction, config);
       
 19166         }
       
 19167     },
       
 19168 
       
 19169    /**
       
 19170     * Event handler bound to onreadystatechange.
       
 19171     *
       
 19172     * @method _rS
       
 19173     * @private
       
 19174     * @param {Object} transaction Transaction object generated by _create().
       
 19175     * @param {Object} config Configuration object passed to YUI.io().
       
 19176     */
       
 19177     _rS: function(transaction, config) {
       
 19178         var io = this;
       
 19179 
       
 19180         if (transaction.c.readyState === 4) {
       
 19181             if (config.timeout) {
       
 19182                 io._clearTimeout(transaction.id);
       
 19183             }
       
 19184 
       
 19185             // Yield in the event of request timeout or abort.
       
 19186             setTimeout(function() {
       
 19187                 io.complete(transaction, config);
       
 19188                 io._result(transaction, config);
       
 19189             }, 0);
       
 19190         }
       
 19191     },
       
 19192 
       
 19193    /**
       
 19194     * Terminates a transaction due to an explicit abort or timeout.
       
 19195     *
       
 19196     * @method _abort
       
 19197     * @private
       
 19198     * @param {Object} transaction Transaction object generated by _create().
       
 19199     * @param {String} type Identifies timed out or aborted transaction.
       
 19200     */
       
 19201     _abort: function(transaction, type) {
       
 19202         if (transaction && transaction.c) {
       
 19203             transaction.e = type;
       
 19204             transaction.c.abort();
       
 19205         }
       
 19206     },
       
 19207 
       
 19208    /**
       
 19209     * Requests a transaction. `send()` is implemented as `Y.io()`.  Each
       
 19210     * transaction may include a configuration object.  Its properties are:
       
 19211     *
       
 19212     * <dl>
       
 19213     *   <dt>method</dt>
       
 19214     *     <dd>HTTP method verb (e.g., GET or POST). If this property is not
       
 19215     *         not defined, the default value will be GET.</dd>
       
 19216     *
       
 19217     *   <dt>data</dt>
       
 19218     *     <dd>This is the name-value string that will be sent as the
       
 19219     *     transaction data. If the request is HTTP GET, the data become
       
 19220     *     part of querystring. If HTTP POST, the data are sent in the
       
 19221     *     message body.</dd>
       
 19222     *
       
 19223     *   <dt>xdr</dt>
       
 19224     *     <dd>Defines the transport to be used for cross-domain requests.
       
 19225     *     By setting this property, the transaction will use the specified
       
 19226     *     transport instead of XMLHttpRequest. The properties of the
       
 19227     *     transport object are:
       
 19228     *     <dl>
       
 19229     *       <dt>use</dt>
       
 19230     *         <dd>The transport to be used: 'flash' or 'native'</dd>
       
 19231     *       <dt>dataType</dt>
       
 19232     *         <dd>Set the value to 'XML' if that is the expected response
       
 19233     *         content type.</dd>
       
 19234     *       <dt>credentials</dt>
       
 19235     *         <dd>Set the value to 'true' to set XHR.withCredentials property to true.</dd>
       
 19236     *     </dl></dd>
       
 19237     *
       
 19238     *   <dt>form</dt>
       
 19239     *     <dd>Form serialization configuration object.  Its properties are:
       
 19240     *     <dl>
       
 19241     *       <dt>id</dt>
       
 19242     *         <dd>Node object or id of HTML form</dd>
       
 19243     *       <dt>useDisabled</dt>
       
 19244     *         <dd>`true` to also serialize disabled form field values
       
 19245     *         (defaults to `false`)</dd>
       
 19246     *     </dl></dd>
       
 19247     *
       
 19248     *   <dt>on</dt>
       
 19249     *     <dd>Assigns transaction event subscriptions. Available events are:
       
 19250     *     <dl>
       
 19251     *       <dt>start</dt>
       
 19252     *         <dd>Fires when a request is sent to a resource.</dd>
       
 19253     *       <dt>complete</dt>
       
 19254     *         <dd>Fires when the transaction is complete.</dd>
       
 19255     *       <dt>success</dt>
       
 19256     *         <dd>Fires when the HTTP response status is within the 2xx
       
 19257     *         range.</dd>
       
 19258     *       <dt>failure</dt>
       
 19259     *         <dd>Fires when the HTTP response status is outside the 2xx
       
 19260     *         range, if an exception occurs, if the transation is aborted,
       
 19261     *         or if the transaction exceeds a configured `timeout`.</dd>
       
 19262     *       <dt>end</dt>
       
 19263     *         <dd>Fires at the conclusion of the transaction
       
 19264     *            lifecycle, after `success` or `failure`.</dd>
       
 19265     *     </dl>
       
 19266     *
       
 19267     *     <p>Callback functions for `start` and `end` receive the id of the
       
 19268     *     transaction as a first argument. For `complete`, `success`, and
       
 19269     *     `failure`, callbacks receive the id and the response object
       
 19270     *     (usually the XMLHttpRequest instance).  If the `arguments`
       
 19271     *     property was included in the configuration object passed to
       
 19272     *     `Y.io()`, the configured data will be passed to all callbacks as
       
 19273     *     the last argument.</p>
       
 19274     *     </dd>
       
 19275     *
       
 19276     *   <dt>sync</dt>
       
 19277     *     <dd>Pass `true` to make a same-domain transaction synchronous.
       
 19278     *     <strong>CAVEAT</strong>: This will negatively impact the user
       
 19279     *     experience. Have a <em>very</em> good reason if you intend to use
       
 19280     *     this.</dd>
       
 19281     *
       
 19282     *   <dt>context</dt>
       
 19283     *     <dd>The "`this'" object for all configured event handlers. If a
       
 19284     *     specific context is needed for individual callbacks, bind the
       
 19285     *     callback to a context using `Y.bind()`.</dd>
       
 19286     *
       
 19287     *   <dt>headers</dt>
       
 19288     *     <dd>Object map of transaction headers to send to the server. The
       
 19289     *     object keys are the header names and the values are the header
       
 19290     *     values.</dd>
       
 19291     *
       
 19292     *   <dt>timeout</dt>
       
 19293     *     <dd>Millisecond threshold for the transaction before being
       
 19294     *     automatically aborted.</dd>
       
 19295     *
       
 19296     *   <dt>arguments</dt>
       
 19297     *     <dd>User-defined data passed to all registered event handlers.
       
 19298     *     This value is available as the second argument in the "start" and
       
 19299     *     "end" event handlers. It is the third argument in the "complete",
       
 19300     *     "success", and "failure" event handlers. <strong>Be sure to quote
       
 19301     *     this property name in the transaction configuration as
       
 19302     *     "arguments" is a reserved word in JavaScript</strong> (e.g.
       
 19303     *     `Y.io({ ..., "arguments": stuff })`).</dd>
       
 19304     * </dl>
       
 19305     *
       
 19306     * @method send
       
 19307     * @public
       
 19308     * @param {String} uri Qualified path to transaction resource.
       
 19309     * @param {Object} config Configuration object for the transaction.
       
 19310     * @param {Number} id Transaction id, if already set.
       
 19311     * @return {Object}
       
 19312     */
       
 19313     send: function(uri, config, id) {
       
 19314         var transaction, method, i, len, sync, data,
       
 19315             io = this,
       
 19316             u = uri,
       
 19317             response = {};
       
 19318 
       
 19319         config = config ? Y.Object(config) : {};
       
 19320         transaction = io._create(config, id);
       
 19321         method = config.method ? config.method.toUpperCase() : 'GET';
       
 19322         sync = config.sync;
       
 19323         data = config.data;
       
 19324 
       
 19325         // Serialize a map object into a key-value string using
       
 19326         // querystring-stringify-simple.
       
 19327         if ((Y.Lang.isObject(data) && !data.nodeType) && !transaction.upload) {
       
 19328             if (Y.QueryString && Y.QueryString.stringify) {
       
 19329                 Y.log('Stringifying config.data for request', 'info', 'io');
       
 19330                 config.data = data = Y.QueryString.stringify(data);
       
 19331             } else {
       
 19332                 Y.log('Failed to stringify config.data object, likely because `querystring-stringify-simple` is missing.', 'warn', 'io');
       
 19333             }
       
 19334         }
       
 19335 
       
 19336         if (config.form) {
       
 19337             if (config.form.upload) {
       
 19338                 // This is a file upload transaction, calling
       
 19339                 // upload() in io-upload-iframe.
       
 19340                 return io.upload(transaction, uri, config);
       
 19341             } else {
       
 19342                 // Serialize HTML form data into a key-value string.
       
 19343                 data = io._serialize(config.form, data);
       
 19344             }
       
 19345         }
       
 19346 
       
 19347         // Convert falsy values to an empty string. This way IE can't be
       
 19348         // rediculous and translate `undefined` to "undefined".
       
 19349         data || (data = '');
       
 19350 
       
 19351         if (data) {
       
 19352             switch (method) {
       
 19353                 case 'GET':
       
 19354                 case 'HEAD':
       
 19355                 case 'DELETE':
       
 19356                     u = io._concat(u, data);
       
 19357                     data = '';
       
 19358                     Y.log('HTTP' + method + ' with data.  The querystring is: ' + u, 'info', 'io');
       
 19359                     break;
       
 19360                 case 'POST':
       
 19361                 case 'PUT':
       
 19362                     // If Content-Type is defined in the configuration object, or
       
 19363                     // or as a default header, it will be used instead of
       
 19364                     // 'application/x-www-form-urlencoded; charset=UTF-8'
       
 19365                     config.headers = Y.merge({
       
 19366                         'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
       
 19367                     }, config.headers);
       
 19368                     break;
       
 19369             }
       
 19370         }
       
 19371 
       
 19372         if (transaction.xdr) {
       
 19373             // Route data to io-xdr module for flash and XDomainRequest.
       
 19374             return io.xdr(u, transaction, config);
       
 19375         }
       
 19376         else if (transaction.notify) {
       
 19377             // Route data to custom transport
       
 19378             return transaction.c.send(transaction, uri, config);
       
 19379         }
       
 19380 
       
 19381         if (!sync && !transaction.upload) {
       
 19382             transaction.c.onreadystatechange = function() {
       
 19383                 io._rS(transaction, config);
       
 19384             };
       
 19385         }
       
 19386 
       
 19387         try {
       
 19388             // Determine if request is to be set as
       
 19389             // synchronous or asynchronous.
       
 19390             transaction.c.open(method, u, !sync, config.username || null, config.password || null);
       
 19391             io._setHeaders(transaction.c, config.headers || {});
       
 19392             io.start(transaction, config);
       
 19393 
       
 19394             // Will work only in browsers that implement the
       
 19395             // Cross-Origin Resource Sharing draft.
       
 19396             if (config.xdr && config.xdr.credentials && SUPPORTS_CORS) {
       
 19397                 transaction.c.withCredentials = true;
       
 19398             }
       
 19399 
       
 19400             // Using "null" with HTTP POST will result in a request
       
 19401             // with no Content-Length header defined.
       
 19402             transaction.c.send(data);
       
 19403 
       
 19404             if (sync) {
       
 19405                 // Create a response object for synchronous transactions,
       
 19406                 // mixing id and arguments properties with the xhr
       
 19407                 // properties whitelist.
       
 19408                 for (i = 0, len = XHR_PROPS.length; i < len; ++i) {
       
 19409                     response[XHR_PROPS[i]] = transaction.c[XHR_PROPS[i]];
       
 19410                 }
       
 19411 
       
 19412                 response.getAllResponseHeaders = function() {
       
 19413                     return transaction.c.getAllResponseHeaders();
       
 19414                 };
       
 19415 
       
 19416                 response.getResponseHeader = function(name) {
       
 19417                     return transaction.c.getResponseHeader(name);
       
 19418                 };
       
 19419 
       
 19420                 io.complete(transaction, config);
       
 19421                 io._result(transaction, config);
       
 19422 
       
 19423                 return response;
       
 19424             }
       
 19425         } catch(e) {
       
 19426             if (transaction.xdr) {
       
 19427                 // This exception is usually thrown by browsers
       
 19428                 // that do not support XMLHttpRequest Level 2.
       
 19429                 // Retry the request with the XDR transport set
       
 19430                 // to 'flash'.  If the Flash transport is not
       
 19431                 // initialized or available, the transaction
       
 19432                 // will resolve to a transport error.
       
 19433                 return io._retry(transaction, uri, config);
       
 19434             } else {
       
 19435                 io.complete(transaction, config);
       
 19436                 io._result(transaction, config);
       
 19437             }
       
 19438         }
       
 19439 
       
 19440         // If config.timeout is defined, and the request is standard XHR,
       
 19441         // initialize timeout polling.
       
 19442         if (config.timeout) {
       
 19443             io._startTimeout(transaction, config.timeout);
       
 19444             Y.log('Configuration timeout set to: ' + config.timeout, 'info', 'io');
       
 19445         }
       
 19446 
       
 19447         return {
       
 19448             id: transaction.id,
       
 19449             abort: function() {
       
 19450                 return transaction.c ? io._abort(transaction, 'abort') : false;
       
 19451             },
       
 19452             isInProgress: function() {
       
 19453                 return transaction.c ? (transaction.c.readyState % 4) : false;
       
 19454             },
       
 19455             io: io
       
 19456         };
       
 19457     }
       
 19458 };
       
 19459 
       
 19460 /**
       
 19461 Method for initiating an ajax call.  The first argument is the url end
       
 19462 point for the call.  The second argument is an object to configure the
       
 19463 transaction and attach event subscriptions.  The configuration object
       
 19464 supports the following properties:
       
 19465 
       
 19466 <dl>
       
 19467   <dt>method</dt>
       
 19468     <dd>HTTP method verb (e.g., GET or POST). If this property is not
       
 19469         not defined, the default value will be GET.</dd>
       
 19470 
       
 19471   <dt>data</dt>
       
 19472     <dd>This is the name-value string that will be sent as the
       
 19473     transaction data. If the request is HTTP GET, the data become
       
 19474     part of querystring. If HTTP POST, the data are sent in the
       
 19475     message body.</dd>
       
 19476 
       
 19477   <dt>xdr</dt>
       
 19478     <dd>Defines the transport to be used for cross-domain requests.
       
 19479     By setting this property, the transaction will use the specified
       
 19480     transport instead of XMLHttpRequest. The properties of the
       
 19481     transport object are:
       
 19482     <dl>
       
 19483       <dt>use</dt>
       
 19484         <dd>The transport to be used: 'flash' or 'native'</dd>
       
 19485       <dt>dataType</dt>
       
 19486         <dd>Set the value to 'XML' if that is the expected response
       
 19487         content type.</dd>
       
 19488     </dl></dd>
       
 19489 
       
 19490   <dt>form</dt>
       
 19491     <dd>Form serialization configuration object.  Its properties are:
       
 19492     <dl>
       
 19493       <dt>id</dt>
       
 19494         <dd>Node object or id of HTML form</dd>
       
 19495       <dt>useDisabled</dt>
       
 19496         <dd>`true` to also serialize disabled form field values
       
 19497         (defaults to `false`)</dd>
       
 19498     </dl></dd>
       
 19499 
       
 19500   <dt>on</dt>
       
 19501     <dd>Assigns transaction event subscriptions. Available events are:
       
 19502     <dl>
       
 19503       <dt>start</dt>
       
 19504         <dd>Fires when a request is sent to a resource.</dd>
       
 19505       <dt>complete</dt>
       
 19506         <dd>Fires when the transaction is complete.</dd>
       
 19507       <dt>success</dt>
       
 19508         <dd>Fires when the HTTP response status is within the 2xx
       
 19509         range.</dd>
       
 19510       <dt>failure</dt>
       
 19511         <dd>Fires when the HTTP response status is outside the 2xx
       
 19512         range, if an exception occurs, if the transation is aborted,
       
 19513         or if the transaction exceeds a configured `timeout`.</dd>
       
 19514       <dt>end</dt>
       
 19515         <dd>Fires at the conclusion of the transaction
       
 19516            lifecycle, after `success` or `failure`.</dd>
       
 19517     </dl>
       
 19518 
       
 19519     <p>Callback functions for `start` and `end` receive the id of the
       
 19520     transaction as a first argument. For `complete`, `success`, and
       
 19521     `failure`, callbacks receive the id and the response object
       
 19522     (usually the XMLHttpRequest instance).  If the `arguments`
       
 19523     property was included in the configuration object passed to
       
 19524     `Y.io()`, the configured data will be passed to all callbacks as
       
 19525     the last argument.</p>
       
 19526     </dd>
       
 19527 
       
 19528   <dt>sync</dt>
       
 19529     <dd>Pass `true` to make a same-domain transaction synchronous.
       
 19530     <strong>CAVEAT</strong>: This will negatively impact the user
       
 19531     experience. Have a <em>very</em> good reason if you intend to use
       
 19532     this.</dd>
       
 19533 
       
 19534   <dt>context</dt>
       
 19535     <dd>The "`this'" object for all configured event handlers. If a
       
 19536     specific context is needed for individual callbacks, bind the
       
 19537     callback to a context using `Y.bind()`.</dd>
       
 19538 
       
 19539   <dt>headers</dt>
       
 19540     <dd>Object map of transaction headers to send to the server. The
       
 19541     object keys are the header names and the values are the header
       
 19542     values.</dd>
       
 19543 
       
 19544   <dt>timeout</dt>
       
 19545     <dd>Millisecond threshold for the transaction before being
       
 19546     automatically aborted.</dd>
       
 19547 
       
 19548   <dt>arguments</dt>
       
 19549     <dd>User-defined data passed to all registered event handlers.
       
 19550     This value is available as the second argument in the "start" and
       
 19551     "end" event handlers. It is the third argument in the "complete",
       
 19552     "success", and "failure" event handlers. <strong>Be sure to quote
       
 19553     this property name in the transaction configuration as
       
 19554     "arguments" is a reserved word in JavaScript</strong> (e.g.
       
 19555     `Y.io({ ..., "arguments": stuff })`).</dd>
       
 19556 </dl>
       
 19557 
       
 19558 @method io
       
 19559 @static
       
 19560 @param {String} url qualified path to transaction resource.
       
 19561 @param {Object} config configuration object for the transaction.
       
 19562 @return {Object}
       
 19563 @for YUI
       
 19564 **/
       
 19565 Y.io = function(url, config) {
       
 19566     // Calling IO through the static interface will use and reuse
       
 19567     // an instance of IO.
       
 19568     var transaction = Y.io._map['io:0'] || new IO();
       
 19569     return transaction.send.apply(transaction, [url, config]);
       
 19570 };
       
 19571 
       
 19572 /**
       
 19573 Method for setting and deleting IO HTTP headers to be sent with every
       
 19574 request.
       
 19575 
       
 19576 Hosted as a property on the `io` function (e.g. `Y.io.header`).
       
 19577 
       
 19578 @method header
       
 19579 @param {String} name HTTP header
       
 19580 @param {String} value HTTP header value
       
 19581 @static
       
 19582 **/
       
 19583 Y.io.header = function(name, value) {
       
 19584     // Calling IO through the static interface will use and reuse
       
 19585     // an instance of IO.
       
 19586     var transaction = Y.io._map['io:0'] || new IO();
       
 19587     transaction.setHeader(name, value);
       
 19588 };
       
 19589 
       
 19590 Y.IO = IO;
       
 19591 // Map of all IO instances created.
       
 19592 Y.io._map = {};
       
 19593 var XHR = win && win.XMLHttpRequest,
       
 19594     XDR = win && win.XDomainRequest,
       
 19595     AX = win && win.ActiveXObject,
       
 19596 
       
 19597     // Checks for the presence of the `withCredentials` in an XHR instance
       
 19598     // object, which will be present if the environment supports CORS.
       
 19599     SUPPORTS_CORS = XHR && 'withCredentials' in (new XMLHttpRequest());
       
 19600 
       
 19601 
       
 19602 Y.mix(Y.IO, {
       
 19603     /**
       
 19604     * The ID of the default IO transport, defaults to `xhr`
       
 19605     * @property _default
       
 19606     * @type {String}
       
 19607     * @static
       
 19608     */
       
 19609     _default: 'xhr',
       
 19610     /**
       
 19611     *
       
 19612     * @method defaultTransport
       
 19613     * @static
       
 19614     * @param {String} [id] The transport to set as the default, if empty a new transport is created.
       
 19615     * @return {Object} The transport object with a `send` method
       
 19616     */
       
 19617     defaultTransport: function(id) {
       
 19618         if (id) {
       
 19619             Y.log('Setting default IO to: ' + id, 'info', 'io');
       
 19620             Y.IO._default = id;
       
 19621         } else {
       
 19622             var o = {
       
 19623                 c: Y.IO.transports[Y.IO._default](),
       
 19624                 notify: Y.IO._default === 'xhr' ? false : true
       
 19625             };
       
 19626             Y.log('Creating default transport: ' + Y.IO._default, 'info', 'io');
       
 19627             return o;
       
 19628         }
       
 19629     },
       
 19630     /**
       
 19631     * An object hash of custom transports available to IO
       
 19632     * @property transports
       
 19633     * @type {Object}
       
 19634     * @static
       
 19635     */
       
 19636     transports: {
       
 19637         xhr: function () {
       
 19638             return XHR ? new XMLHttpRequest() :
       
 19639                 AX ? new ActiveXObject('Microsoft.XMLHTTP') : null;
       
 19640         },
       
 19641         xdr: function () {
       
 19642             return XDR ? new XDomainRequest() : null;
       
 19643         },
       
 19644         iframe: function () { return {}; },
       
 19645         flash: null,
       
 19646         nodejs: null
       
 19647     },
       
 19648     /**
       
 19649     * Create a custom transport of type and return it's object
       
 19650     * @method customTransport
       
 19651     * @param {String} id The id of the transport to create.
       
 19652     * @static
       
 19653     */
       
 19654     customTransport: function(id) {
       
 19655         var o = { c: Y.IO.transports[id]() };
       
 19656 
       
 19657         o[(id === 'xdr' || id === 'flash') ? 'xdr' : 'notify'] = true;
       
 19658         return o;
       
 19659     }
       
 19660 });
       
 19661 
       
 19662 Y.mix(Y.IO.prototype, {
       
 19663     /**
       
 19664     * Fired from the notify method of the transport which in turn fires
       
 19665     * the event on the IO object.
       
 19666     * @method notify
       
 19667     * @param {String} event The name of the event
       
 19668     * @param {Object} transaction The transaction object
       
 19669     * @param {Object} config The configuration object for this transaction
       
 19670     */
       
 19671     notify: function(event, transaction, config) {
       
 19672         var io = this;
       
 19673 
       
 19674         switch (event) {
       
 19675             case 'timeout':
       
 19676             case 'abort':
       
 19677             case 'transport error':
       
 19678                 transaction.c = { status: 0, statusText: event };
       
 19679                 event = 'failure';
       
 19680             default:
       
 19681                 io[event].apply(io, [transaction, config]);
       
 19682         }
       
 19683     }
       
 19684 });
       
 19685 
       
 19686 
       
 19687 
       
 19688 
       
 19689 }, '@VERSION@', {"requires": ["event-custom-base", "querystring-stringify-simple"]});
       
 19690 YUI.add('json-parse', function (Y, NAME) {
       
 19691 
       
 19692 var _JSON = Y.config.global.JSON;
       
 19693 
       
 19694 Y.namespace('JSON').parse = function (obj, reviver, space) {
       
 19695     return _JSON.parse((typeof obj === 'string' ? obj : obj + ''), reviver, space);
       
 19696 };
       
 19697 
       
 19698 
       
 19699 }, '@VERSION@', {"requires": ["yui-base"]});
       
 19700 YUI.add('transition', function (Y, NAME) {
       
 19701 
       
 19702 /**
       
 19703 * Provides the transition method for Node.
       
 19704 * Transition has no API of its own, but adds the transition method to Node.
       
 19705 *
       
 19706 * @module transition
       
 19707 * @requires node-style
       
 19708 */
       
 19709 
       
 19710 var CAMEL_VENDOR_PREFIX = '',
       
 19711     VENDOR_PREFIX = '',
       
 19712     DOCUMENT = Y.config.doc,
       
 19713     DOCUMENT_ELEMENT = 'documentElement',
       
 19714     DOCUMENT_STYLE = DOCUMENT[DOCUMENT_ELEMENT].style,
       
 19715     TRANSITION_CAMEL = 'transition',
       
 19716     TRANSITION_PROPERTY_CAMEL = 'transitionProperty',
       
 19717     TRANSITION_PROPERTY,
       
 19718     TRANSITION_DURATION,
       
 19719     TRANSITION_TIMING_FUNCTION,
       
 19720     TRANSITION_DELAY,
       
 19721     TRANSITION_END,
       
 19722     ON_TRANSITION_END,
       
 19723 
       
 19724     EMPTY_OBJ = {},
       
 19725 
       
 19726     VENDORS = [
       
 19727         'Webkit',
       
 19728         'Moz'
       
 19729     ],
       
 19730 
       
 19731     VENDOR_TRANSITION_END = {
       
 19732         Webkit: 'webkitTransitionEnd'
       
 19733     },
       
 19734 
       
 19735 /**
       
 19736  * A class for constructing transition instances.
       
 19737  * Adds the "transition" method to Node.
       
 19738  * @class Transition
       
 19739  * @constructor
       
 19740  */
       
 19741 
       
 19742 Transition = function() {
       
 19743     this.init.apply(this, arguments);
       
 19744 };
       
 19745 
       
 19746 // One off handling of transform-prefixing.
       
 19747 Transition._TRANSFORM = 'transform';
       
 19748 
       
 19749 Transition._toCamel = function(property) {
       
 19750     property = property.replace(/-([a-z])/gi, function(m0, m1) {
       
 19751         return m1.toUpperCase();
       
 19752     });
       
 19753 
       
 19754     return property;
       
 19755 };
       
 19756 
       
 19757 Transition._toHyphen = function(property) {
       
 19758     property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
       
 19759         var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2;
       
 19760 
       
 19761         if (m3) {
       
 19762             str += '-' + m3.toLowerCase();
       
 19763         }
       
 19764 
       
 19765         return str;
       
 19766     });
       
 19767 
       
 19768     return property;
       
 19769 };
       
 19770 
       
 19771 Transition.SHOW_TRANSITION = 'fadeIn';
       
 19772 Transition.HIDE_TRANSITION = 'fadeOut';
       
 19773 
       
 19774 Transition.useNative = false;
       
 19775 
       
 19776 // Map transition properties to vendor-specific versions.
       
 19777 if ('transition' in DOCUMENT_STYLE 
       
 19778     && 'transitionProperty' in DOCUMENT_STYLE 
       
 19779     && 'transitionDuration' in DOCUMENT_STYLE
       
 19780     && 'transitionTimingFunction' in DOCUMENT_STYLE
       
 19781     && 'transitionDelay' in DOCUMENT_STYLE) {
       
 19782     Transition.useNative = true;
       
 19783     Transition.supported = true; // TODO: remove
       
 19784 } else {
       
 19785     Y.Array.each(VENDORS, function(val) { // then vendor specific
       
 19786         var property = val + 'Transition';
       
 19787         if (property in DOCUMENT[DOCUMENT_ELEMENT].style) {
       
 19788             CAMEL_VENDOR_PREFIX = val;
       
 19789             VENDOR_PREFIX       = Transition._toHyphen(val) + '-';
       
 19790 
       
 19791             Transition.useNative = true;
       
 19792             Transition.supported = true; // TODO: remove
       
 19793             Transition._VENDOR_PREFIX = val;
       
 19794         }
       
 19795     });
       
 19796 }
       
 19797 
       
 19798 // Map transform property to vendor-specific versions.
       
 19799 // One-off required for cssText injection.
       
 19800 if (typeof DOCUMENT_STYLE.transform === 'undefined') {
       
 19801     Y.Array.each(VENDORS, function(val) { // then vendor specific
       
 19802         var property = val + 'Transform';
       
 19803         if (typeof DOCUMENT_STYLE[property] !== 'undefined') {
       
 19804             Transition._TRANSFORM = property;
       
 19805         }
       
 19806     });
       
 19807 }
       
 19808 
       
 19809 if (CAMEL_VENDOR_PREFIX) {
       
 19810     TRANSITION_CAMEL          = CAMEL_VENDOR_PREFIX + 'Transition';
       
 19811     TRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty';
       
 19812 }
       
 19813 
       
 19814 TRANSITION_PROPERTY        = VENDOR_PREFIX + 'transition-property';
       
 19815 TRANSITION_DURATION        = VENDOR_PREFIX + 'transition-duration';
       
 19816 TRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function';
       
 19817 TRANSITION_DELAY           = VENDOR_PREFIX + 'transition-delay';
       
 19818 
       
 19819 TRANSITION_END    = 'transitionend';
       
 19820 ON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend';
       
 19821 TRANSITION_END    = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END;
       
 19822 
       
 19823 Transition.fx = {};
       
 19824 Transition.toggles = {};
       
 19825 
       
 19826 Transition._hasEnd = {};
       
 19827 
       
 19828 Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
       
 19829 
       
 19830 Y.Node.DOM_EVENTS[TRANSITION_END] = 1;
       
 19831 
       
 19832 Transition.NAME = 'transition';
       
 19833 
       
 19834 Transition.DEFAULT_EASING = 'ease';
       
 19835 Transition.DEFAULT_DURATION = 0.5;
       
 19836 Transition.DEFAULT_DELAY = 0;
       
 19837 
       
 19838 Transition._nodeAttrs = {};
       
 19839 
       
 19840 Transition.prototype = {
       
 19841     constructor: Transition,
       
 19842     init: function(node, config) {
       
 19843         var anim = this;
       
 19844         anim._node = node;
       
 19845         if (!anim._running && config) {
       
 19846             anim._config = config;
       
 19847             node._transition = anim; // cache for reuse
       
 19848 
       
 19849             anim._duration = ('duration' in config) ?
       
 19850                 config.duration: anim.constructor.DEFAULT_DURATION;
       
 19851 
       
 19852             anim._delay = ('delay' in config) ?
       
 19853                 config.delay: anim.constructor.DEFAULT_DELAY;
       
 19854 
       
 19855             anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
       
 19856             anim._count = 0; // track number of animated properties
       
 19857             anim._running = false;
       
 19858 
       
 19859         }
       
 19860 
       
 19861         return anim;
       
 19862     },
       
 19863 
       
 19864     addProperty: function(prop, config) {
       
 19865         var anim = this,
       
 19866             node = this._node,
       
 19867             uid = Y.stamp(node),
       
 19868             nodeInstance = Y.one(node),
       
 19869             attrs = Transition._nodeAttrs[uid],
       
 19870             computed,
       
 19871             compareVal,
       
 19872             dur,
       
 19873             attr,
       
 19874             val;
       
 19875 
       
 19876         if (!attrs) {
       
 19877             attrs = Transition._nodeAttrs[uid] = {};
       
 19878         }
       
 19879 
       
 19880         attr = attrs[prop];
       
 19881 
       
 19882         // might just be a value
       
 19883         if (config && config.value !== undefined) {
       
 19884             val = config.value;
       
 19885         } else if (config !== undefined) {
       
 19886             val = config;
       
 19887             config = EMPTY_OBJ;
       
 19888         }
       
 19889 
       
 19890         if (typeof val === 'function') {
       
 19891             val = val.call(nodeInstance, nodeInstance);
       
 19892         }
       
 19893 
       
 19894         if (attr && attr.transition) {
       
 19895             // take control if another transition owns this property
       
 19896             if (attr.transition !== anim) {
       
 19897                 attr.transition._count--; // remapping attr to this transition
       
 19898             }
       
 19899         }
       
 19900 
       
 19901         anim._count++; // properties per transition
       
 19902 
       
 19903         // make 0 async and fire events
       
 19904         dur = ((typeof config.duration !== 'undefined') ? config.duration :
       
 19905                     anim._duration) || 0.0001;
       
 19906 
       
 19907         attrs[prop] = {
       
 19908             value: val,
       
 19909             duration: dur,
       
 19910             delay: (typeof config.delay !== 'undefined') ? config.delay :
       
 19911                     anim._delay,
       
 19912 
       
 19913             easing: config.easing || anim._easing,
       
 19914 
       
 19915             transition: anim
       
 19916         };
       
 19917 
       
 19918         // native end event doesnt fire when setting to same value
       
 19919         // supplementing with timer
       
 19920         // val may be a string or number (height: 0, etc), but computedStyle is always string
       
 19921         computed = Y.DOM.getComputedStyle(node, prop);
       
 19922         compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
       
 19923 
       
 19924         if (Transition.useNative && compareVal === val) {
       
 19925             setTimeout(function() {
       
 19926                 anim._onNativeEnd.call(node, {
       
 19927                     propertyName: prop,
       
 19928                     elapsedTime: dur
       
 19929                 });
       
 19930             }, dur * 1000);
       
 19931         }
       
 19932     },
       
 19933 
       
 19934     removeProperty: function(prop) {
       
 19935         var anim = this,
       
 19936             attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
       
 19937 
       
 19938         if (attrs && attrs[prop]) {
       
 19939             delete attrs[prop];
       
 19940             anim._count--;
       
 19941         }
       
 19942 
       
 19943     },
       
 19944 
       
 19945     initAttrs: function(config) {
       
 19946         var attr,
       
 19947             node = this._node;
       
 19948 
       
 19949         if (config.transform && !config[Transition._TRANSFORM]) {
       
 19950             config[Transition._TRANSFORM] = config.transform;
       
 19951             delete config.transform; // TODO: copy
       
 19952         }
       
 19953 
       
 19954         for (attr in config) {
       
 19955             if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
       
 19956                 this.addProperty(attr, config[attr]);
       
 19957 
       
 19958                 // when size is auto or % webkit starts from zero instead of computed
       
 19959                 // (https://bugs.webkit.org/show_bug.cgi?id=16020)
       
 19960                 // TODO: selective set
       
 19961                 if (node.style[attr] === '') {
       
 19962                     Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
       
 19963                 }
       
 19964             }
       
 19965         }
       
 19966     },
       
 19967 
       
 19968     /**
       
 19969      * Starts or an animation.
       
 19970      * @method run
       
 19971      * @chainable
       
 19972      * @private
       
 19973      */
       
 19974     run: function(callback) {
       
 19975         var anim = this,
       
 19976             node = anim._node,
       
 19977             config = anim._config,
       
 19978             data = {
       
 19979                 type: 'transition:start',
       
 19980                 config: config
       
 19981             };
       
 19982 
       
 19983 
       
 19984         if (!anim._running) {
       
 19985             anim._running = true;
       
 19986 
       
 19987             if (config.on && config.on.start) {
       
 19988                 config.on.start.call(Y.one(node), data);
       
 19989             }
       
 19990 
       
 19991             anim.initAttrs(anim._config);
       
 19992 
       
 19993             anim._callback = callback;
       
 19994             anim._start();
       
 19995         }
       
 19996 
       
 19997 
       
 19998         return anim;
       
 19999     },
       
 20000 
       
 20001     _start: function() {
       
 20002         this._runNative();
       
 20003     },
       
 20004 
       
 20005     _prepDur: function(dur) {
       
 20006         dur = parseFloat(dur) * 1000;
       
 20007 
       
 20008         return dur + 'ms';
       
 20009     },
       
 20010 
       
 20011     _runNative: function() {
       
 20012         var anim = this,
       
 20013             node = anim._node,
       
 20014             uid = Y.stamp(node),
       
 20015             style = node.style,
       
 20016             computed = node.ownerDocument.defaultView.getComputedStyle(node),
       
 20017             attrs = Transition._nodeAttrs[uid],
       
 20018             cssText = '',
       
 20019             cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)],
       
 20020 
       
 20021             transitionText = TRANSITION_PROPERTY + ': ',
       
 20022             duration = TRANSITION_DURATION + ': ',
       
 20023             easing = TRANSITION_TIMING_FUNCTION + ': ',
       
 20024             delay = TRANSITION_DELAY + ': ',
       
 20025             hyphy,
       
 20026             attr,
       
 20027             name;
       
 20028 
       
 20029         // preserve existing transitions
       
 20030         if (cssTransition !== 'all') {
       
 20031             transitionText += cssTransition + ',';
       
 20032             duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ',';
       
 20033             easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ',';
       
 20034             delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ',';
       
 20035 
       
 20036         }
       
 20037 
       
 20038         // run transitions mapped to this instance
       
 20039         for (name in attrs) {
       
 20040             hyphy = Transition._toHyphen(name);
       
 20041             attr = attrs[name];
       
 20042             if ((attr = attrs[name]) && attr.transition === anim) {
       
 20043                 if (name in node.style) { // only native styles allowed
       
 20044                     duration += anim._prepDur(attr.duration) + ',';
       
 20045                     delay += anim._prepDur(attr.delay) + ',';
       
 20046                     easing += (attr.easing) + ',';
       
 20047 
       
 20048                     transitionText += hyphy + ',';
       
 20049                     cssText += hyphy + ': ' + attr.value + '; ';
       
 20050                 } else {
       
 20051                     this.removeProperty(name);
       
 20052                 }
       
 20053             }
       
 20054         }
       
 20055 
       
 20056         transitionText = transitionText.replace(/,$/, ';');
       
 20057         duration = duration.replace(/,$/, ';');
       
 20058         easing = easing.replace(/,$/, ';');
       
 20059         delay = delay.replace(/,$/, ';');
       
 20060 
       
 20061         // only one native end event per node
       
 20062         if (!Transition._hasEnd[uid]) {
       
 20063             node.addEventListener(TRANSITION_END, anim._onNativeEnd, '');
       
 20064             Transition._hasEnd[uid] = true;
       
 20065 
       
 20066         }
       
 20067 
       
 20068         style.cssText += transitionText + duration + easing + delay + cssText;
       
 20069 
       
 20070     },
       
 20071 
       
 20072     _end: function(elapsed) {
       
 20073         var anim = this,
       
 20074             node = anim._node,
       
 20075             callback = anim._callback,
       
 20076             config = anim._config,
       
 20077             data = {
       
 20078                 type: 'transition:end',
       
 20079                 config: config,
       
 20080                 elapsedTime: elapsed
       
 20081             },
       
 20082 
       
 20083             nodeInstance = Y.one(node);
       
 20084 
       
 20085         anim._running = false;
       
 20086         anim._callback = null;
       
 20087 
       
 20088         if (node) {
       
 20089             if (config.on && config.on.end) {
       
 20090                 setTimeout(function() { // IE: allow previous update to finish
       
 20091                     config.on.end.call(nodeInstance, data);
       
 20092 
       
 20093                     // nested to ensure proper fire order
       
 20094                     if (callback) {
       
 20095                         callback.call(nodeInstance, data);
       
 20096                     }
       
 20097 
       
 20098                 }, 1);
       
 20099             } else if (callback) {
       
 20100                 setTimeout(function() { // IE: allow previous update to finish
       
 20101                     callback.call(nodeInstance, data);
       
 20102                 }, 1);
       
 20103             }
       
 20104         }
       
 20105 
       
 20106     },
       
 20107 
       
 20108     _endNative: function(name) {
       
 20109         var node = this._node,
       
 20110             value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)];
       
 20111 
       
 20112         name = Transition._toHyphen(name);
       
 20113         if (typeof value === 'string') {
       
 20114             value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
       
 20115             value = value.replace(/^,|,$/, '');
       
 20116             node.style[TRANSITION_CAMEL] = value;
       
 20117         }
       
 20118     },
       
 20119 
       
 20120     _onNativeEnd: function(e) {
       
 20121         var node = this,
       
 20122             uid = Y.stamp(node),
       
 20123             event = e,//e._event,
       
 20124             name = Transition._toCamel(event.propertyName),
       
 20125             elapsed = event.elapsedTime,
       
 20126             attrs = Transition._nodeAttrs[uid],
       
 20127             attr = attrs[name],
       
 20128             anim = (attr) ? attr.transition : null,
       
 20129             data,
       
 20130             config;
       
 20131 
       
 20132         if (anim) {
       
 20133             anim.removeProperty(name);
       
 20134             anim._endNative(name);
       
 20135             config = anim._config[name];
       
 20136 
       
 20137             data = {
       
 20138                 type: 'propertyEnd',
       
 20139                 propertyName: name,
       
 20140                 elapsedTime: elapsed,
       
 20141                 config: config
       
 20142             };
       
 20143 
       
 20144             if (config && config.on && config.on.end) {
       
 20145                 config.on.end.call(Y.one(node), data);
       
 20146             }
       
 20147 
       
 20148             if (anim._count <= 0)  { // after propertyEnd fires
       
 20149                 anim._end(elapsed);
       
 20150                 node.style[TRANSITION_PROPERTY_CAMEL] = ''; // clean up style
       
 20151             }
       
 20152         }
       
 20153     },
       
 20154 
       
 20155     destroy: function() {
       
 20156         var anim = this,
       
 20157             node = anim._node;
       
 20158 
       
 20159         if (node) {
       
 20160             node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
       
 20161             anim._node = null;
       
 20162         }
       
 20163     }
       
 20164 };
       
 20165 
       
 20166 Y.Transition = Transition;
       
 20167 Y.TransitionNative = Transition; // TODO: remove
       
 20168 
       
 20169 /**
       
 20170  *   Animate one or more css properties to a given value. Requires the "transition" module.
       
 20171  *   <pre>example usage:
       
 20172  *       Y.one('#demo').transition({
       
 20173  *           duration: 1, // in seconds, default is 0.5
       
 20174  *           easing: 'ease-out', // default is 'ease'
       
 20175  *           delay: '1', // delay start for 1 second, default is 0
       
 20176  *
       
 20177  *           height: '10px',
       
 20178  *           width: '10px',
       
 20179  *
       
 20180  *           opacity: { // per property
       
 20181  *               value: 0,
       
 20182  *               duration: 2,
       
 20183  *               delay: 2,
       
 20184  *               easing: 'ease-in'
       
 20185  *           }
       
 20186  *       });
       
 20187  *   </pre>
       
 20188  *   @for Node
       
 20189  *   @method transition
       
 20190  *   @param {Object} config An object containing one or more style properties, a duration and an easing.
       
 20191  *   @param {Function} callback A function to run after the transition has completed.
       
 20192  *   @chainable
       
 20193 */
       
 20194 Y.Node.prototype.transition = function(name, config, callback) {
       
 20195     var
       
 20196         transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
       
 20197         anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
       
 20198         fxConfig,
       
 20199         prop;
       
 20200 
       
 20201     if (typeof name === 'string') { // named effect, pull config from registry
       
 20202         if (typeof config === 'function') {
       
 20203             callback = config;
       
 20204             config = null;
       
 20205         }
       
 20206 
       
 20207         fxConfig = Transition.fx[name];
       
 20208 
       
 20209         if (config && typeof config !== 'boolean') {
       
 20210             config = Y.clone(config);
       
 20211 
       
 20212             for (prop in fxConfig) {
       
 20213                 if (fxConfig.hasOwnProperty(prop)) {
       
 20214                     if (! (prop in config)) {
       
 20215                         config[prop] = fxConfig[prop];
       
 20216                     }
       
 20217                 }
       
 20218             }
       
 20219         } else {
       
 20220             config = fxConfig;
       
 20221         }
       
 20222 
       
 20223     } else { // name is a config, config is a callback or undefined
       
 20224         callback = config;
       
 20225         config = name;
       
 20226     }
       
 20227 
       
 20228     if (anim && !anim._running) {
       
 20229         anim.init(this, config);
       
 20230     } else {
       
 20231         anim = new Transition(this._node, config);
       
 20232     }
       
 20233 
       
 20234     anim.run(callback);
       
 20235     return this;
       
 20236 };
       
 20237 
       
 20238 Y.Node.prototype.show = function(name, config, callback) {
       
 20239     this._show(); // show prior to transition
       
 20240     if (name && Y.Transition) {
       
 20241         if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
       
 20242             if (typeof config === 'function') {
       
 20243                 callback = config;
       
 20244                 config = name;
       
 20245             }
       
 20246             name = Transition.SHOW_TRANSITION;
       
 20247         }
       
 20248         this.transition(name, config, callback);
       
 20249     }
       
 20250     else if (name && !Y.Transition) { Y.log('unable to transition show; missing transition module', 'warn', 'node'); }
       
 20251     return this;
       
 20252 };
       
 20253 
       
 20254 Y.NodeList.prototype.show = function(name, config, callback) {
       
 20255     var nodes = this._nodes,
       
 20256         i = 0,
       
 20257         node;
       
 20258 
       
 20259     while ((node = nodes[i++])) {
       
 20260         Y.one(node).show(name, config, callback);
       
 20261     }
       
 20262 
       
 20263     return this;
       
 20264 };
       
 20265 
       
 20266 
       
 20267 
       
 20268 var _wrapCallBack = function(anim, fn, callback) {
       
 20269     return function() {
       
 20270         if (fn) {
       
 20271             fn.call(anim);
       
 20272         }
       
 20273         if (callback && typeof callback === 'function') {
       
 20274             callback.apply(anim._node, arguments);
       
 20275         }
       
 20276     };
       
 20277 };
       
 20278 
       
 20279 Y.Node.prototype.hide = function(name, config, callback) {
       
 20280     if (name && Y.Transition) {
       
 20281         if (typeof config === 'function') {
       
 20282             callback = config;
       
 20283             config = null;
       
 20284         }
       
 20285 
       
 20286         callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
       
 20287         if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
       
 20288             if (typeof config === 'function') {
       
 20289                 callback = config;
       
 20290                 config = name;
       
 20291             }
       
 20292             name = Transition.HIDE_TRANSITION;
       
 20293         }
       
 20294         this.transition(name, config, callback);
       
 20295     } else if (name && !Y.Transition) { Y.log('unable to transition hide; missing transition module', 'warn', 'node');
       
 20296     } else {
       
 20297         this._hide();
       
 20298     }
       
 20299     return this;
       
 20300 };
       
 20301 
       
 20302 Y.NodeList.prototype.hide = function(name, config, callback) {
       
 20303     var nodes = this._nodes,
       
 20304         i = 0,
       
 20305         node;
       
 20306 
       
 20307     while ((node = nodes[i++])) {
       
 20308         Y.one(node).hide(name, config, callback);
       
 20309     }
       
 20310 
       
 20311     return this;
       
 20312 };
       
 20313 
       
 20314 /**
       
 20315  *   Animate one or more css properties to a given value. Requires the "transition" module.
       
 20316  *   <pre>example usage:
       
 20317  *       Y.all('.demo').transition({
       
 20318  *           duration: 1, // in seconds, default is 0.5
       
 20319  *           easing: 'ease-out', // default is 'ease'
       
 20320  *           delay: '1', // delay start for 1 second, default is 0
       
 20321  *
       
 20322  *           height: '10px',
       
 20323  *           width: '10px',
       
 20324  *
       
 20325  *           opacity: { // per property
       
 20326  *               value: 0,
       
 20327  *               duration: 2,
       
 20328  *               delay: 2,
       
 20329  *               easing: 'ease-in'
       
 20330  *           }
       
 20331  *       });
       
 20332  *   </pre>
       
 20333  *   @for NodeList
       
 20334  *   @method transition
       
 20335  *   @param {Object} config An object containing one or more style properties, a duration and an easing.
       
 20336  *   @param {Function} callback A function to run after the transition has completed. The callback fires
       
 20337  *       once per item in the NodeList.
       
 20338  *   @chainable
       
 20339 */
       
 20340 Y.NodeList.prototype.transition = function(config, callback) {
       
 20341     var nodes = this._nodes,
       
 20342         i = 0,
       
 20343         node;
       
 20344 
       
 20345     while ((node = nodes[i++])) {
       
 20346         Y.one(node).transition(config, callback);
       
 20347     }
       
 20348 
       
 20349     return this;
       
 20350 };
       
 20351 
       
 20352 Y.Node.prototype.toggleView = function(name, on, callback) {
       
 20353     this._toggles = this._toggles || [];
       
 20354     callback = arguments[arguments.length - 1];
       
 20355 
       
 20356     if (typeof name !== 'string') { // no transition, just toggle
       
 20357         on = name;
       
 20358         this._toggleView(on, callback); // call original _toggleView in Y.Node
       
 20359         return;
       
 20360     }
       
 20361 
       
 20362     if (typeof on === 'function') { // Ignore "on" if used for callback argument.
       
 20363         on = undefined;
       
 20364     }
       
 20365 
       
 20366     if (typeof on === 'undefined' && name in this._toggles) { // reverse current toggle
       
 20367         on = ! this._toggles[name];
       
 20368     }
       
 20369 
       
 20370     on = (on) ? 1 : 0;
       
 20371     if (on) {
       
 20372         this._show();
       
 20373     }  else {
       
 20374         callback = _wrapCallBack(this, this._hide, callback);
       
 20375     }
       
 20376 
       
 20377     this._toggles[name] = on;
       
 20378     this.transition(Y.Transition.toggles[name][on], callback);
       
 20379 
       
 20380     return this;
       
 20381 };
       
 20382 
       
 20383 Y.NodeList.prototype.toggleView = function(name, on, callback) {
       
 20384     var nodes = this._nodes,
       
 20385         i = 0,
       
 20386         node;
       
 20387 
       
 20388     while ((node = nodes[i++])) {
       
 20389         node = Y.one(node);
       
 20390         node.toggleView.apply(node, arguments);
       
 20391     }
       
 20392 
       
 20393     return this;
       
 20394 };
       
 20395 
       
 20396 Y.mix(Transition.fx, {
       
 20397     fadeOut: {
       
 20398         opacity: 0,
       
 20399         duration: 0.5,
       
 20400         easing: 'ease-out'
       
 20401     },
       
 20402 
       
 20403     fadeIn: {
       
 20404         opacity: 1,
       
 20405         duration: 0.5,
       
 20406         easing: 'ease-in'
       
 20407     },
       
 20408 
       
 20409     sizeOut: {
       
 20410         height: 0,
       
 20411         width: 0,
       
 20412         duration: 0.75,
       
 20413         easing: 'ease-out'
       
 20414     },
       
 20415 
       
 20416     sizeIn: {
       
 20417         height: function(node) {
       
 20418             return node.get('scrollHeight') + 'px';
       
 20419         },
       
 20420         width: function(node) {
       
 20421             return node.get('scrollWidth') + 'px';
       
 20422         },
       
 20423         duration: 0.5,
       
 20424         easing: 'ease-in',
       
 20425 
       
 20426         on: {
       
 20427             start: function() {
       
 20428                 var overflow = this.getStyle('overflow');
       
 20429                 if (overflow !== 'hidden') { // enable scrollHeight/Width
       
 20430                     this.setStyle('overflow', 'hidden');
       
 20431                     this._transitionOverflow = overflow;
       
 20432                 }
       
 20433             },
       
 20434 
       
 20435             end: function() {
       
 20436                 if (this._transitionOverflow) { // revert overridden value
       
 20437                     this.setStyle('overflow', this._transitionOverflow);
       
 20438                     delete this._transitionOverflow;
       
 20439                 }
       
 20440             }
       
 20441         }
       
 20442     }
       
 20443 });
       
 20444 
       
 20445 Y.mix(Transition.toggles, {
       
 20446     size: ['sizeOut', 'sizeIn'],
       
 20447     fade: ['fadeOut', 'fadeIn']
       
 20448 });
       
 20449 
       
 20450 
       
 20451 }, '@VERSION@', {"requires": ["node-style"]});
       
 20452 YUI.add('selector-css2', function (Y, NAME) {
       
 20453 
       
 20454 /**
       
 20455  * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
       
 20456  * @module dom
       
 20457  * @submodule selector-css2
       
 20458  * @for Selector
       
 20459  */
       
 20460 
       
 20461 /*
       
 20462  * Provides helper methods for collecting and filtering DOM elements.
       
 20463  */
       
 20464 
       
 20465 var PARENT_NODE = 'parentNode',
       
 20466     TAG_NAME = 'tagName',
       
 20467     ATTRIBUTES = 'attributes',
       
 20468     COMBINATOR = 'combinator',
       
 20469     PSEUDOS = 'pseudos',
       
 20470 
       
 20471     Selector = Y.Selector,
       
 20472 
       
 20473     SelectorCSS2 = {
       
 20474         _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,
       
 20475         SORT_RESULTS: true,
       
 20476 
       
 20477         // TODO: better detection, document specific
       
 20478         _isXML: (function() {
       
 20479             var isXML = (Y.config.doc.createElement('div').tagName !== 'DIV');
       
 20480             return isXML;
       
 20481         }()),
       
 20482 
       
 20483         /**
       
 20484          * Mapping of shorthand tokens to corresponding attribute selector 
       
 20485          * @property shorthand
       
 20486          * @type object
       
 20487          */
       
 20488         shorthand: {
       
 20489             '\\#(-?[_a-z0-9]+[-\\w\\uE000]*)': '[id=$1]',
       
 20490             '\\.(-?[_a-z]+[-\\w\\uE000]*)': '[className~=$1]'
       
 20491         },
       
 20492 
       
 20493         /**
       
 20494          * List of operators and corresponding boolean functions. 
       
 20495          * These functions are passed the attribute and the current node's value of the attribute.
       
 20496          * @property operators
       
 20497          * @type object
       
 20498          */
       
 20499         operators: {
       
 20500             '': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute
       
 20501             '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
       
 20502             '|=': '^{val}-?' // optional hyphen-delimited
       
 20503         },
       
 20504 
       
 20505         pseudos: {
       
 20506            'first-child': function(node) { 
       
 20507                 return Y.DOM._children(node[PARENT_NODE])[0] === node; 
       
 20508             } 
       
 20509         },
       
 20510 
       
 20511         _bruteQuery: function(selector, root, firstOnly) {
       
 20512             var ret = [],
       
 20513                 nodes = [],
       
 20514                 tokens = Selector._tokenize(selector),
       
 20515                 token = tokens[tokens.length - 1],
       
 20516                 rootDoc = Y.DOM._getDoc(root),
       
 20517                 child,
       
 20518                 id,
       
 20519                 className,
       
 20520                 tagName;
       
 20521 
       
 20522             if (token) {
       
 20523                 // prefilter nodes
       
 20524                 id = token.id;
       
 20525                 className = token.className;
       
 20526                 tagName = token.tagName || '*';
       
 20527 
       
 20528                 if (root.getElementsByTagName) { // non-IE lacks DOM api on doc frags
       
 20529                     // try ID first, unless no root.all && root not in document
       
 20530                     // (root.all works off document, but not getElementById)
       
 20531                     if (id && (root.all || (root.nodeType === 9 || Y.DOM.inDoc(root)))) {
       
 20532                         nodes = Y.DOM.allById(id, root);
       
 20533                     // try className
       
 20534                     } else if (className) {
       
 20535                         nodes = root.getElementsByClassName(className);
       
 20536                     } else { // default to tagName
       
 20537                         nodes = root.getElementsByTagName(tagName);
       
 20538                     }
       
 20539 
       
 20540                 } else { // brute getElementsByTagName()
       
 20541                     child = root.firstChild;
       
 20542                     while (child) {
       
 20543                         // only collect HTMLElements
       
 20544                         // match tag to supplement missing getElementsByTagName
       
 20545                         if (child.tagName && (tagName === '*' || child.tagName === tagName)) {
       
 20546                             nodes.push(child);
       
 20547                         }
       
 20548                         child = child.nextSibling || child.firstChild;
       
 20549                     }
       
 20550                 }
       
 20551                 if (nodes.length) {
       
 20552                     ret = Selector._filterNodes(nodes, tokens, firstOnly);
       
 20553                 }
       
 20554             }
       
 20555 
       
 20556             return ret;
       
 20557         },
       
 20558         
       
 20559         _filterNodes: function(nodes, tokens, firstOnly) {
       
 20560             var i = 0,
       
 20561                 j,
       
 20562                 len = tokens.length,
       
 20563                 n = len - 1,
       
 20564                 result = [],
       
 20565                 node = nodes[0],
       
 20566                 tmpNode = node,
       
 20567                 getters = Y.Selector.getters,
       
 20568                 operator,
       
 20569                 combinator,
       
 20570                 token,
       
 20571                 path,
       
 20572                 pass,
       
 20573                 value,
       
 20574                 tests,
       
 20575                 test;
       
 20576 
       
 20577             for (i = 0; (tmpNode = node = nodes[i++]);) {
       
 20578                 n = len - 1;
       
 20579                 path = null;
       
 20580                 
       
 20581                 testLoop:
       
 20582                 while (tmpNode && tmpNode.tagName) {
       
 20583                     token = tokens[n];
       
 20584                     tests = token.tests;
       
 20585                     j = tests.length;
       
 20586                     if (j && !pass) {
       
 20587                         while ((test = tests[--j])) {
       
 20588                             operator = test[1];
       
 20589                             if (getters[test[0]]) {
       
 20590                                 value = getters[test[0]](tmpNode, test[0]);
       
 20591                             } else {
       
 20592                                 value = tmpNode[test[0]];
       
 20593                                 if (test[0] === 'tagName' && !Selector._isXML) {
       
 20594                                     value = value.toUpperCase();    
       
 20595                                 }
       
 20596                                 if (typeof value != 'string' && value !== undefined && value.toString) {
       
 20597                                     value = value.toString(); // coerce for comparison
       
 20598                                 } else if (value === undefined && tmpNode.getAttribute) {
       
 20599                                     // use getAttribute for non-standard attributes
       
 20600                                     value = tmpNode.getAttribute(test[0], 2); // 2 === force string for IE
       
 20601                                 }
       
 20602                             }
       
 20603 
       
 20604                             if ((operator === '=' && value !== test[2]) ||  // fast path for equality
       
 20605                                 (typeof operator !== 'string' && // protect against String.test monkey-patch (Moo)
       
 20606                                 operator.test && !operator.test(value)) ||  // regex test
       
 20607                                 (!operator.test && // protect against RegExp as function (webkit)
       
 20608                                         typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // function test
       
 20609 
       
 20610                                 // skip non element nodes or non-matching tags
       
 20611                                 if ((tmpNode = tmpNode[path])) {
       
 20612                                     while (tmpNode &&
       
 20613                                         (!tmpNode.tagName ||
       
 20614                                             (token.tagName && token.tagName !== tmpNode.tagName))
       
 20615                                     ) {
       
 20616                                         tmpNode = tmpNode[path]; 
       
 20617                                     }
       
 20618                                 }
       
 20619                                 continue testLoop;
       
 20620                             }
       
 20621                         }
       
 20622                     }
       
 20623 
       
 20624                     n--; // move to next token
       
 20625                     // now that we've passed the test, move up the tree by combinator
       
 20626                     if (!pass && (combinator = token.combinator)) {
       
 20627                         path = combinator.axis;
       
 20628                         tmpNode = tmpNode[path];
       
 20629 
       
 20630                         // skip non element nodes
       
 20631                         while (tmpNode && !tmpNode.tagName) {
       
 20632                             tmpNode = tmpNode[path]; 
       
 20633                         }
       
 20634 
       
 20635                         if (combinator.direct) { // one pass only
       
 20636                             path = null; 
       
 20637                         }
       
 20638 
       
 20639                     } else { // success if we made it this far
       
 20640                         result.push(node);
       
 20641                         if (firstOnly) {
       
 20642                             return result;
       
 20643                         }
       
 20644                         break;
       
 20645                     }
       
 20646                 }
       
 20647             }
       
 20648             node = tmpNode = null;
       
 20649             return result;
       
 20650         },
       
 20651 
       
 20652         combinators: {
       
 20653             ' ': {
       
 20654                 axis: 'parentNode'
       
 20655             },
       
 20656 
       
 20657             '>': {
       
 20658                 axis: 'parentNode',
       
 20659                 direct: true
       
 20660             },
       
 20661 
       
 20662 
       
 20663             '+': {
       
 20664                 axis: 'previousSibling',
       
 20665                 direct: true
       
 20666             }
       
 20667         },
       
 20668 
       
 20669         _parsers: [
       
 20670             {
       
 20671                 name: ATTRIBUTES,
       
 20672                 re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,
       
 20673                 fn: function(match, token) {
       
 20674                     var operator = match[2] || '',
       
 20675                         operators = Selector.operators,
       
 20676                         escVal = (match[3]) ? match[3].replace(/\\/g, '') : '',
       
 20677                         test;
       
 20678 
       
 20679                     // add prefiltering for ID and CLASS
       
 20680                     if ((match[1] === 'id' && operator === '=') ||
       
 20681                             (match[1] === 'className' &&
       
 20682                             Y.config.doc.documentElement.getElementsByClassName &&
       
 20683                             (operator === '~=' || operator === '='))) {
       
 20684                         token.prefilter = match[1];
       
 20685 
       
 20686 
       
 20687                         match[3] = escVal; 
       
 20688 
       
 20689                         // escape all but ID for prefilter, which may run through QSA (via Dom.allById)
       
 20690                         token[match[1]] = (match[1] === 'id') ? match[3] : escVal;
       
 20691 
       
 20692                     }
       
 20693 
       
 20694                     // add tests
       
 20695                     if (operator in operators) {
       
 20696                         test = operators[operator];
       
 20697                         if (typeof test === 'string') {
       
 20698                             match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1');
       
 20699                             test = new RegExp(test.replace('{val}', match[3]));
       
 20700                         }
       
 20701                         match[2] = test;
       
 20702                     }
       
 20703                     if (!token.last || token.prefilter !== match[1]) {
       
 20704                         return match.slice(1);
       
 20705                     }
       
 20706                 }
       
 20707             },
       
 20708             {
       
 20709                 name: TAG_NAME,
       
 20710                 re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
       
 20711                 fn: function(match, token) {
       
 20712                     var tag = match[1];
       
 20713 
       
 20714                     if (!Selector._isXML) {
       
 20715                         tag = tag.toUpperCase();
       
 20716                     }
       
 20717 
       
 20718                     token.tagName = tag;
       
 20719 
       
 20720                     if (tag !== '*' && (!token.last || token.prefilter)) {
       
 20721                         return [TAG_NAME, '=', tag];
       
 20722                     }
       
 20723                     if (!token.prefilter) {
       
 20724                         token.prefilter = 'tagName';
       
 20725                     }
       
 20726                 }
       
 20727             },
       
 20728             {
       
 20729                 name: COMBINATOR,
       
 20730                 re: /^\s*([>+~]|\s)\s*/,
       
 20731                 fn: function(match, token) {
       
 20732                 }
       
 20733             },
       
 20734             {
       
 20735                 name: PSEUDOS,
       
 20736                 re: /^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,
       
 20737                 fn: function(match, token) {
       
 20738                     var test = Selector[PSEUDOS][match[1]];
       
 20739                     if (test) { // reorder match array and unescape special chars for tests
       
 20740                         if (match[2]) {
       
 20741                             match[2] = match[2].replace(/\\/g, '');
       
 20742                         }
       
 20743                         return [match[2], test]; 
       
 20744                     } else { // selector token not supported (possibly missing CSS3 module)
       
 20745                         return false;
       
 20746                     }
       
 20747                 }
       
 20748             }
       
 20749             ],
       
 20750 
       
 20751         _getToken: function(token) {
       
 20752             return {
       
 20753                 tagName: null,
       
 20754                 id: null,
       
 20755                 className: null,
       
 20756                 attributes: {},
       
 20757                 combinator: null,
       
 20758                 tests: []
       
 20759             };
       
 20760         },
       
 20761 
       
 20762         /*
       
 20763             Break selector into token units per simple selector.
       
 20764             Combinator is attached to the previous token.
       
 20765          */
       
 20766         _tokenize: function(selector) {
       
 20767             selector = selector || '';
       
 20768             selector = Selector._parseSelector(Y.Lang.trim(selector)); 
       
 20769             var token = Selector._getToken(),     // one token per simple selector (left selector holds combinator)
       
 20770                 query = selector, // original query for debug report
       
 20771                 tokens = [],    // array of tokens
       
 20772                 found = false,  // whether or not any matches were found this pass
       
 20773                 match,         // the regex match
       
 20774                 test,
       
 20775                 i, parser;
       
 20776 
       
 20777             /*
       
 20778                 Search for selector patterns, store, and strip them from the selector string
       
 20779                 until no patterns match (invalid selector) or we run out of chars.
       
 20780 
       
 20781                 Multiple attributes and pseudos are allowed, in any order.
       
 20782                 for example:
       
 20783                     'form:first-child[type=button]:not(button)[lang|=en]'
       
 20784             */
       
 20785             outer:
       
 20786             do {
       
 20787                 found = false; // reset after full pass
       
 20788                 for (i = 0; (parser = Selector._parsers[i++]);) {
       
 20789                     if ( (match = parser.re.exec(selector)) ) { // note assignment
       
 20790                         if (parser.name !== COMBINATOR ) {
       
 20791                             token.selector = selector;
       
 20792                         }
       
 20793                         selector = selector.replace(match[0], ''); // strip current match from selector
       
 20794                         if (!selector.length) {
       
 20795                             token.last = true;
       
 20796                         }
       
 20797 
       
 20798                         if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
       
 20799                             match[1] = Selector._attrFilters[match[1]];
       
 20800                         }
       
 20801 
       
 20802                         test = parser.fn(match, token);
       
 20803                         if (test === false) { // selector not supported
       
 20804                             found = false;
       
 20805                             break outer;
       
 20806                         } else if (test) {
       
 20807                             token.tests.push(test);
       
 20808                         }
       
 20809 
       
 20810                         if (!selector.length || parser.name === COMBINATOR) {
       
 20811                             tokens.push(token);
       
 20812                             token = Selector._getToken(token);
       
 20813                             if (parser.name === COMBINATOR) {
       
 20814                                 token.combinator = Y.Selector.combinators[match[1]];
       
 20815                             }
       
 20816                         }
       
 20817                         found = true;
       
 20818                     }
       
 20819                 }
       
 20820             } while (found && selector.length);
       
 20821 
       
 20822             if (!found || selector.length) { // not fully parsed
       
 20823                 Y.log('query: ' + query + ' contains unsupported token in: ' + selector, 'warn', 'Selector');
       
 20824                 tokens = [];
       
 20825             }
       
 20826             return tokens;
       
 20827         },
       
 20828 
       
 20829         _replaceMarkers: function(selector) {
       
 20830             selector = selector.replace(/\[/g, '\uE003');
       
 20831             selector = selector.replace(/\]/g, '\uE004');
       
 20832 
       
 20833             selector = selector.replace(/\(/g, '\uE005');
       
 20834             selector = selector.replace(/\)/g, '\uE006');
       
 20835             return selector;
       
 20836         },
       
 20837 
       
 20838         _replaceShorthand: function(selector) {
       
 20839             var shorthand = Y.Selector.shorthand,
       
 20840                 re;
       
 20841 
       
 20842             for (re in shorthand) {
       
 20843                 if (shorthand.hasOwnProperty(re)) {
       
 20844                     selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]);
       
 20845                 }
       
 20846             }
       
 20847 
       
 20848             return selector;
       
 20849         },
       
 20850 
       
 20851         _parseSelector: function(selector) {
       
 20852             var replaced = Y.Selector._replaceSelector(selector),
       
 20853                 selector = replaced.selector;
       
 20854 
       
 20855             // replace shorthand (".foo, #bar") after pseudos and attrs
       
 20856             // to avoid replacing unescaped chars
       
 20857             selector = Y.Selector._replaceShorthand(selector);
       
 20858 
       
 20859             selector = Y.Selector._restore('attr', selector, replaced.attrs);
       
 20860             selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
       
 20861 
       
 20862             // replace braces and parens before restoring escaped chars
       
 20863             // to avoid replacing ecaped markers
       
 20864             selector = Y.Selector._replaceMarkers(selector);
       
 20865             selector = Y.Selector._restore('esc', selector, replaced.esc);
       
 20866 
       
 20867             return selector;
       
 20868         },
       
 20869 
       
 20870         _attrFilters: {
       
 20871             'class': 'className',
       
 20872             'for': 'htmlFor'
       
 20873         },
       
 20874 
       
 20875         getters: {
       
 20876             href: function(node, attr) {
       
 20877                 return Y.DOM.getAttribute(node, attr);
       
 20878             },
       
 20879 
       
 20880             id: function(node, attr) {
       
 20881                 return Y.DOM.getId(node);
       
 20882             }
       
 20883         }
       
 20884     };
       
 20885 
       
 20886 Y.mix(Y.Selector, SelectorCSS2, true);
       
 20887 Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
       
 20888 
       
 20889 // IE wants class with native queries
       
 20890 if (Y.Selector.useNative && Y.config.doc.querySelector) {
       
 20891     Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
       
 20892 }
       
 20893 
       
 20894 
       
 20895 
       
 20896 }, '@VERSION@', {"requires": ["selector-native"]});
       
 20897 YUI.add('selector-css3', function (Y, NAME) {
       
 20898 
       
 20899 /**
       
 20900  * The selector css3 module provides support for css3 selectors.
       
 20901  * @module dom
       
 20902  * @submodule selector-css3
       
 20903  * @for Selector
       
 20904  */
       
 20905 
       
 20906 /*
       
 20907     an+b = get every _a_th node starting at the _b_th
       
 20908     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
       
 20909     1n+b =  get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
       
 20910     an+0 = get every _a_th element, "0" may be omitted 
       
 20911 */
       
 20912 
       
 20913 Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
       
 20914 
       
 20915 Y.Selector._getNth = function(node, expr, tag, reverse) {
       
 20916     Y.Selector._reNth.test(expr);
       
 20917     var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
       
 20918         n = RegExp.$2, // "n"
       
 20919         oddeven = RegExp.$3, // "odd" or "even"
       
 20920         b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
       
 20921         result = [],
       
 20922         siblings = Y.DOM._children(node.parentNode, tag),
       
 20923         op;
       
 20924 
       
 20925     if (oddeven) {
       
 20926         a = 2; // always every other
       
 20927         op = '+';
       
 20928         n = 'n';
       
 20929         b = (oddeven === 'odd') ? 1 : 0;
       
 20930     } else if ( isNaN(a) ) {
       
 20931         a = (n) ? 1 : 0; // start from the first or no repeat
       
 20932     }
       
 20933 
       
 20934     if (a === 0) { // just the first
       
 20935         if (reverse) {
       
 20936             b = siblings.length - b + 1; 
       
 20937         }
       
 20938 
       
 20939         if (siblings[b - 1] === node) {
       
 20940             return true;
       
 20941         } else {
       
 20942             return false;
       
 20943         }
       
 20944 
       
 20945     } else if (a < 0) {
       
 20946         reverse = !!reverse;
       
 20947         a = Math.abs(a);
       
 20948     }
       
 20949 
       
 20950     if (!reverse) {
       
 20951         for (var i = b - 1, len = siblings.length; i < len; i += a) {
       
 20952             if ( i >= 0 && siblings[i] === node ) {
       
 20953                 return true;
       
 20954             }
       
 20955         }
       
 20956     } else {
       
 20957         for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
       
 20958             if ( i < len && siblings[i] === node ) {
       
 20959                 return true;
       
 20960             }
       
 20961         }
       
 20962     }
       
 20963     return false;
       
 20964 };
       
 20965 
       
 20966 Y.mix(Y.Selector.pseudos, {
       
 20967     'root': function(node) {
       
 20968         return node === node.ownerDocument.documentElement;
       
 20969     },
       
 20970 
       
 20971     'nth-child': function(node, expr) {
       
 20972         return Y.Selector._getNth(node, expr);
       
 20973     },
       
 20974 
       
 20975     'nth-last-child': function(node, expr) {
       
 20976         return Y.Selector._getNth(node, expr, null, true);
       
 20977     },
       
 20978 
       
 20979     'nth-of-type': function(node, expr) {
       
 20980         return Y.Selector._getNth(node, expr, node.tagName);
       
 20981     },
       
 20982      
       
 20983     'nth-last-of-type': function(node, expr) {
       
 20984         return Y.Selector._getNth(node, expr, node.tagName, true);
       
 20985     },
       
 20986      
       
 20987     'last-child': function(node) {
       
 20988         var children = Y.DOM._children(node.parentNode);
       
 20989         return children[children.length - 1] === node;
       
 20990     },
       
 20991 
       
 20992     'first-of-type': function(node) {
       
 20993         return Y.DOM._children(node.parentNode, node.tagName)[0] === node;
       
 20994     },
       
 20995      
       
 20996     'last-of-type': function(node) {
       
 20997         var children = Y.DOM._children(node.parentNode, node.tagName);
       
 20998         return children[children.length - 1] === node;
       
 20999     },
       
 21000      
       
 21001     'only-child': function(node) {
       
 21002         var children = Y.DOM._children(node.parentNode);
       
 21003         return children.length === 1 && children[0] === node;
       
 21004     },
       
 21005 
       
 21006     'only-of-type': function(node) {
       
 21007         var children = Y.DOM._children(node.parentNode, node.tagName);
       
 21008         return children.length === 1 && children[0] === node;
       
 21009     },
       
 21010 
       
 21011     'empty': function(node) {
       
 21012         return node.childNodes.length === 0;
       
 21013     },
       
 21014 
       
 21015     'not': function(node, expr) {
       
 21016         return !Y.Selector.test(node, expr);
       
 21017     },
       
 21018 
       
 21019     'contains': function(node, expr) {
       
 21020         var text = node.innerText || node.textContent || '';
       
 21021         return text.indexOf(expr) > -1;
       
 21022     },
       
 21023 
       
 21024     'checked': function(node) {
       
 21025         return (node.checked === true || node.selected === true);
       
 21026     },
       
 21027 
       
 21028     enabled: function(node) {
       
 21029         return (node.disabled !== undefined && !node.disabled);
       
 21030     },
       
 21031 
       
 21032     disabled: function(node) {
       
 21033         return (node.disabled);
       
 21034     }
       
 21035 });
       
 21036 
       
 21037 Y.mix(Y.Selector.operators, {
       
 21038     '^=': '^{val}', // Match starts with value
       
 21039     '$=': '{val}$', // Match ends with value
       
 21040     '*=': '{val}' // Match contains value as substring 
       
 21041 });
       
 21042 
       
 21043 Y.Selector.combinators['~'] = {
       
 21044     axis: 'previousSibling'
       
 21045 };
       
 21046 
       
 21047 
       
 21048 }, '@VERSION@', {"requires": ["selector-native", "selector-css2"]});
       
 21049 YUI.add('yui-log', function (Y, NAME) {
       
 21050 
       
 21051 /**
       
 21052  * Provides console log capability and exposes a custom event for
       
 21053  * console implementations. This module is a `core` YUI module,
       
 21054  * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
       
 21055  *
       
 21056  * @module yui
       
 21057  * @submodule yui-log
       
 21058  */
       
 21059 
       
 21060 var INSTANCE = Y,
       
 21061     LOGEVENT = 'yui:log',
       
 21062     UNDEFINED = 'undefined',
       
 21063     LEVELS = { debug: 1,
       
 21064                info: 2,
       
 21065                warn: 4,
       
 21066                error: 8 };
       
 21067 
       
 21068 /**
       
 21069  * If the 'debug' config is true, a 'yui:log' event will be
       
 21070  * dispatched, which the Console widget and anything else
       
 21071  * can consume.  If the 'useBrowserConsole' config is true, it will
       
 21072  * write to the browser console if available.  YUI-specific log
       
 21073  * messages will only be present in the -debug versions of the
       
 21074  * JS files.  The build system is supposed to remove log statements
       
 21075  * from the raw and minified versions of the files.
       
 21076  *
       
 21077  * @method log
       
 21078  * @for YUI
       
 21079  * @param  {String}  msg  The message to log.
       
 21080  * @param  {String}  cat  The log category for the message.  Default
       
 21081  *                        categories are "info", "warn", "error", time".
       
 21082  *                        Custom categories can be used as well. (opt).
       
 21083  * @param  {String}  src  The source of the the message (opt).
       
 21084  * @param  {boolean} silent If true, the log event won't fire.
       
 21085  * @return {YUI}      YUI instance.
       
 21086  */
       
 21087 INSTANCE.log = function(msg, cat, src, silent) {
       
 21088     var bail, excl, incl, m, f, minlevel,
       
 21089         Y = INSTANCE,
       
 21090         c = Y.config,
       
 21091         publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
       
 21092     // suppress log message if the config is off or the event stack
       
 21093     // or the event call stack contains a consumer of the yui:log event
       
 21094     if (c.debug) {
       
 21095         // apply source filters
       
 21096         src = src || "";
       
 21097         if (typeof src !== "undefined") {
       
 21098             excl = c.logExclude;
       
 21099             incl = c.logInclude;
       
 21100             if (incl && !(src in incl)) {
       
 21101                 bail = 1;
       
 21102             } else if (incl && (src in incl)) {
       
 21103                 bail = !incl[src];
       
 21104             } else if (excl && (src in excl)) {
       
 21105                 bail = excl[src];
       
 21106             }
       
 21107 
       
 21108             // Determine the current minlevel as defined in configuration
       
 21109             Y.config.logLevel = Y.config.logLevel || 'debug';
       
 21110             minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
       
 21111 
       
 21112             if (cat in LEVELS && LEVELS[cat] < minlevel) {
       
 21113                 // Skip this message if the we don't meet the defined minlevel
       
 21114                 bail = 1;
       
 21115             }
       
 21116         }
       
 21117         if (!bail) {
       
 21118             if (c.useBrowserConsole) {
       
 21119                 m = (src) ? src + ': ' + msg : msg;
       
 21120                 if (Y.Lang.isFunction(c.logFn)) {
       
 21121                     c.logFn.call(Y, msg, cat, src);
       
 21122                 } else if (typeof console !== UNDEFINED && console.log) {
       
 21123                     f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
       
 21124                     console[f](m);
       
 21125                 } else if (typeof opera !== UNDEFINED) {
       
 21126                     opera.postError(m);
       
 21127                 }
       
 21128             }
       
 21129 
       
 21130             if (publisher && !silent) {
       
 21131 
       
 21132                 if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
       
 21133                     publisher.publish(LOGEVENT, {
       
 21134                         broadcast: 2
       
 21135                     });
       
 21136                 }
       
 21137 
       
 21138                 publisher.fire(LOGEVENT, {
       
 21139                     msg: msg,
       
 21140                     cat: cat,
       
 21141                     src: src
       
 21142                 });
       
 21143             }
       
 21144         }
       
 21145     }
       
 21146 
       
 21147     return Y;
       
 21148 };
       
 21149 
       
 21150 /**
       
 21151  * Write a system message.  This message will be preserved in the
       
 21152  * minified and raw versions of the YUI files, unlike log statements.
       
 21153  * @method message
       
 21154  * @for YUI
       
 21155  * @param  {String}  msg  The message to log.
       
 21156  * @param  {String}  cat  The log category for the message.  Default
       
 21157  *                        categories are "info", "warn", "error", time".
       
 21158  *                        Custom categories can be used as well. (opt).
       
 21159  * @param  {String}  src  The source of the the message (opt).
       
 21160  * @param  {boolean} silent If true, the log event won't fire.
       
 21161  * @return {YUI}      YUI instance.
       
 21162  */
       
 21163 INSTANCE.message = function() {
       
 21164     return INSTANCE.log.apply(INSTANCE, arguments);
       
 21165 };
       
 21166 
       
 21167 
       
 21168 }, '@VERSION@', {"requires": ["yui-base"]});
       
 21169 YUI.add('dump', function (Y, NAME) {
       
 21170 
       
 21171 /**
       
 21172  * Returns a simple string representation of the object or array.
       
 21173  * Other types of objects will be returned unprocessed.  Arrays
       
 21174  * are expected to be indexed.  Use object notation for
       
 21175  * associative arrays.
       
 21176  *
       
 21177  * If included, the dump method is added to the YUI instance.
       
 21178  *
       
 21179  * @module dump
       
 21180  */
       
 21181 
       
 21182     var L = Y.Lang,
       
 21183         OBJ = '{...}',
       
 21184         FUN = 'f(){...}',
       
 21185         COMMA = ', ',
       
 21186         ARROW = ' => ',
       
 21187 
       
 21188     /**
       
 21189      * Returns a simple string representation of the object or array.
       
 21190      * Other types of objects will be returned unprocessed.  Arrays
       
 21191      * are expected to be indexed.
       
 21192      *
       
 21193      * @method dump
       
 21194      * @param {Object} o The object to dump.
       
 21195      * @param {Number} d How deep to recurse child objects, default 3.
       
 21196      * @return {String} the dump result.
       
 21197      * @for YUI
       
 21198      */
       
 21199     dump = function(o, d) {
       
 21200         var i, len, s = [], type = L.type(o);
       
 21201 
       
 21202         // Cast non-objects to string
       
 21203         // Skip dates because the std toString is what we want
       
 21204         // Skip HTMLElement-like objects because trying to dump
       
 21205         // an element will cause an unhandled exception in FF 2.x
       
 21206         if (!L.isObject(o)) {
       
 21207             return o + '';
       
 21208         } else if (type == 'date') {
       
 21209             return o;
       
 21210         } else if (o.nodeType && o.tagName) {
       
 21211             return o.tagName + '#' + o.id;
       
 21212         } else if (o.document && o.navigator) {
       
 21213             return 'window';
       
 21214         } else if (o.location && o.body) {
       
 21215             return 'document';
       
 21216         } else if (type == 'function') {
       
 21217             return FUN;
       
 21218         }
       
 21219 
       
 21220         // dig into child objects the depth specifed. Default 3
       
 21221         d = (L.isNumber(d)) ? d : 3;
       
 21222 
       
 21223         // arrays [1, 2, 3]
       
 21224         if (type == 'array') {
       
 21225             s.push('[');
       
 21226             for (i = 0, len = o.length; i < len; i = i + 1) {
       
 21227                 if (L.isObject(o[i])) {
       
 21228                     s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
       
 21229                 } else {
       
 21230                     s.push(o[i]);
       
 21231                 }
       
 21232                 s.push(COMMA);
       
 21233             }
       
 21234             if (s.length > 1) {
       
 21235                 s.pop();
       
 21236             }
       
 21237             s.push(']');
       
 21238         // regexp /foo/
       
 21239         } else if (type == 'regexp') {
       
 21240             s.push(o.toString());
       
 21241         // objects {k1 => v1, k2 => v2}
       
 21242         } else {
       
 21243             s.push('{');
       
 21244             for (i in o) {
       
 21245                 if (o.hasOwnProperty(i)) {
       
 21246                     try {
       
 21247                         s.push(i + ARROW);
       
 21248                         if (L.isObject(o[i])) {
       
 21249                             s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
       
 21250                         } else {
       
 21251                             s.push(o[i]);
       
 21252                         }
       
 21253                         s.push(COMMA);
       
 21254                     } catch (e) {
       
 21255                         s.push('Error: ' + e.message);
       
 21256                     }
       
 21257                 }
       
 21258             }
       
 21259             if (s.length > 1) {
       
 21260                 s.pop();
       
 21261             }
       
 21262             s.push('}');
       
 21263         }
       
 21264 
       
 21265         return s.join('');
       
 21266     };
       
 21267 
       
 21268     Y.dump = dump;
       
 21269     L.dump = dump;
       
 21270 
       
 21271 
       
 21272 
       
 21273 }, '@VERSION@', {"requires": ["yui-base"]});
       
 21274 YUI.add('transition-timer', function (Y, NAME) {
       
 21275 
       
 21276 /**
       
 21277 * Provides the base Transition class, for animating numeric properties.
       
 21278 *
       
 21279 * @module transition
       
 21280 * @submodule transition-timer
       
 21281 */
       
 21282 
       
 21283 
       
 21284 var Transition = Y.Transition;
       
 21285 
       
 21286 Y.mix(Transition.prototype, {
       
 21287     _start: function() {
       
 21288         if (Transition.useNative) {
       
 21289             this._runNative();
       
 21290         } else {
       
 21291             this._runTimer();
       
 21292         }
       
 21293     },
       
 21294 
       
 21295     _runTimer: function() {
       
 21296         var anim = this;
       
 21297         anim._initAttrs();
       
 21298 
       
 21299         Transition._running[Y.stamp(anim)] = anim;
       
 21300         anim._startTime = new Date();
       
 21301         Transition._startTimer();
       
 21302     },
       
 21303 
       
 21304     _endTimer: function() {
       
 21305         var anim = this;
       
 21306         delete Transition._running[Y.stamp(anim)];
       
 21307         anim._startTime = null;
       
 21308     },
       
 21309 
       
 21310     _runFrame: function() {
       
 21311         var t = new Date() - this._startTime;
       
 21312         this._runAttrs(t);
       
 21313     },
       
 21314 
       
 21315     _runAttrs: function(time) {
       
 21316         var anim = this,
       
 21317             node = anim._node,
       
 21318             config = anim._config,
       
 21319             uid = Y.stamp(node),
       
 21320             attrs = Transition._nodeAttrs[uid],
       
 21321             customAttr = Transition.behaviors,
       
 21322             done = false,
       
 21323             allDone = false,
       
 21324             data,
       
 21325             name,
       
 21326             attribute,
       
 21327             setter,
       
 21328             elapsed,
       
 21329             delay,
       
 21330             d,
       
 21331             t,
       
 21332             i;
       
 21333 
       
 21334         for (name in attrs) {
       
 21335             if ((attribute = attrs[name]) && attribute.transition === anim) {
       
 21336                 d = attribute.duration;
       
 21337                 delay = attribute.delay;
       
 21338                 elapsed = (time - delay) / 1000;
       
 21339                 t = time;
       
 21340                 data = {
       
 21341                     type: 'propertyEnd',
       
 21342                     propertyName: name,
       
 21343                     config: config,
       
 21344                     elapsedTime: elapsed
       
 21345                 };
       
 21346 
       
 21347                 setter = (i in customAttr && 'set' in customAttr[i]) ?
       
 21348                         customAttr[i].set : Transition.DEFAULT_SETTER;
       
 21349 
       
 21350                 done = (t >= d);
       
 21351 
       
 21352                 if (t > d) {
       
 21353                     t = d;
       
 21354                 }
       
 21355 
       
 21356                 if (!delay || time >= delay) {
       
 21357                     setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
       
 21358                         attribute.easing, attribute.unit);
       
 21359 
       
 21360                     if (done) {
       
 21361                         delete attrs[name];
       
 21362                         anim._count--;
       
 21363 
       
 21364                         if (config[name] && config[name].on && config[name].on.end) {
       
 21365                             config[name].on.end.call(Y.one(node), data);
       
 21366                         }
       
 21367 
       
 21368                         //node.fire('transition:propertyEnd', data);
       
 21369 
       
 21370                         if (!allDone && anim._count <= 0) {
       
 21371                             allDone = true;
       
 21372                             anim._end(elapsed);
       
 21373                             anim._endTimer();
       
 21374                         }
       
 21375                     }
       
 21376                 }
       
 21377 
       
 21378             }
       
 21379         }
       
 21380     },
       
 21381 
       
 21382     _initAttrs: function() {
       
 21383         var anim = this,
       
 21384             customAttr = Transition.behaviors,
       
 21385             uid = Y.stamp(anim._node),
       
 21386             attrs = Transition._nodeAttrs[uid],
       
 21387             attribute,
       
 21388             duration,
       
 21389             delay,
       
 21390             easing,
       
 21391             val,
       
 21392             name,
       
 21393             mTo,
       
 21394             mFrom,
       
 21395             unit, begin, end;
       
 21396 
       
 21397         for (name in attrs) {
       
 21398             if ((attribute = attrs[name]) && attribute.transition === anim) {
       
 21399                 duration = attribute.duration * 1000;
       
 21400                 delay = attribute.delay * 1000;
       
 21401                 easing = attribute.easing;
       
 21402                 val = attribute.value;
       
 21403 
       
 21404                 // only allow supported properties
       
 21405                 if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
       
 21406                     begin = (name in customAttr && 'get' in customAttr[name])  ?
       
 21407                             customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
       
 21408 
       
 21409                     mFrom = Transition.RE_UNITS.exec(begin);
       
 21410                     mTo = Transition.RE_UNITS.exec(val);
       
 21411 
       
 21412                     begin = mFrom ? mFrom[1] : begin;
       
 21413                     end = mTo ? mTo[1] : val;
       
 21414                     unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
       
 21415 
       
 21416                     if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
       
 21417                         unit = Transition.DEFAULT_UNIT;
       
 21418                     }
       
 21419 
       
 21420                     if (typeof easing === 'string') {
       
 21421                         if (easing.indexOf('cubic-bezier') > -1) {
       
 21422                             easing = easing.substring(13, easing.length - 1).split(',');
       
 21423                         } else if (Transition.easings[easing]) {
       
 21424                             easing = Transition.easings[easing];
       
 21425                         }
       
 21426                     }
       
 21427 
       
 21428                     attribute.from = Number(begin);
       
 21429                     attribute.to = Number(end);
       
 21430                     attribute.unit = unit;
       
 21431                     attribute.easing = easing;
       
 21432                     attribute.duration = duration + delay;
       
 21433                     attribute.delay = delay;
       
 21434                 } else {
       
 21435                     delete attrs[name];
       
 21436                     anim._count--;
       
 21437                 }
       
 21438             }
       
 21439         }
       
 21440     },
       
 21441 
       
 21442     destroy: function() {
       
 21443         this.detachAll();
       
 21444         this._node = null;
       
 21445     }
       
 21446 }, true);
       
 21447 
       
 21448 Y.mix(Y.Transition, {
       
 21449     _runtimeAttrs: {},
       
 21450     /*
       
 21451      * Regex of properties that should use the default unit.
       
 21452      *
       
 21453      * @property RE_DEFAULT_UNIT
       
 21454      * @static
       
 21455      */
       
 21456     RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
       
 21457 
       
 21458     /*
       
 21459      * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
       
 21460      *
       
 21461      * @property DEFAULT_UNIT
       
 21462      * @static
       
 21463      */
       
 21464     DEFAULT_UNIT: 'px',
       
 21465 
       
 21466     /*
       
 21467      * Time in milliseconds passed to setInterval for frame processing
       
 21468      *
       
 21469      * @property intervalTime
       
 21470      * @default 20
       
 21471      * @static
       
 21472      */
       
 21473     intervalTime: 20,
       
 21474 
       
 21475     /*
       
 21476      * Bucket for custom getters and setters
       
 21477      *
       
 21478      * @property behaviors
       
 21479      * @static
       
 21480      */
       
 21481     behaviors: {
       
 21482         left: {
       
 21483             get: function(anim, attr) {
       
 21484                 return Y.DOM._getAttrOffset(anim._node, attr);
       
 21485             }
       
 21486         }
       
 21487     },
       
 21488 
       
 21489     /*
       
 21490      * The default setter to use when setting object properties.
       
 21491      *
       
 21492      * @property DEFAULT_SETTER
       
 21493      * @static
       
 21494      */
       
 21495     DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
       
 21496         from = Number(from);
       
 21497         to = Number(to);
       
 21498 
       
 21499         var node = anim._node,
       
 21500             val = Transition.cubicBezier(fn, elapsed / duration);
       
 21501 
       
 21502         val = from + val[0] * (to - from);
       
 21503 
       
 21504         if (node) {
       
 21505             if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
       
 21506                 unit = unit || '';
       
 21507                 Y.DOM.setStyle(node, att, val + unit);
       
 21508             }
       
 21509         } else {
       
 21510             anim._end();
       
 21511         }
       
 21512     },
       
 21513 
       
 21514     /*
       
 21515      * The default getter to use when getting object properties.
       
 21516      *
       
 21517      * @property DEFAULT_GETTER
       
 21518      * @static
       
 21519      */
       
 21520     DEFAULT_GETTER: function(anim, att) {
       
 21521         var node = anim._node,
       
 21522             val = '';
       
 21523 
       
 21524         if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
       
 21525             val = Y.DOM.getComputedStyle(node, att);
       
 21526         }
       
 21527 
       
 21528         return val;
       
 21529     },
       
 21530 
       
 21531     _startTimer: function() {
       
 21532         if (!Transition._timer) {
       
 21533             Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
       
 21534         }
       
 21535     },
       
 21536 
       
 21537     _stopTimer: function() {
       
 21538         clearInterval(Transition._timer);
       
 21539         Transition._timer = null;
       
 21540     },
       
 21541 
       
 21542     /*
       
 21543      * Called per Interval to handle each animation frame.
       
 21544      * @method _runFrame
       
 21545      * @private
       
 21546      * @static
       
 21547      */
       
 21548     _runFrame: function() {
       
 21549         var done = true,
       
 21550             anim;
       
 21551         for (anim in Transition._running) {
       
 21552             if (Transition._running[anim]._runFrame) {
       
 21553                 done = false;
       
 21554                 Transition._running[anim]._runFrame();
       
 21555             }
       
 21556         }
       
 21557 
       
 21558         if (done) {
       
 21559             Transition._stopTimer();
       
 21560         }
       
 21561     },
       
 21562 
       
 21563     cubicBezier: function(p, t) {
       
 21564         var x0 = 0,
       
 21565             y0 = 0,
       
 21566             x1 = p[0],
       
 21567             y1 = p[1],
       
 21568             x2 = p[2],
       
 21569             y2 = p[3],
       
 21570             x3 = 1,
       
 21571             y3 = 0,
       
 21572 
       
 21573             A = x3 - 3 * x2 + 3 * x1 - x0,
       
 21574             B = 3 * x2 - 6 * x1 + 3 * x0,
       
 21575             C = 3 * x1 - 3 * x0,
       
 21576             D = x0,
       
 21577             E = y3 - 3 * y2 + 3 * y1 - y0,
       
 21578             F = 3 * y2 - 6 * y1 + 3 * y0,
       
 21579             G = 3 * y1 - 3 * y0,
       
 21580             H = y0,
       
 21581 
       
 21582             x = (((A*t) + B)*t + C)*t + D,
       
 21583             y = (((E*t) + F)*t + G)*t + H;
       
 21584 
       
 21585         return [x, y];
       
 21586     },
       
 21587 
       
 21588     easings: {
       
 21589         ease: [0.25, 0, 1, 0.25],
       
 21590         linear: [0, 0, 1, 1],
       
 21591         'ease-in': [0.42, 0, 1, 1],
       
 21592         'ease-out': [0, 0, 0.58, 1],
       
 21593         'ease-in-out': [0.42, 0, 0.58, 1]
       
 21594     },
       
 21595 
       
 21596     _running: {},
       
 21597     _timer: null,
       
 21598 
       
 21599     RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
       
 21600 }, true);
       
 21601 
       
 21602 Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
       
 21603 
       
 21604 Y.Transition = Transition;
       
 21605 
       
 21606 
       
 21607 }, '@VERSION@', {"requires": ["transition"]});
       
 21608 YUI.add('yui', function (Y, NAME) {
       
 21609 
       
 21610 // empty
       
 21611 
       
 21612 
       
 21613 
       
 21614 }, '@VERSION@', {
       
 21615     "use": [
       
 21616         "yui",
       
 21617         "oop",
       
 21618         "dom",
       
 21619         "event-custom-base",
       
 21620         "event-base",
       
 21621         "pluginhost",
       
 21622         "node",
       
 21623         "event-delegate",
       
 21624         "io-base",
       
 21625         "json-parse",
       
 21626         "transition",
       
 21627         "selector-css3",
       
 21628         "dom-style-ie",
       
 21629         "querystring-stringify-simple"
       
 21630     ]
       
 21631 });
       
 21632 var Y = YUI().use('*');