~ubuntu-branches/ubuntu/precise/maas/precise-updates

« back to all changes in this revision

Viewing changes to src/maasserver/static/jslibs/yui/3.4.1/build/simpleyui/simpleyui-debug.js

Tags: 1.2+bzr1373+dfsg-0ubuntu1~12.04.4
* SECURITY UPDATE: failure to authenticate downloaded content (LP: #1039513)
  - debian/patches/CVE-2013-1058.patch: Authenticate downloaded files with
    GnuPG and MD5SUM files. Thanks to Julian Edwards.
  - CVE-2013-1058
* SECURITY UPDATE: configuration options may be loaded from current working
  directory (LP: #1158425)
  - debian/patches/CVE-2013-1057-1-2.patch: Do not load configuration
    options from the current working directory. Thanks to Julian Edwards.
  - CVE-2013-1057

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
YUI 3.4.1 (build 4118)
3
 
Copyright 2011 Yahoo! Inc. All rights reserved.
4
 
Licensed under the BSD License.
5
 
http://yuilibrary.com/license/
6
 
*/
7
 
/**
8
 
 * The YUI module contains the components required for building the YUI seed
9
 
 * file.  This includes the script loading mechanism, a simple queue, and
10
 
 * the core utilities for the library.
11
 
 * @module yui
12
 
 * @submodule yui-base
13
 
 */
14
 
 
15
 
if (typeof YUI != 'undefined') {
16
 
    YUI._YUI = YUI;
17
 
}
18
 
 
19
 
/**
20
 
 * The YUI global namespace object.  If YUI is already defined, the
21
 
 * existing YUI object will not be overwritten so that defined
22
 
 * namespaces are preserved.  It is the constructor for the object
23
 
 * the end user interacts with.  As indicated below, each instance
24
 
 * has full custom event support, but only if the event system
25
 
 * is available.  This is a self-instantiable factory function.  You
26
 
 * can invoke it directly like this:
27
 
 *
28
 
 *      YUI().use('*', function(Y) {
29
 
 *          // ready
30
 
 *      });
31
 
 *
32
 
 * But it also works like this:
33
 
 *
34
 
 *      var Y = YUI();
35
 
 *
36
 
 * @class YUI
37
 
 * @constructor
38
 
 * @global
39
 
 * @uses EventTarget
40
 
 * @param o* {object} 0..n optional configuration objects.  these values
41
 
 * are store in Y.config.  See <a href="config.html">Config</a> for the list of supported
42
 
 * properties.
43
 
 */
44
 
    /*global YUI*/
45
 
    /*global YUI_config*/
46
 
    var YUI = function() {
47
 
        var i = 0,
48
 
            Y = this,
49
 
            args = arguments,
50
 
            l = args.length,
51
 
            instanceOf = function(o, type) {
52
 
                return (o && o.hasOwnProperty && (o instanceof type));
53
 
            },
54
 
            gconf = (typeof YUI_config !== 'undefined') && YUI_config;
55
 
 
56
 
        if (!(instanceOf(Y, YUI))) {
57
 
            Y = new YUI();
58
 
        } else {
59
 
            // set up the core environment
60
 
            Y._init();
61
 
 
62
 
            // YUI.GlobalConfig is a master configuration that might span
63
 
            // multiple contexts in a non-browser environment.  It is applied
64
 
            // first to all instances in all contexts.
65
 
            if (YUI.GlobalConfig) {
66
 
                Y.applyConfig(YUI.GlobalConfig);
67
 
            }
68
 
 
69
 
            // YUI_Config is a page-level config.  It is applied to all
70
 
            // instances created on the page.  This is applied after
71
 
            // YUI.GlobalConfig, and before the instance level configuration
72
 
            // objects.
73
 
            if (gconf) {
74
 
                Y.applyConfig(gconf);
75
 
            }
76
 
 
77
 
            // bind the specified additional modules for this instance
78
 
            if (!l) {
79
 
                Y._setup();
80
 
            }
81
 
        }
82
 
 
83
 
        if (l) {
84
 
            // Each instance can accept one or more configuration objects.
85
 
            // These are applied after YUI.GlobalConfig and YUI_Config,
86
 
            // overriding values set in those config files if there is a '
87
 
            // matching property.
88
 
            for (; i < l; i++) {
89
 
                Y.applyConfig(args[i]);
90
 
            }
91
 
 
92
 
            Y._setup();
93
 
        }
94
 
 
95
 
        Y.instanceOf = instanceOf;
96
 
 
97
 
        return Y;
98
 
    };
99
 
 
100
 
(function() {
101
 
 
102
 
    var proto, prop,
103
 
        VERSION = '3.4.1',
104
 
        PERIOD = '.',
105
 
        BASE = 'http://yui.yahooapis.com/',
106
 
        DOC_LABEL = 'yui3-js-enabled',
107
 
        NOOP = function() {},
108
 
        SLICE = Array.prototype.slice,
109
 
        APPLY_TO_AUTH = { 'io.xdrReady': 1,   // the functions applyTo
110
 
                          'io.xdrResponse': 1,   // can call. this should
111
 
                          'SWF.eventHandler': 1 }, // be done at build time
112
 
        hasWin = (typeof window != 'undefined'),
113
 
        win = (hasWin) ? window : null,
114
 
        doc = (hasWin) ? win.document : null,
115
 
        docEl = doc && doc.documentElement,
116
 
        docClass = docEl && docEl.className,
117
 
        instances = {},
118
 
        time = new Date().getTime(),
119
 
        add = function(el, type, fn, capture) {
120
 
            if (el && el.addEventListener) {
121
 
                el.addEventListener(type, fn, capture);
122
 
            } else if (el && el.attachEvent) {
123
 
                el.attachEvent('on' + type, fn);
124
 
            }
125
 
        },
126
 
        remove = function(el, type, fn, capture) {
127
 
            if (el && el.removeEventListener) {
128
 
                // this can throw an uncaught exception in FF
129
 
                try {
130
 
                    el.removeEventListener(type, fn, capture);
131
 
                } catch (ex) {}
132
 
            } else if (el && el.detachEvent) {
133
 
                el.detachEvent('on' + type, fn);
134
 
            }
135
 
        },
136
 
        handleLoad = function() {
137
 
            YUI.Env.windowLoaded = true;
138
 
            YUI.Env.DOMReady = true;
139
 
            if (hasWin) {
140
 
                remove(window, 'load', handleLoad);
141
 
            }
142
 
        },
143
 
        getLoader = function(Y, o) {
144
 
            var loader = Y.Env._loader;
145
 
            if (loader) {
146
 
                //loader._config(Y.config);
147
 
                loader.ignoreRegistered = false;
148
 
                loader.onEnd = null;
149
 
                loader.data = null;
150
 
                loader.required = [];
151
 
                loader.loadType = null;
152
 
            } else {
153
 
                loader = new Y.Loader(Y.config);
154
 
                Y.Env._loader = loader;
155
 
            }
156
 
 
157
 
            return loader;
158
 
        },
159
 
 
160
 
        clobber = function(r, s) {
161
 
            for (var i in s) {
162
 
                if (s.hasOwnProperty(i)) {
163
 
                    r[i] = s[i];
164
 
                }
165
 
            }
166
 
        },
167
 
 
168
 
        ALREADY_DONE = { success: true };
169
 
 
170
 
//  Stamp the documentElement (HTML) with a class of "yui-loaded" to
171
 
//  enable styles that need to key off of JS being enabled.
172
 
if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
173
 
    if (docClass) {
174
 
        docClass += ' ';
175
 
    }
176
 
    docClass += DOC_LABEL;
177
 
    docEl.className = docClass;
178
 
}
179
 
 
180
 
if (VERSION.indexOf('@') > -1) {
181
 
    VERSION = '3.3.0'; // dev time hack for cdn test
182
 
}
183
 
 
184
 
proto = {
185
 
    /**
186
 
     * Applies a new configuration object to the YUI instance config.
187
 
     * This will merge new group/module definitions, and will also
188
 
     * update the loader cache if necessary.  Updating Y.config directly
189
 
     * will not update the cache.
190
 
     * @method applyConfig
191
 
     * @param {object} the configuration object.
192
 
     * @since 3.2.0
193
 
     */
194
 
    applyConfig: function(o) {
195
 
 
196
 
        o = o || NOOP;
197
 
 
198
 
        var attr,
199
 
            name,
200
 
            // detail,
201
 
            config = this.config,
202
 
            mods = config.modules,
203
 
            groups = config.groups,
204
 
            rls = config.rls,
205
 
            loader = this.Env._loader;
206
 
 
207
 
        for (name in o) {
208
 
            if (o.hasOwnProperty(name)) {
209
 
                attr = o[name];
210
 
                if (mods && name == 'modules') {
211
 
                    clobber(mods, attr);
212
 
                } else if (groups && name == 'groups') {
213
 
                    clobber(groups, attr);
214
 
                } else if (rls && name == 'rls') {
215
 
                    clobber(rls, attr);
216
 
                } else if (name == 'win') {
217
 
                    config[name] = attr.contentWindow || attr;
218
 
                    config.doc = config[name].document;
219
 
                } else if (name == '_yuid') {
220
 
                    // preserve the guid
221
 
                } else {
222
 
                    config[name] = attr;
223
 
                }
224
 
            }
225
 
        }
226
 
 
227
 
        if (loader) {
228
 
            loader._config(o);
229
 
        }
230
 
    },
231
 
    /**
232
 
    * Old way to apply a config to the instance (calls `applyConfig` under the hood)
233
 
    * @private
234
 
    * @method _config
235
 
    * @param {Object} o The config to apply
236
 
    */
237
 
    _config: function(o) {
238
 
        this.applyConfig(o);
239
 
    },
240
 
 
241
 
    /**
242
 
     * Initialize this YUI instance
243
 
     * @private
244
 
     * @method _init
245
 
     */
246
 
    _init: function() {
247
 
        var filter,
248
 
            Y = this,
249
 
            G_ENV = YUI.Env,
250
 
            Env = Y.Env,
251
 
            prop;
252
 
 
253
 
        /**
254
 
         * The version number of the YUI instance.
255
 
         * @property version
256
 
         * @type string
257
 
         */
258
 
        Y.version = VERSION;
259
 
 
260
 
        if (!Env) {
261
 
            Y.Env = {
262
 
                mods: {}, // flat module map
263
 
                versions: {}, // version module map
264
 
                base: BASE,
265
 
                cdn: BASE + VERSION + '/build/',
266
 
                // bootstrapped: false,
267
 
                _idx: 0,
268
 
                _used: {},
269
 
                _attached: {},
270
 
                _missed: [],
271
 
                _yidx: 0,
272
 
                _uidx: 0,
273
 
                _guidp: 'y',
274
 
                _loaded: {},
275
 
                // serviced: {},
276
 
                // Regex in English:
277
 
                // I'll start at the \b(simpleyui).
278
 
                // 1. Look in the test string for "simpleyui" or "yui" or
279
 
                //    "yui-base" or "yui-rls" or "yui-foobar" that comes after a word break.  That is, it
280
 
                //    can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
281
 
                // 2. After #1 must come a forward slash followed by the string matched in #1, so
282
 
                //    "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
283
 
                // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
284
 
                //    so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
285
 
                // 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
286
 
                // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
287
 
                //    then capture the junk between the LAST "&" and the string in 1-4.  So
288
 
                //    "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-rls/yui-rls.js"
289
 
                //    will capture "3.3.0/build/"
290
 
                //
291
 
                // Regex Exploded:
292
 
                // (?:\?             Find a ?
293
 
                //   (?:[^&]*&)      followed by 0..n characters followed by an &
294
 
                //   *               in fact, find as many sets of characters followed by a & as you can
295
 
                //   ([^&]*)         capture the stuff after the last & in \1
296
 
                // )?                but it's ok if all this ?junk&more_junk stuff isn't even there
297
 
                // \b(simpleyui|     after a word break find either the string "simpleyui" or
298
 
                //    yui(?:-\w+)?   the string "yui" optionally followed by a -, then more characters
299
 
                // )                 and store the simpleyui or yui-* string in \2
300
 
                // \/\2              then comes a / followed by the simpleyui or yui-* string in \2
301
 
                // (?:-(min|debug))? optionally followed by "-min" or "-debug"
302
 
                // .js               and ending in ".js"
303
 
                _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
304
 
                parseBasePath: function(src, pattern) {
305
 
                    var match = src.match(pattern),
306
 
                        path, filter;
307
 
 
308
 
                    if (match) {
309
 
                        path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
310
 
 
311
 
                        // this is to set up the path to the loader.  The file
312
 
                        // filter for loader should match the yui include.
313
 
                        filter = match[3];
314
 
 
315
 
                        // extract correct path for mixed combo urls
316
 
                        // http://yuilibrary.com/projects/yui3/ticket/2528423
317
 
                        if (match[1]) {
318
 
                            path += '?' + match[1];
319
 
                        }
320
 
                        path = {
321
 
                            filter: filter,
322
 
                            path: path
323
 
                        }
324
 
                    }
325
 
                    return path;
326
 
                },
327
 
                getBase: G_ENV && G_ENV.getBase ||
328
 
                        function(pattern) {
329
 
                            var nodes = (doc && doc.getElementsByTagName('script')) || [],
330
 
                                path = Env.cdn, parsed,
331
 
                                i, len, src;
332
 
 
333
 
                            for (i = 0, len = nodes.length; i < len; ++i) {
334
 
                                src = nodes[i].src;
335
 
                                if (src) {
336
 
                                    parsed = Y.Env.parseBasePath(src, pattern);
337
 
                                    if (parsed) {
338
 
                                        filter = parsed.filter;
339
 
                                        path = parsed.path;
340
 
                                        break;
341
 
                                    }
342
 
                                }
343
 
                            }
344
 
 
345
 
                            // use CDN default
346
 
                            return path;
347
 
                        }
348
 
 
349
 
            };
350
 
 
351
 
            Env = Y.Env;
352
 
 
353
 
            Env._loaded[VERSION] = {};
354
 
 
355
 
            if (G_ENV && Y !== YUI) {
356
 
                Env._yidx = ++G_ENV._yidx;
357
 
                Env._guidp = ('yui_' + VERSION + '_' +
358
 
                             Env._yidx + '_' + time).replace(/\./g, '_');
359
 
            } else if (YUI._YUI) {
360
 
 
361
 
                G_ENV = YUI._YUI.Env;
362
 
                Env._yidx += G_ENV._yidx;
363
 
                Env._uidx += G_ENV._uidx;
364
 
 
365
 
                for (prop in G_ENV) {
366
 
                    if (!(prop in Env)) {
367
 
                        Env[prop] = G_ENV[prop];
368
 
                    }
369
 
                }
370
 
 
371
 
                delete YUI._YUI;
372
 
            }
373
 
 
374
 
            Y.id = Y.stamp(Y);
375
 
            instances[Y.id] = Y;
376
 
 
377
 
        }
378
 
 
379
 
        Y.constructor = YUI;
380
 
 
381
 
        // configuration defaults
382
 
        Y.config = Y.config || {
383
 
            win: win,
384
 
            doc: doc,
385
 
            debug: true,
386
 
            useBrowserConsole: true,
387
 
            throwFail: true,
388
 
            bootstrap: true,
389
 
            cacheUse: true,
390
 
            fetchCSS: true,
391
 
            use_rls: false,
392
 
            rls_timeout: 2000
393
 
        };
394
 
 
395
 
        if (YUI.Env.rls_disabled) {
396
 
            Y.config.use_rls = false;
397
 
        }
398
 
 
399
 
        Y.config.lang = Y.config.lang || 'en-US';
400
 
 
401
 
        Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
402
 
        
403
 
        if (!filter || (!('mindebug').indexOf(filter))) {
404
 
            filter = 'min';
405
 
        }
406
 
        filter = (filter) ? '-' + filter : filter;
407
 
        Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
408
 
 
409
 
    },
410
 
 
411
 
    /**
412
 
     * Finishes the instance setup. Attaches whatever modules were defined
413
 
     * when the yui modules was registered.
414
 
     * @method _setup
415
 
     * @private
416
 
     */
417
 
    _setup: function(o) {
418
 
        var i, Y = this,
419
 
            core = [],
420
 
            mods = YUI.Env.mods,
421
 
            extras = Y.config.core || ['get','features','intl-base','yui-log','yui-later'];
422
 
 
423
 
        for (i = 0; i < extras.length; i++) {
424
 
            if (mods[extras[i]]) {
425
 
                core.push(extras[i]);
426
 
            }
427
 
        }
428
 
 
429
 
        Y._attach(['yui-base']);
430
 
        Y._attach(core);
431
 
 
432
 
        // Y.log(Y.id + ' initialized', 'info', 'yui');
433
 
    },
434
 
 
435
 
    /**
436
 
     * Executes a method on a YUI instance with
437
 
     * the specified id if the specified method is whitelisted.
438
 
     * @method applyTo
439
 
     * @param id {String} the YUI instance id.
440
 
     * @param method {String} the name of the method to exectute.
441
 
     * Ex: 'Object.keys'.
442
 
     * @param args {Array} the arguments to apply to the method.
443
 
     * @return {Object} the return value from the applied method or null.
444
 
     */
445
 
    applyTo: function(id, method, args) {
446
 
        if (!(method in APPLY_TO_AUTH)) {
447
 
            this.log(method + ': applyTo not allowed', 'warn', 'yui');
448
 
            return null;
449
 
        }
450
 
 
451
 
        var instance = instances[id], nest, m, i;
452
 
        if (instance) {
453
 
            nest = method.split('.');
454
 
            m = instance;
455
 
            for (i = 0; i < nest.length; i = i + 1) {
456
 
                m = m[nest[i]];
457
 
                if (!m) {
458
 
                    this.log('applyTo not found: ' + method, 'warn', 'yui');
459
 
                }
460
 
            }
461
 
            return m.apply(instance, args);
462
 
        }
463
 
 
464
 
        return null;
465
 
    },
466
 
 
467
 
    /**
468
 
     * Registers a module with the YUI global.  The easiest way to create a
469
 
     * first-class YUI module is to use the YUI component build tool.
470
 
     *
471
 
     * http://yuilibrary.com/projects/builder
472
 
     *
473
 
     * The build system will produce the `YUI.add` wrapper for you module, along
474
 
     * with any configuration info required for the module.
475
 
     * @method add
476
 
     * @param name {String} module name.
477
 
     * @param fn {Function} entry point into the module that
478
 
     * is used to bind module to the YUI instance.
479
 
     * @param version {String} version string.
480
 
     * @param details {Object} optional config data:
481
 
     * @param details.requires {Array} features that must be present before this module can be attached.
482
 
     * @param details.optional {Array} optional features that should be present if loadOptional
483
 
     * is defined.  Note: modules are not often loaded this way in YUI 3,
484
 
     * but this field is still useful to inform the user that certain
485
 
     * features in the component will require additional dependencies.
486
 
     * @param details.use {Array} features that are included within this module which need to
487
 
     * be attached automatically when this module is attached.  This
488
 
     * supports the YUI 3 rollup system -- a module with submodules
489
 
     * defined will need to have the submodules listed in the 'use'
490
 
     * config.  The YUI component build tool does this for you.
491
 
     * @return {YUI} the YUI instance.
492
 
     *
493
 
     */
494
 
    add: function(name, fn, version, details) {
495
 
        details = details || {};
496
 
        var env = YUI.Env,
497
 
            mod = {
498
 
                name: name,
499
 
                fn: fn,
500
 
                version: version,
501
 
                details: details
502
 
            },
503
 
            loader,
504
 
            i, versions = env.versions;
505
 
 
506
 
        env.mods[name] = mod;
507
 
        versions[version] = versions[version] || {};
508
 
        versions[version][name] = mod;
509
 
 
510
 
        for (i in instances) {
511
 
            if (instances.hasOwnProperty(i)) {
512
 
                loader = instances[i].Env._loader;
513
 
                if (loader) {
514
 
                    if (!loader.moduleInfo[name]) {
515
 
                        loader.addModule(details, name);
516
 
                    }
517
 
                }
518
 
            }
519
 
        }
520
 
 
521
 
        return this;
522
 
    },
523
 
 
524
 
    /**
525
 
     * Executes the function associated with each required
526
 
     * module, binding the module to the YUI instance.
527
 
     * @method _attach
528
 
     * @private
529
 
     */
530
 
    _attach: function(r, moot) {
531
 
        var i, name, mod, details, req, use, after,
532
 
            mods = YUI.Env.mods,
533
 
            aliases = YUI.Env.aliases,
534
 
            Y = this, j,
535
 
            done = Y.Env._attached,
536
 
            len = r.length, loader;
537
 
 
538
 
        //console.info('attaching: ' + r, 'info', 'yui');
539
 
 
540
 
        for (i = 0; i < len; i++) {
541
 
            if (!done[r[i]]) {
542
 
                name = r[i];
543
 
                mod = mods[name];
544
 
                if (aliases && aliases[name]) {
545
 
                    Y._attach(aliases[name]);
546
 
                    continue;
547
 
                }
548
 
                if (!mod) {
549
 
                    loader = Y.Env._loader;
550
 
                    if (loader && loader.moduleInfo[name]) {
551
 
                        mod = loader.moduleInfo[name];
552
 
                        if (mod.use) {
553
 
                            moot = true;
554
 
                        }
555
 
                    }
556
 
 
557
 
                    // Y.log('no js def for: ' + name, 'info', 'yui');
558
 
 
559
 
                    //if (!loader || !loader.moduleInfo[name]) {
560
 
                    //if ((!loader || !loader.moduleInfo[name]) && !moot) {
561
 
                    if (!moot) {
562
 
                        if (name.indexOf('skin-') === -1) {
563
 
                            Y.Env._missed.push(name);
564
 
                            Y.message('NOT loaded: ' + name, 'warn', 'yui');
565
 
                        }
566
 
                    }
567
 
                } else {
568
 
                    done[name] = true;
569
 
                    //Don't like this, but in case a mod was asked for once, then we fetch it
570
 
                    //We need to remove it from the missed list
571
 
                    for (j = 0; j < Y.Env._missed.length; j++) {
572
 
                        if (Y.Env._missed[j] === name) {
573
 
                            Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
574
 
                            Y.Env._missed.splice(j, 1);
575
 
                        }
576
 
                    }
577
 
                    details = mod.details;
578
 
                    req = details.requires;
579
 
                    use = details.use;
580
 
                    after = details.after;
581
 
 
582
 
                    if (req) {
583
 
                        for (j = 0; j < req.length; j++) {
584
 
                            if (!done[req[j]]) {
585
 
                                if (!Y._attach(req)) {
586
 
                                    return false;
587
 
                                }
588
 
                                break;
589
 
                            }
590
 
                        }
591
 
                    }
592
 
 
593
 
                    if (after) {
594
 
                        for (j = 0; j < after.length; j++) {
595
 
                            if (!done[after[j]]) {
596
 
                                if (!Y._attach(after, true)) {
597
 
                                    return false;
598
 
                                }
599
 
                                break;
600
 
                            }
601
 
                        }
602
 
                    }
603
 
 
604
 
                    if (mod.fn) {
605
 
                        try {
606
 
                            mod.fn(Y, name);
607
 
                        } catch (e) {
608
 
                            Y.error('Attach error: ' + name, e, name);
609
 
                            return false;
610
 
                        }
611
 
                    }
612
 
 
613
 
                    if (use) {
614
 
                        for (j = 0; j < use.length; j++) {
615
 
                            if (!done[use[j]]) {
616
 
                                if (!Y._attach(use)) {
617
 
                                    return false;
618
 
                                }
619
 
                                break;
620
 
                            }
621
 
                        }
622
 
                    }
623
 
 
624
 
 
625
 
 
626
 
                }
627
 
            }
628
 
        }
629
 
 
630
 
        return true;
631
 
    },
632
 
 
633
 
    /**
634
 
     * Attaches one or more modules to the YUI instance.  When this
635
 
     * is executed, the requirements are analyzed, and one of
636
 
     * several things can happen:
637
 
     *
638
 
     *  * All requirements are available on the page --  The modules
639
 
     *   are attached to the instance.  If supplied, the use callback
640
 
     *   is executed synchronously.
641
 
     *
642
 
     *  * Modules are missing, the Get utility is not available OR
643
 
     *   the 'bootstrap' config is false -- A warning is issued about
644
 
     *   the missing modules and all available modules are attached.
645
 
     *
646
 
     *  * Modules are missing, the Loader is not available but the Get
647
 
     *   utility is and boostrap is not false -- The loader is bootstrapped
648
 
     *   before doing the following....
649
 
     *
650
 
     *  * Modules are missing and the Loader is available -- The loader
651
 
     *   expands the dependency tree and fetches missing modules.  When
652
 
     *   the loader is finshed the callback supplied to use is executed
653
 
     *   asynchronously.
654
 
     *
655
 
     * @method use
656
 
     * @param modules* {String} 1-n modules to bind (uses arguments array).
657
 
     * @param *callback {Function} callback function executed when
658
 
     * the instance has the required functionality.  If included, it
659
 
     * must be the last parameter.
660
 
     *
661
 
     * @example
662
 
     *      // loads and attaches dd and its dependencies
663
 
     *      YUI().use('dd', function(Y) {});
664
 
     *
665
 
     *      // loads and attaches dd and node as well as all of their dependencies (since 3.4.0)
666
 
     *      YUI().use(['dd', 'node'], function(Y) {});
667
 
     *
668
 
     *      // attaches all modules that are available on the page
669
 
     *      YUI().use('*', function(Y) {});
670
 
     *
671
 
     *      // intrinsic YUI gallery support (since 3.1.0)
672
 
     *      YUI().use('gallery-yql', function(Y) {});
673
 
     *
674
 
     *      // intrinsic YUI 2in3 support (since 3.1.0)
675
 
     *      YUI().use('yui2-datatable', function(Y) {});
676
 
     *
677
 
     * @return {YUI} the YUI instance.
678
 
     */
679
 
    use: function() {
680
 
        var args = SLICE.call(arguments, 0),
681
 
            callback = args[args.length - 1],
682
 
            Y = this,
683
 
            i = 0,
684
 
            name,
685
 
            Env = Y.Env,
686
 
            provisioned = true;
687
 
 
688
 
        // The last argument supplied to use can be a load complete callback
689
 
        if (Y.Lang.isFunction(callback)) {
690
 
            args.pop();
691
 
        } else {
692
 
            callback = null;
693
 
        }
694
 
        if (Y.Lang.isArray(args[0])) {
695
 
            args = args[0];
696
 
        }
697
 
 
698
 
        if (Y.config.cacheUse) {
699
 
            while ((name = args[i++])) {
700
 
                if (!Env._attached[name]) {
701
 
                    provisioned = false;
702
 
                    break;
703
 
                }
704
 
            }
705
 
 
706
 
            if (provisioned) {
707
 
                if (args.length) {
708
 
                    Y.log('already provisioned: ' + args, 'info', 'yui');
709
 
                }
710
 
                Y._notify(callback, ALREADY_DONE, args);
711
 
                return Y;
712
 
            }
713
 
        }
714
 
 
715
 
        if (Y.config.cacheUse) {
716
 
            while ((name = args[i++])) {
717
 
                if (!Env._attached[name]) {
718
 
                    provisioned = false;
719
 
                    break;
720
 
                }
721
 
            }
722
 
 
723
 
            if (provisioned) {
724
 
                if (args.length) {
725
 
                    Y.log('already provisioned: ' + args, 'info', 'yui');
726
 
                }
727
 
                Y._notify(callback, ALREADY_DONE, args);
728
 
                return Y;
729
 
            }
730
 
        }
731
 
 
732
 
        if (Y._loading) {
733
 
            Y._useQueue = Y._useQueue || new Y.Queue();
734
 
            Y._useQueue.add([args, callback]);
735
 
        } else {
736
 
            Y._use(args, function(Y, response) {
737
 
                Y._notify(callback, response, args);
738
 
            });
739
 
        }
740
 
 
741
 
        return Y;
742
 
    },
743
 
    /**
744
 
    * Notify handler from Loader for attachment/load errors
745
 
    * @method _notify
746
 
    * @param callback {Function} The callback to pass to the `Y.config.loadErrorFn`
747
 
    * @param response {Object} The response returned from Loader
748
 
    * @param args {Array} The aruments passed from Loader
749
 
    * @private
750
 
    */
751
 
    _notify: function(callback, response, args) {
752
 
        if (!response.success && this.config.loadErrorFn) {
753
 
            this.config.loadErrorFn.call(this, this, callback, response, args);
754
 
        } else if (callback) {
755
 
            try {
756
 
                callback(this, response);
757
 
            } catch (e) {
758
 
                this.error('use callback error', e, args);
759
 
            }
760
 
        }
761
 
    },
762
 
    
763
 
    /**
764
 
    * This private method is called from the `use` method queue. To ensure that only one set of loading
765
 
    * logic is performed at a time.
766
 
    * @method _use
767
 
    * @private
768
 
    * @param args* {String} 1-n modules to bind (uses arguments array).
769
 
    * @param *callback {Function} callback function executed when
770
 
    * the instance has the required functionality.  If included, it
771
 
    * must be the last parameter.
772
 
    */
773
 
    _use: function(args, callback) {
774
 
 
775
 
        if (!this.Array) {
776
 
            this._attach(['yui-base']);
777
 
        }
778
 
 
779
 
        var len, loader, handleBoot, handleRLS,
780
 
            Y = this,
781
 
            G_ENV = YUI.Env,
782
 
            mods = G_ENV.mods,
783
 
            Env = Y.Env,
784
 
            used = Env._used,
785
 
            queue = G_ENV._loaderQueue,
786
 
            firstArg = args[0],
787
 
            YArray = Y.Array,
788
 
            config = Y.config,
789
 
            boot = config.bootstrap,
790
 
            missing = [],
791
 
            r = [],
792
 
            ret = true,
793
 
            fetchCSS = config.fetchCSS,
794
 
            process = function(names, skip) {
795
 
 
796
 
                if (!names.length) {
797
 
                    return;
798
 
                }
799
 
 
800
 
                YArray.each(names, function(name) {
801
 
 
802
 
                    // add this module to full list of things to attach
803
 
                    if (!skip) {
804
 
                        r.push(name);
805
 
                    }
806
 
 
807
 
                    // only attach a module once
808
 
                    if (used[name]) {
809
 
                        return;
810
 
                    }
811
 
 
812
 
                    var m = mods[name], req, use;
813
 
 
814
 
                    if (m) {
815
 
                        used[name] = true;
816
 
                        req = m.details.requires;
817
 
                        use = m.details.use;
818
 
                    } else {
819
 
                        // CSS files don't register themselves, see if it has
820
 
                        // been loaded
821
 
                        if (!G_ENV._loaded[VERSION][name]) {
822
 
                            missing.push(name);
823
 
                        } else {
824
 
                            used[name] = true; // probably css
825
 
                        }
826
 
                    }
827
 
 
828
 
                    // make sure requirements are attached
829
 
                    if (req && req.length) {
830
 
                        process(req);
831
 
                    }
832
 
 
833
 
                    // make sure we grab the submodule dependencies too
834
 
                    if (use && use.length) {
835
 
                        process(use, 1);
836
 
                    }
837
 
                });
838
 
            },
839
 
 
840
 
            handleLoader = function(fromLoader) {
841
 
                var response = fromLoader || {
842
 
                        success: true,
843
 
                        msg: 'not dynamic'
844
 
                    },
845
 
                    redo, origMissing,
846
 
                    ret = true,
847
 
                    data = response.data;
848
 
 
849
 
 
850
 
                Y._loading = false;
851
 
 
852
 
                if (data) {
853
 
                    origMissing = missing;
854
 
                    missing = [];
855
 
                    r = [];
856
 
                    process(data);
857
 
                    redo = missing.length;
858
 
                    if (redo) {
859
 
                        if (missing.sort().join() ==
860
 
                                origMissing.sort().join()) {
861
 
                            redo = false;
862
 
                        }
863
 
                    }
864
 
                }
865
 
 
866
 
                if (redo && data) {
867
 
                    Y._loading = false;
868
 
                    Y._use(args, function() {
869
 
                        Y.log('Nested use callback: ' + data, 'info', 'yui');
870
 
                        if (Y._attach(data)) {
871
 
                            Y._notify(callback, response, data);
872
 
                        }
873
 
                    });
874
 
                } else {
875
 
                    if (data) {
876
 
                        // Y.log('attaching from loader: ' + data, 'info', 'yui');
877
 
                        ret = Y._attach(data);
878
 
                    }
879
 
                    if (ret) {
880
 
                        Y._notify(callback, response, args);
881
 
                    }
882
 
                }
883
 
 
884
 
                if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
885
 
                    Y._use.apply(Y, Y._useQueue.next());
886
 
                }
887
 
 
888
 
            };
889
 
 
890
 
// Y.log(Y.id + ': use called: ' + a + ' :: ' + callback, 'info', 'yui');
891
 
 
892
 
        // YUI().use('*'); // bind everything available
893
 
        if (firstArg === '*') {
894
 
            ret = Y._attach(Y.Object.keys(mods));
895
 
            if (ret) {
896
 
                handleLoader();
897
 
            }
898
 
            return Y;
899
 
        }
900
 
 
901
 
        // Y.log('before loader requirements: ' + args, 'info', 'yui');
902
 
 
903
 
        // use loader to expand dependencies and sort the
904
 
        // requirements if it is available.
905
 
        if (boot && Y.Loader && args.length) {
906
 
            loader = getLoader(Y);
907
 
            loader.require(args);
908
 
            loader.ignoreRegistered = true;
909
 
            loader.calculate(null, (fetchCSS) ? null : 'js');
910
 
            args = loader.sorted;
911
 
        }
912
 
 
913
 
        // process each requirement and any additional requirements
914
 
        // the module metadata specifies
915
 
        process(args);
916
 
 
917
 
        len = missing.length;
918
 
 
919
 
        if (len) {
920
 
            missing = Y.Object.keys(YArray.hash(missing));
921
 
            len = missing.length;
922
 
Y.log('Modules missing: ' + missing + ', ' + missing.length, 'info', 'yui');
923
 
        }
924
 
 
925
 
        // dynamic load
926
 
        if (boot && len && Y.Loader) {
927
 
// Y.log('Using loader to fetch missing deps: ' + missing, 'info', 'yui');
928
 
            Y.log('Using Loader', 'info', 'yui');
929
 
            Y._loading = true;
930
 
            loader = getLoader(Y);
931
 
            loader.onEnd = handleLoader;
932
 
            loader.context = Y;
933
 
            loader.data = args;
934
 
            loader.ignoreRegistered = false;
935
 
            loader.require(args);
936
 
            loader.insert(null, (fetchCSS) ? null : 'js');
937
 
            // loader.partial(missing, (fetchCSS) ? null : 'js');
938
 
 
939
 
        } else if (len && Y.config.use_rls && !YUI.Env.rls_enabled) {
940
 
 
941
 
            G_ENV._rls_queue = G_ENV._rls_queue || new Y.Queue();
942
 
 
943
 
            // server side loader service
944
 
            handleRLS = function(instance, argz) {
945
 
 
946
 
                var rls_end = function(o) {
947
 
                    handleLoader(o);
948
 
                    instance.rls_advance();
949
 
                },
950
 
                rls_url = instance._rls(argz);
951
 
 
952
 
                if (rls_url) {
953
 
                    Y.log('Fetching RLS url', 'info', 'rls');
954
 
                    instance.rls_oncomplete(function(o) {
955
 
                        rls_end(o);
956
 
                    });
957
 
                    instance.Get.script(rls_url, {
958
 
                        data: argz,
959
 
                        timeout: instance.config.rls_timeout,
960
 
                        onFailure: instance.rls_handleFailure,
961
 
                        onTimeout: instance.rls_handleTimeout
962
 
                    });
963
 
                } else {
964
 
                    rls_end({
965
 
                        data: argz
966
 
                    });
967
 
                }
968
 
            };
969
 
 
970
 
            G_ENV._rls_queue.add(function() {
971
 
                Y.log('executing queued rls request', 'info', 'rls');
972
 
                G_ENV._rls_in_progress = true;
973
 
                Y.rls_callback = callback;
974
 
                Y.rls_locals(Y, args, handleRLS);
975
 
            });
976
 
 
977
 
            if (!G_ENV._rls_in_progress && G_ENV._rls_queue.size()) {
978
 
                G_ENV._rls_queue.next()();
979
 
            }
980
 
 
981
 
        } else if (boot && len && Y.Get && !Env.bootstrapped) {
982
 
 
983
 
            Y._loading = true;
984
 
 
985
 
            handleBoot = function() {
986
 
                Y._loading = false;
987
 
                queue.running = false;
988
 
                Env.bootstrapped = true;
989
 
                G_ENV._bootstrapping = false;
990
 
                if (Y._attach(['loader'])) {
991
 
                    Y._use(args, callback);
992
 
                }
993
 
            };
994
 
 
995
 
            if (G_ENV._bootstrapping) {
996
 
Y.log('Waiting for loader', 'info', 'yui');
997
 
                queue.add(handleBoot);
998
 
            } else {
999
 
                G_ENV._bootstrapping = true;
1000
 
Y.log('Fetching loader: ' + config.base + config.loaderPath, 'info', 'yui');
1001
 
                Y.Get.script(config.base + config.loaderPath, {
1002
 
                    onEnd: handleBoot
1003
 
                });
1004
 
            }
1005
 
 
1006
 
        } else {
1007
 
            Y.log('Attaching available dependencies: ' + args, 'info', 'yui');
1008
 
            ret = Y._attach(args);
1009
 
            if (ret) {
1010
 
                handleLoader();
1011
 
            }
1012
 
        }
1013
 
 
1014
 
        return Y;
1015
 
    },
1016
 
 
1017
 
 
1018
 
    /**
1019
 
     * Returns the namespace specified and creates it if it doesn't exist
1020
 
     * 
1021
 
     *      YUI.namespace("property.package");
1022
 
     *      YUI.namespace("YAHOO.property.package");
1023
 
     * 
1024
 
     * Either of the above would create `YUI.property`, then
1025
 
     * `YUI.property.package` (`YAHOO` is scrubbed out, this is
1026
 
     * to remain compatible with YUI2)
1027
 
     *
1028
 
     * Be careful when naming packages. Reserved words may work in some browsers
1029
 
     * and not others. For instance, the following will fail in Safari:
1030
 
     * 
1031
 
     *      YUI.namespace("really.long.nested.namespace");
1032
 
     * 
1033
 
     * This fails because "long" is a future reserved word in ECMAScript
1034
 
     *
1035
 
     * @method namespace
1036
 
     * @param  {string*} arguments 1-n namespaces to create.
1037
 
     * @return {object}  A reference to the last namespace object created.
1038
 
     */
1039
 
    namespace: function() {
1040
 
        var a = arguments, o = this, i = 0, j, d, arg;
1041
 
        for (; i < a.length; i++) {
1042
 
            // d = ('' + a[i]).split('.');
1043
 
            arg = a[i];
1044
 
            if (arg.indexOf(PERIOD)) {
1045
 
                d = arg.split(PERIOD);
1046
 
                for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
1047
 
                    o[d[j]] = o[d[j]] || {};
1048
 
                    o = o[d[j]];
1049
 
                }
1050
 
            } else {
1051
 
                o[arg] = o[arg] || {};
1052
 
            }
1053
 
        }
1054
 
        return o;
1055
 
    },
1056
 
 
1057
 
    // this is replaced if the log module is included
1058
 
    log: NOOP,
1059
 
    message: NOOP,
1060
 
    // this is replaced if the dump module is included
1061
 
    dump: function (o) { return ''+o; },
1062
 
 
1063
 
    /**
1064
 
     * Report an error.  The reporting mechanism is controled by
1065
 
     * the `throwFail` configuration attribute.  If throwFail is
1066
 
     * not specified, the message is written to the Logger, otherwise
1067
 
     * a JS error is thrown
1068
 
     * @method error
1069
 
     * @param msg {String} the error message.
1070
 
     * @param e {Error|String} Optional JS error that was caught, or an error string.
1071
 
     * @param data Optional additional info
1072
 
     * and `throwFail` is specified, this error will be re-thrown.
1073
 
     * @return {YUI} this YUI instance.
1074
 
     */
1075
 
    error: function(msg, e, data) {
1076
 
 
1077
 
        var Y = this, ret;
1078
 
 
1079
 
        if (Y.config.errorFn) {
1080
 
            ret = Y.config.errorFn.apply(Y, arguments);
1081
 
        }
1082
 
 
1083
 
        if (Y.config.throwFail && !ret) {
1084
 
            throw (e || new Error(msg));
1085
 
        } else {
1086
 
            Y.message(msg, 'error'); // don't scrub this one
1087
 
        }
1088
 
 
1089
 
        return Y;
1090
 
    },
1091
 
 
1092
 
    /**
1093
 
     * Generate an id that is unique among all YUI instances
1094
 
     * @method guid
1095
 
     * @param pre {String} optional guid prefix.
1096
 
     * @return {String} the guid.
1097
 
     */
1098
 
    guid: function(pre) {
1099
 
        var id = this.Env._guidp + '_' + (++this.Env._uidx);
1100
 
        return (pre) ? (pre + id) : id;
1101
 
    },
1102
 
 
1103
 
    /**
1104
 
     * Returns a `guid` associated with an object.  If the object
1105
 
     * does not have one, a new one is created unless `readOnly`
1106
 
     * is specified.
1107
 
     * @method stamp
1108
 
     * @param o {Object} The object to stamp.
1109
 
     * @param readOnly {Boolean} if `true`, a valid guid will only
1110
 
     * be returned if the object has one assigned to it.
1111
 
     * @return {String} The object's guid or null.
1112
 
     */
1113
 
    stamp: function(o, readOnly) {
1114
 
        var uid;
1115
 
        if (!o) {
1116
 
            return o;
1117
 
        }
1118
 
 
1119
 
        // IE generates its own unique ID for dom nodes
1120
 
        // The uniqueID property of a document node returns a new ID
1121
 
        if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
1122
 
            uid = o.uniqueID;
1123
 
        } else {
1124
 
            uid = (typeof o === 'string') ? o : o._yuid;
1125
 
        }
1126
 
 
1127
 
        if (!uid) {
1128
 
            uid = this.guid();
1129
 
            if (!readOnly) {
1130
 
                try {
1131
 
                    o._yuid = uid;
1132
 
                } catch (e) {
1133
 
                    uid = null;
1134
 
                }
1135
 
            }
1136
 
        }
1137
 
        return uid;
1138
 
    },
1139
 
 
1140
 
    /**
1141
 
     * Destroys the YUI instance
1142
 
     * @method destroy
1143
 
     * @since 3.3.0
1144
 
     */
1145
 
    destroy: function() {
1146
 
        var Y = this;
1147
 
        if (Y.Event) {
1148
 
            Y.Event._unload();
1149
 
        }
1150
 
        delete instances[Y.id];
1151
 
        delete Y.Env;
1152
 
        delete Y.config;
1153
 
    }
1154
 
 
1155
 
    /**
1156
 
     * instanceof check for objects that works around
1157
 
     * memory leak in IE when the item tested is
1158
 
     * window/document
1159
 
     * @method instanceOf
1160
 
     * @since 3.3.0
1161
 
     */
1162
 
};
1163
 
 
1164
 
 
1165
 
 
1166
 
    YUI.prototype = proto;
1167
 
 
1168
 
    // inheritance utilities are not available yet
1169
 
    for (prop in proto) {
1170
 
        if (proto.hasOwnProperty(prop)) {
1171
 
            YUI[prop] = proto[prop];
1172
 
        }
1173
 
    }
1174
 
 
1175
 
    // set up the environment
1176
 
    YUI._init();
1177
 
 
1178
 
    if (hasWin) {
1179
 
        // add a window load event at load time so we can capture
1180
 
        // the case where it fires before dynamic loading is
1181
 
        // complete.
1182
 
        add(window, 'load', handleLoad);
1183
 
    } else {
1184
 
        handleLoad();
1185
 
    }
1186
 
 
1187
 
    YUI.Env.add = add;
1188
 
    YUI.Env.remove = remove;
1189
 
 
1190
 
    /*global exports*/
1191
 
    // Support the CommonJS method for exporting our single global
1192
 
    if (typeof exports == 'object') {
1193
 
        exports.YUI = YUI;
1194
 
    }
1195
 
 
1196
 
}());
1197
 
 
1198
 
 
1199
 
/**
1200
 
 * The config object contains all of the configuration options for
1201
 
 * the `YUI` instance.  This object is supplied by the implementer
1202
 
 * when instantiating a `YUI` instance.  Some properties have default
1203
 
 * values if they are not supplied by the implementer.  This should
1204
 
 * not be updated directly because some values are cached.  Use
1205
 
 * `applyConfig()` to update the config object on a YUI instance that
1206
 
 * has already been configured.
1207
 
 *
1208
 
 * @class config
1209
 
 * @static
1210
 
 */
1211
 
 
1212
 
/**
1213
 
 * Allows the YUI seed file to fetch the loader component and library
1214
 
 * metadata to dynamically load additional dependencies.
1215
 
 *
1216
 
 * @property bootstrap
1217
 
 * @type boolean
1218
 
 * @default true
1219
 
 */
1220
 
 
1221
 
/**
1222
 
 * Log to the browser console if debug is on and the browser has a
1223
 
 * supported console.
1224
 
 *
1225
 
 * @property useBrowserConsole
1226
 
 * @type boolean
1227
 
 * @default true
1228
 
 */
1229
 
 
1230
 
/**
1231
 
 * A hash of log sources that should be logged.  If specified, only
1232
 
 * log messages from these sources will be logged.
1233
 
 *
1234
 
 * @property logInclude
1235
 
 * @type object
1236
 
 */
1237
 
 
1238
 
/**
1239
 
 * A hash of log sources that should be not be logged.  If specified,
1240
 
 * all sources are logged if not on this list.
1241
 
 *
1242
 
 * @property logExclude
1243
 
 * @type object
1244
 
 */
1245
 
 
1246
 
/**
1247
 
 * Set to true if the yui seed file was dynamically loaded in
1248
 
 * order to bootstrap components relying on the window load event
1249
 
 * and the `domready` custom event.
1250
 
 *
1251
 
 * @property injected
1252
 
 * @type boolean
1253
 
 * @default false
1254
 
 */
1255
 
 
1256
 
/**
1257
 
 * If `throwFail` is set, `Y.error` will generate or re-throw a JS Error.
1258
 
 * Otherwise the failure is logged.
1259
 
 *
1260
 
 * @property throwFail
1261
 
 * @type boolean
1262
 
 * @default true
1263
 
 */
1264
 
 
1265
 
/**
1266
 
 * The window/frame that this instance should operate in.
1267
 
 *
1268
 
 * @property win
1269
 
 * @type Window
1270
 
 * @default the window hosting YUI
1271
 
 */
1272
 
 
1273
 
/**
1274
 
 * The document associated with the 'win' configuration.
1275
 
 *
1276
 
 * @property doc
1277
 
 * @type Document
1278
 
 * @default the document hosting YUI
1279
 
 */
1280
 
 
1281
 
/**
1282
 
 * A list of modules that defines the YUI core (overrides the default).
1283
 
 *
1284
 
 * @property core
1285
 
 * @type string[]
1286
 
 */
1287
 
 
1288
 
/**
1289
 
 * A list of languages in order of preference. This list is matched against
1290
 
 * the list of available languages in modules that the YUI instance uses to
1291
 
 * determine the best possible localization of language sensitive modules.
1292
 
 * Languages are represented using BCP 47 language tags, such as "en-GB" for
1293
 
 * English as used in the United Kingdom, or "zh-Hans-CN" for simplified
1294
 
 * Chinese as used in China. The list can be provided as a comma-separated
1295
 
 * list or as an array.
1296
 
 *
1297
 
 * @property lang
1298
 
 * @type string|string[]
1299
 
 */
1300
 
 
1301
 
/**
1302
 
 * The default date format
1303
 
 * @property dateFormat
1304
 
 * @type string
1305
 
 * @deprecated use configuration in `DataType.Date.format()` instead.
1306
 
 */
1307
 
 
1308
 
/**
1309
 
 * The default locale
1310
 
 * @property locale
1311
 
 * @type string
1312
 
 * @deprecated use `config.lang` instead.
1313
 
 */
1314
 
 
1315
 
/**
1316
 
 * The default interval when polling in milliseconds.
1317
 
 * @property pollInterval
1318
 
 * @type int
1319
 
 * @default 20
1320
 
 */
1321
 
 
1322
 
/**
1323
 
 * The number of dynamic nodes to insert by default before
1324
 
 * automatically removing them.  This applies to script nodes
1325
 
 * because removing the node will not make the evaluated script
1326
 
 * unavailable.  Dynamic CSS is not auto purged, because removing
1327
 
 * a linked style sheet will also remove the style definitions.
1328
 
 * @property purgethreshold
1329
 
 * @type int
1330
 
 * @default 20
1331
 
 */
1332
 
 
1333
 
/**
1334
 
 * The default interval when polling in milliseconds.
1335
 
 * @property windowResizeDelay
1336
 
 * @type int
1337
 
 * @default 40
1338
 
 */
1339
 
 
1340
 
/**
1341
 
 * Base directory for dynamic loading
1342
 
 * @property base
1343
 
 * @type string
1344
 
 */
1345
 
 
1346
 
/*
1347
 
 * The secure base dir (not implemented)
1348
 
 * For dynamic loading.
1349
 
 * @property secureBase
1350
 
 * @type string
1351
 
 */
1352
 
 
1353
 
/**
1354
 
 * The YUI combo service base dir. Ex: `http://yui.yahooapis.com/combo?`
1355
 
 * For dynamic loading.
1356
 
 * @property comboBase
1357
 
 * @type string
1358
 
 */
1359
 
 
1360
 
/**
1361
 
 * The root path to prepend to module path for the combo service.
1362
 
 * Ex: 3.0.0b1/build/
1363
 
 * For dynamic loading.
1364
 
 * @property root
1365
 
 * @type string
1366
 
 */
1367
 
 
1368
 
/**
1369
 
 * A filter to apply to result urls.  This filter will modify the default
1370
 
 * path for all modules.  The default path for the YUI library is the
1371
 
 * minified version of the files (e.g., event-min.js).  The filter property
1372
 
 * can be a predefined filter or a custom filter.  The valid predefined
1373
 
 * filters are:
1374
 
 * <dl>
1375
 
 *  <dt>DEBUG</dt>
1376
 
 *  <dd>Selects the debug versions of the library (e.g., event-debug.js).
1377
 
 *      This option will automatically include the Logger widget</dd>
1378
 
 *  <dt>RAW</dt>
1379
 
 *  <dd>Selects the non-minified version of the library (e.g., event.js).</dd>
1380
 
 * </dl>
1381
 
 * You can also define a custom filter, which must be an object literal
1382
 
 * containing a search expression and a replace string:
1383
 
 * 
1384
 
 *      myFilter: {
1385
 
 *          'searchExp': "-min\\.js",
1386
 
 *          'replaceStr': "-debug.js"
1387
 
 *      }
1388
 
 *
1389
 
 * For dynamic loading.
1390
 
 *
1391
 
 * @property filter
1392
 
 * @type string|object
1393
 
 */
1394
 
 
1395
 
/**
1396
 
 * The `skin` config let's you configure application level skin
1397
 
 * customizations.  It contains the following attributes which
1398
 
 * can be specified to override the defaults:
1399
 
 *
1400
 
 *      // The default skin, which is automatically applied if not
1401
 
 *      // overriden by a component-specific skin definition.
1402
 
 *      // Change this in to apply a different skin globally
1403
 
 *      defaultSkin: 'sam',
1404
 
 *
1405
 
 *      // This is combined with the loader base property to get
1406
 
 *      // the default root directory for a skin.
1407
 
 *      base: 'assets/skins/',
1408
 
 *
1409
 
 *      // Any component-specific overrides can be specified here,
1410
 
 *      // making it possible to load different skins for different
1411
 
 *      // components.  It is possible to load more than one skin
1412
 
 *      // for a given component as well.
1413
 
 *      overrides: {
1414
 
 *          slider: ['capsule', 'round']
1415
 
 *      }
1416
 
 *
1417
 
 * For dynamic loading.
1418
 
 *
1419
 
 *  @property skin
1420
 
 */
1421
 
 
1422
 
/**
1423
 
 * Hash of per-component filter specification.  If specified for a given
1424
 
 * component, this overrides the filter config.
1425
 
 *
1426
 
 * For dynamic loading.
1427
 
 *
1428
 
 * @property filters
1429
 
 */
1430
 
 
1431
 
/**
1432
 
 * Use the YUI combo service to reduce the number of http connections
1433
 
 * required to load your dependencies.  Turning this off will
1434
 
 * disable combo handling for YUI and all module groups configured
1435
 
 * with a combo service.
1436
 
 *
1437
 
 * For dynamic loading.
1438
 
 *
1439
 
 * @property combine
1440
 
 * @type boolean
1441
 
 * @default true if 'base' is not supplied, false if it is.
1442
 
 */
1443
 
 
1444
 
/**
1445
 
 * A list of modules that should never be dynamically loaded
1446
 
 *
1447
 
 * @property ignore
1448
 
 * @type string[]
1449
 
 */
1450
 
 
1451
 
/**
1452
 
 * A list of modules that should always be loaded when required, even if already
1453
 
 * present on the page.
1454
 
 *
1455
 
 * @property force
1456
 
 * @type string[]
1457
 
 */
1458
 
 
1459
 
/**
1460
 
 * Node or id for a node that should be used as the insertion point for new
1461
 
 * nodes.  For dynamic loading.
1462
 
 *
1463
 
 * @property insertBefore
1464
 
 * @type string
1465
 
 */
1466
 
 
1467
 
/**
1468
 
 * Object literal containing attributes to add to dynamically loaded script
1469
 
 * nodes.
1470
 
 * @property jsAttributes
1471
 
 * @type string
1472
 
 */
1473
 
 
1474
 
/**
1475
 
 * Object literal containing attributes to add to dynamically loaded link
1476
 
 * nodes.
1477
 
 * @property cssAttributes
1478
 
 * @type string
1479
 
 */
1480
 
 
1481
 
/**
1482
 
 * Number of milliseconds before a timeout occurs when dynamically
1483
 
 * loading nodes. If not set, there is no timeout.
1484
 
 * @property timeout
1485
 
 * @type int
1486
 
 */
1487
 
 
1488
 
/**
1489
 
 * Callback for the 'CSSComplete' event.  When dynamically loading YUI
1490
 
 * components with CSS, this property fires when the CSS is finished
1491
 
 * loading but script loading is still ongoing.  This provides an
1492
 
 * opportunity to enhance the presentation of a loading page a little
1493
 
 * bit before the entire loading process is done.
1494
 
 *
1495
 
 * @property onCSS
1496
 
 * @type function
1497
 
 */
1498
 
 
1499
 
/**
1500
 
 * A hash of module definitions to add to the list of YUI components.
1501
 
 * These components can then be dynamically loaded side by side with
1502
 
 * YUI via the `use()` method. This is a hash, the key is the module
1503
 
 * name, and the value is an object literal specifying the metdata
1504
 
 * for the module.  See `Loader.addModule` for the supported module
1505
 
 * metadata fields.  Also see groups, which provides a way to
1506
 
 * configure the base and combo spec for a set of modules.
1507
 
 * 
1508
 
 *      modules: {
1509
 
 *          mymod1: {
1510
 
 *              requires: ['node'],
1511
 
 *              fullpath: 'http://myserver.mydomain.com/mymod1/mymod1.js'
1512
 
 *          },
1513
 
 *          mymod2: {
1514
 
 *              requires: ['mymod1'],
1515
 
 *              fullpath: 'http://myserver.mydomain.com/mymod2/mymod2.js'
1516
 
 *          }
1517
 
 *      }
1518
 
 *
1519
 
 * @property modules
1520
 
 * @type object
1521
 
 */
1522
 
 
1523
 
/**
1524
 
 * A hash of module group definitions.  It for each group you
1525
 
 * can specify a list of modules and the base path and
1526
 
 * combo spec to use when dynamically loading the modules.
1527
 
 * 
1528
 
 *      groups: {
1529
 
 *          yui2: {
1530
 
 *              // specify whether or not this group has a combo service
1531
 
 *              combine: true,
1532
 
 * 
1533
 
 *              // the base path for non-combo paths
1534
 
 *              base: 'http://yui.yahooapis.com/2.8.0r4/build/',
1535
 
 * 
1536
 
 *              // the path to the combo service
1537
 
 *              comboBase: 'http://yui.yahooapis.com/combo?',
1538
 
 * 
1539
 
 *              // a fragment to prepend to the path attribute when
1540
 
 *              // when building combo urls
1541
 
 *              root: '2.8.0r4/build/',
1542
 
 * 
1543
 
 *              // the module definitions
1544
 
 *              modules:  {
1545
 
 *                  yui2_yde: {
1546
 
 *                      path: "yahoo-dom-event/yahoo-dom-event.js"
1547
 
 *                  },
1548
 
 *                  yui2_anim: {
1549
 
 *                      path: "animation/animation.js",
1550
 
 *                      requires: ['yui2_yde']
1551
 
 *                  }
1552
 
 *              }
1553
 
 *          }
1554
 
 *      }
1555
 
 * 
1556
 
 * @property groups
1557
 
 * @type object
1558
 
 */
1559
 
 
1560
 
/**
1561
 
 * The loader 'path' attribute to the loader itself.  This is combined
1562
 
 * with the 'base' attribute to dynamically load the loader component
1563
 
 * when boostrapping with the get utility alone.
1564
 
 *
1565
 
 * @property loaderPath
1566
 
 * @type string
1567
 
 * @default loader/loader-min.js
1568
 
 */
1569
 
 
1570
 
/**
1571
 
 * Specifies whether or not YUI().use(...) will attempt to load CSS
1572
 
 * resources at all.  Any truthy value will cause CSS dependencies
1573
 
 * to load when fetching script.  The special value 'force' will
1574
 
 * cause CSS dependencies to be loaded even if no script is needed.
1575
 
 *
1576
 
 * @property fetchCSS
1577
 
 * @type boolean|string
1578
 
 * @default true
1579
 
 */
1580
 
 
1581
 
/**
1582
 
 * The default gallery version to build gallery module urls
1583
 
 * @property gallery
1584
 
 * @type string
1585
 
 * @since 3.1.0
1586
 
 */
1587
 
 
1588
 
/**
1589
 
 * The default YUI 2 version to build yui2 module urls.  This is for
1590
 
 * intrinsic YUI 2 support via the 2in3 project.  Also see the '2in3'
1591
 
 * config for pulling different revisions of the wrapped YUI 2
1592
 
 * modules.
1593
 
 * @since 3.1.0
1594
 
 * @property yui2
1595
 
 * @type string
1596
 
 * @default 2.8.1
1597
 
 */
1598
 
 
1599
 
/**
1600
 
 * The 2in3 project is a deployment of the various versions of YUI 2
1601
 
 * deployed as first-class YUI 3 modules.  Eventually, the wrapper
1602
 
 * for the modules will change (but the underlying YUI 2 code will
1603
 
 * be the same), and you can select a particular version of
1604
 
 * the wrapper modules via this config.
1605
 
 * @since 3.1.0
1606
 
 * @property 2in3
1607
 
 * @type string
1608
 
 * @default 1
1609
 
 */
1610
 
 
1611
 
/**
1612
 
 * Alternative console log function for use in environments without
1613
 
 * a supported native console.  The function is executed in the
1614
 
 * YUI instance context.
1615
 
 * @since 3.1.0
1616
 
 * @property logFn
1617
 
 * @type Function
1618
 
 */
1619
 
 
1620
 
/**
1621
 
 * A callback to execute when Y.error is called.  It receives the
1622
 
 * error message and an javascript error object if Y.error was
1623
 
 * executed because a javascript error was caught.  The function
1624
 
 * is executed in the YUI instance context.
1625
 
 *
1626
 
 * @since 3.2.0
1627
 
 * @property errorFn
1628
 
 * @type Function
1629
 
 */
1630
 
 
1631
 
/**
1632
 
 * A callback to execute when the loader fails to load one or
1633
 
 * more resource.  This could be because of a script load
1634
 
 * failure.  It can also fail if a javascript module fails
1635
 
 * to register itself, but only when the 'requireRegistration'
1636
 
 * is true.  If this function is defined, the use() callback will
1637
 
 * only be called when the loader succeeds, otherwise it always
1638
 
 * executes unless there was a javascript error when attaching
1639
 
 * a module.
1640
 
 *
1641
 
 * @since 3.3.0
1642
 
 * @property loadErrorFn
1643
 
 * @type Function
1644
 
 */
1645
 
 
1646
 
/**
1647
 
 * When set to true, the YUI loader will expect that all modules
1648
 
 * it is responsible for loading will be first-class YUI modules
1649
 
 * that register themselves with the YUI global.  If this is
1650
 
 * set to true, loader will fail if the module registration fails
1651
 
 * to happen after the script is loaded.
1652
 
 *
1653
 
 * @since 3.3.0
1654
 
 * @property requireRegistration
1655
 
 * @type boolean
1656
 
 * @default false
1657
 
 */
1658
 
 
1659
 
/**
1660
 
 * Cache serviced use() requests.
1661
 
 * @since 3.3.0
1662
 
 * @property cacheUse
1663
 
 * @type boolean
1664
 
 * @default true
1665
 
 * @deprecated no longer used
1666
 
 */
1667
 
 
1668
 
/**
1669
 
 * The parameter defaults for the remote loader service.
1670
 
 * Requires the rls submodule.  The properties that are
1671
 
 * supported:
1672
 
 * 
1673
 
 *  * `m`: comma separated list of module requirements.  This
1674
 
 *    must be the param name even for custom implemetations.
1675
 
 *  * `v`: the version of YUI to load.  Defaults to the version
1676
 
 *    of YUI that is being used.
1677
 
 *  * `gv`: the version of the gallery to load (see the gallery config)
1678
 
 *  * `env`: comma separated list of modules already on the page.
1679
 
 *      this must be the param name even for custom implemetations.
1680
 
 *  * `lang`: the languages supported on the page (see the lang config)
1681
 
 *  * `'2in3v'`:  the version of the 2in3 wrapper to use (see the 2in3 config).
1682
 
 *  * `'2v'`: the version of yui2 to use in the yui 2in3 wrappers
1683
 
 *  * `filt`: a filter def to apply to the urls (see the filter config).
1684
 
 *  * `filts`: a list of custom filters to apply per module
1685
 
 *  * `tests`: this is a map of conditional module test function id keys
1686
 
 * with the values of 1 if the test passes, 0 if not.  This must be
1687
 
 * the name of the querystring param in custom templates.
1688
 
 *
1689
 
 * @since 3.2.0
1690
 
 * @property rls
1691
 
 */
1692
 
 
1693
 
/**
1694
 
 * The base path to the remote loader service
1695
 
 *
1696
 
 * @since 3.2.0
1697
 
 * @property rls_base
1698
 
 */
1699
 
 
1700
 
/**
1701
 
 * The template to use for building the querystring portion
1702
 
 * of the remote loader service url.  The default is determined
1703
 
 * by the rls config -- each property that has a value will be
1704
 
 * represented.
1705
 
 * 
1706
 
 * @since 3.2.0
1707
 
 * @property rls_tmpl
1708
 
 * @example
1709
 
 *      m={m}&v={v}&env={env}&lang={lang}&filt={filt}&tests={tests}
1710
 
 *
1711
 
 */
1712
 
 
1713
 
/**
1714
 
 * Configure the instance to use a remote loader service instead of
1715
 
 * the client loader.
1716
 
 *
1717
 
 * @since 3.2.0
1718
 
 * @property use_rls
1719
 
 */
1720
 
YUI.add('yui-base', function(Y) {
1721
 
 
1722
 
/*
1723
 
 * YUI stub
1724
 
 * @module yui
1725
 
 * @submodule yui-base
1726
 
 */
1727
 
/**
1728
 
 * The YUI module contains the components required for building the YUI
1729
 
 * seed file.  This includes the script loading mechanism, a simple queue,
1730
 
 * and the core utilities for the library.
1731
 
 * @module yui
1732
 
 * @submodule yui-base
1733
 
 */
1734
 
 
1735
 
/**
1736
 
 * Provides core language utilites and extensions used throughout YUI.
1737
 
 *
1738
 
 * @class Lang
1739
 
 * @static
1740
 
 */
1741
 
 
1742
 
var L = Y.Lang || (Y.Lang = {}),
1743
 
 
1744
 
STRING_PROTO = String.prototype,
1745
 
TOSTRING     = Object.prototype.toString,
1746
 
 
1747
 
TYPES = {
1748
 
    'undefined'        : 'undefined',
1749
 
    'number'           : 'number',
1750
 
    'boolean'          : 'boolean',
1751
 
    'string'           : 'string',
1752
 
    '[object Function]': 'function',
1753
 
    '[object RegExp]'  : 'regexp',
1754
 
    '[object Array]'   : 'array',
1755
 
    '[object Date]'    : 'date',
1756
 
    '[object Error]'   : 'error'
1757
 
},
1758
 
 
1759
 
SUBREGEX  = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
1760
 
TRIMREGEX = /^\s+|\s+$/g,
1761
 
 
1762
 
// If either MooTools or Prototype is on the page, then there's a chance that we
1763
 
// can't trust "native" language features to actually be native. When this is
1764
 
// the case, we take the safe route and fall back to our own non-native
1765
 
// implementation.
1766
 
win           = Y.config.win,
1767
 
unsafeNatives = win && !!(win.MooTools || win.Prototype);
1768
 
 
1769
 
/**
1770
 
 * Determines whether or not the provided item is an array.
1771
 
 *
1772
 
 * Returns `false` for array-like collections such as the function `arguments`
1773
 
 * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
1774
 
 * test for an array-like collection.
1775
 
 *
1776
 
 * @method isArray
1777
 
 * @param o The object to test.
1778
 
 * @return {boolean} true if o is an array.
1779
 
 * @static
1780
 
 */
1781
 
L.isArray = (!unsafeNatives && Array.isArray) || function (o) {
1782
 
    return L.type(o) === 'array';
1783
 
};
1784
 
 
1785
 
/**
1786
 
 * Determines whether or not the provided item is a boolean.
1787
 
 * @method isBoolean
1788
 
 * @static
1789
 
 * @param o The object to test.
1790
 
 * @return {boolean} true if o is a boolean.
1791
 
 */
1792
 
L.isBoolean = function(o) {
1793
 
    return typeof o === 'boolean';
1794
 
};
1795
 
 
1796
 
/**
1797
 
 * <p>
1798
 
 * Determines whether or not the provided item is a function.
1799
 
 * Note: Internet Explorer thinks certain functions are objects:
1800
 
 * </p>
1801
 
 *
1802
 
 * <pre>
1803
 
 * var obj = document.createElement("object");
1804
 
 * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
1805
 
 * &nbsp;
1806
 
 * var input = document.createElement("input"); // append to body
1807
 
 * Y.Lang.isFunction(input.focus) // reports false in IE
1808
 
 * </pre>
1809
 
 *
1810
 
 * <p>
1811
 
 * You will have to implement additional tests if these functions
1812
 
 * matter to you.
1813
 
 * </p>
1814
 
 *
1815
 
 * @method isFunction
1816
 
 * @static
1817
 
 * @param o The object to test.
1818
 
 * @return {boolean} true if o is a function.
1819
 
 */
1820
 
L.isFunction = function(o) {
1821
 
    return L.type(o) === 'function';
1822
 
};
1823
 
 
1824
 
/**
1825
 
 * Determines whether or not the supplied item is a date instance.
1826
 
 * @method isDate
1827
 
 * @static
1828
 
 * @param o The object to test.
1829
 
 * @return {boolean} true if o is a date.
1830
 
 */
1831
 
L.isDate = function(o) {
1832
 
    return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
1833
 
};
1834
 
 
1835
 
/**
1836
 
 * Determines whether or not the provided item is null.
1837
 
 * @method isNull
1838
 
 * @static
1839
 
 * @param o The object to test.
1840
 
 * @return {boolean} true if o is null.
1841
 
 */
1842
 
L.isNull = function(o) {
1843
 
    return o === null;
1844
 
};
1845
 
 
1846
 
/**
1847
 
 * Determines whether or not the provided item is a legal number.
1848
 
 * @method isNumber
1849
 
 * @static
1850
 
 * @param o The object to test.
1851
 
 * @return {boolean} true if o is a number.
1852
 
 */
1853
 
L.isNumber = function(o) {
1854
 
    return typeof o === 'number' && isFinite(o);
1855
 
};
1856
 
 
1857
 
/**
1858
 
 * Determines whether or not the provided item is of type object
1859
 
 * or function. Note that arrays are also objects, so
1860
 
 * <code>Y.Lang.isObject([]) === true</code>.
1861
 
 * @method isObject
1862
 
 * @static
1863
 
 * @param o The object to test.
1864
 
 * @param failfn {boolean} fail if the input is a function.
1865
 
 * @return {boolean} true if o is an object.
1866
 
 * @see isPlainObject
1867
 
 */
1868
 
L.isObject = function(o, failfn) {
1869
 
    var t = typeof o;
1870
 
    return (o && (t === 'object' ||
1871
 
        (!failfn && (t === 'function' || L.isFunction(o))))) || false;
1872
 
};
1873
 
 
1874
 
/**
1875
 
 * Determines whether or not the provided item is a string.
1876
 
 * @method isString
1877
 
 * @static
1878
 
 * @param o The object to test.
1879
 
 * @return {boolean} true if o is a string.
1880
 
 */
1881
 
L.isString = function(o) {
1882
 
    return typeof o === 'string';
1883
 
};
1884
 
 
1885
 
/**
1886
 
 * Determines whether or not the provided item is undefined.
1887
 
 * @method isUndefined
1888
 
 * @static
1889
 
 * @param o The object to test.
1890
 
 * @return {boolean} true if o is undefined.
1891
 
 */
1892
 
L.isUndefined = function(o) {
1893
 
    return typeof o === 'undefined';
1894
 
};
1895
 
 
1896
 
/**
1897
 
 * Returns a string without any leading or trailing whitespace.  If
1898
 
 * the input is not a string, the input will be returned untouched.
1899
 
 * @method trim
1900
 
 * @static
1901
 
 * @param s {string} the string to trim.
1902
 
 * @return {string} the trimmed string.
1903
 
 */
1904
 
L.trim = STRING_PROTO.trim ? function(s) {
1905
 
    return s && s.trim ? s.trim() : s;
1906
 
} : function (s) {
1907
 
    try {
1908
 
        return s.replace(TRIMREGEX, '');
1909
 
    } catch (e) {
1910
 
        return s;
1911
 
    }
1912
 
};
1913
 
 
1914
 
/**
1915
 
 * Returns a string without any leading whitespace.
1916
 
 * @method trimLeft
1917
 
 * @static
1918
 
 * @param s {string} the string to trim.
1919
 
 * @return {string} the trimmed string.
1920
 
 */
1921
 
L.trimLeft = STRING_PROTO.trimLeft ? function (s) {
1922
 
    return s.trimLeft();
1923
 
} : function (s) {
1924
 
    return s.replace(/^\s+/, '');
1925
 
};
1926
 
 
1927
 
/**
1928
 
 * Returns a string without any trailing whitespace.
1929
 
 * @method trimRight
1930
 
 * @static
1931
 
 * @param s {string} the string to trim.
1932
 
 * @return {string} the trimmed string.
1933
 
 */
1934
 
L.trimRight = STRING_PROTO.trimRight ? function (s) {
1935
 
    return s.trimRight();
1936
 
} : function (s) {
1937
 
    return s.replace(/\s+$/, '');
1938
 
};
1939
 
 
1940
 
/**
1941
 
 * A convenience method for detecting a legitimate non-null value.
1942
 
 * Returns false for null/undefined/NaN, true for other values,
1943
 
 * including 0/false/''
1944
 
 * @method isValue
1945
 
 * @static
1946
 
 * @param o The item to test.
1947
 
 * @return {boolean} true if it is not null/undefined/NaN || false.
1948
 
 */
1949
 
L.isValue = function(o) {
1950
 
    var t = L.type(o);
1951
 
 
1952
 
    switch (t) {
1953
 
        case 'number':
1954
 
            return isFinite(o);
1955
 
 
1956
 
        case 'null': // fallthru
1957
 
        case 'undefined':
1958
 
            return false;
1959
 
 
1960
 
        default:
1961
 
            return !!t;
1962
 
    }
1963
 
};
1964
 
 
1965
 
/**
1966
 
 * <p>
1967
 
 * Returns a string representing the type of the item passed in.
1968
 
 * </p>
1969
 
 *
1970
 
 * <p>
1971
 
 * Known issues:
1972
 
 * </p>
1973
 
 *
1974
 
 * <ul>
1975
 
 *   <li>
1976
 
 *     <code>typeof HTMLElementCollection</code> returns function in Safari, but
1977
 
 *     <code>Y.type()</code> reports object, which could be a good thing --
1978
 
 *     but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
1979
 
 *   </li>
1980
 
 * </ul>
1981
 
 *
1982
 
 * @method type
1983
 
 * @param o the item to test.
1984
 
 * @return {string} the detected type.
1985
 
 * @static
1986
 
 */
1987
 
L.type = function(o) {
1988
 
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
1989
 
};
1990
 
 
1991
 
/**
1992
 
 * Lightweight version of <code>Y.substitute</code>. Uses the same template
1993
 
 * structure as <code>Y.substitute</code>, but doesn't support recursion,
1994
 
 * auto-object coersion, or formats.
1995
 
 * @method sub
1996
 
 * @param {string} s String to be modified.
1997
 
 * @param {object} o Object containing replacement values.
1998
 
 * @return {string} the substitute result.
1999
 
 * @static
2000
 
 * @since 3.2.0
2001
 
 */
2002
 
L.sub = function(s, o) {
2003
 
    return s.replace ? s.replace(SUBREGEX, function (match, key) {
2004
 
        return L.isUndefined(o[key]) ? match : o[key];
2005
 
    }) : s;
2006
 
};
2007
 
 
2008
 
/**
2009
 
 * Returns the current time in milliseconds.
2010
 
 *
2011
 
 * @method now
2012
 
 * @return {Number} Current time in milliseconds.
2013
 
 * @static
2014
 
 * @since 3.3.0
2015
 
 */
2016
 
L.now = Date.now || function () {
2017
 
    return new Date().getTime();
2018
 
};
2019
 
/**
2020
 
 * The YUI module contains the components required for building the YUI seed
2021
 
 * file. This includes the script loading mechanism, a simple queue, and the
2022
 
 * core utilities for the library.
2023
 
 *
2024
 
 * @module yui
2025
 
 * @submodule yui-base
2026
 
 */
2027
 
 
2028
 
var Lang   = Y.Lang,
2029
 
    Native = Array.prototype,
2030
 
 
2031
 
    hasOwn = Object.prototype.hasOwnProperty;
2032
 
 
2033
 
/**
2034
 
Provides utility methods for working with arrays. Additional array helpers can
2035
 
be found in the `collection` and `array-extras` modules.
2036
 
 
2037
 
`Y.Array(thing)` returns a native array created from _thing_. Depending on
2038
 
_thing_'s type, one of the following will happen:
2039
 
 
2040
 
  * Arrays are returned unmodified unless a non-zero _startIndex_ is
2041
 
    specified.
2042
 
  * Array-like collections (see `Array.test()`) are converted to arrays.
2043
 
  * For everything else, a new array is created with _thing_ as the sole
2044
 
    item.
2045
 
 
2046
 
Note: elements that are also collections, such as `<form>` and `<select>`
2047
 
elements, are not automatically converted to arrays. To force a conversion,
2048
 
pass `true` as the value of the _force_ parameter.
2049
 
 
2050
 
@class Array
2051
 
@constructor
2052
 
@param {Any} thing The thing to arrayify.
2053
 
@param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
2054
 
  collection, a subset of items starting at the specified index will be
2055
 
  returned.
2056
 
@param {Boolean} [force=false] If `true`, _thing_ will be treated as an
2057
 
  array-like collection no matter what.
2058
 
@return {Array} A native array created from _thing_, according to the rules
2059
 
  described above.
2060
 
**/
2061
 
function YArray(thing, startIndex, force) {
2062
 
    var len, result;
2063
 
 
2064
 
    startIndex || (startIndex = 0);
2065
 
 
2066
 
    if (force || YArray.test(thing)) {
2067
 
        // IE throws when trying to slice HTMLElement collections.
2068
 
        try {
2069
 
            return Native.slice.call(thing, startIndex);
2070
 
        } catch (ex) {
2071
 
            result = [];
2072
 
 
2073
 
            for (len = thing.length; startIndex < len; ++startIndex) {
2074
 
                result.push(thing[startIndex]);
2075
 
            }
2076
 
 
2077
 
            return result;
2078
 
        }
2079
 
    }
2080
 
 
2081
 
    return [thing];
2082
 
}
2083
 
 
2084
 
Y.Array = YArray;
2085
 
 
2086
 
/**
2087
 
Evaluates _obj_ to determine if it's an array, an array-like collection, or
2088
 
something else. This is useful when working with the function `arguments`
2089
 
collection and `HTMLElement` collections.
2090
 
 
2091
 
Note: This implementation doesn't consider elements that are also
2092
 
collections, such as `<form>` and `<select>`, to be array-like.
2093
 
 
2094
 
@method test
2095
 
@param {Object} obj Object to test.
2096
 
@return {Number} A number indicating the results of the test:
2097
 
 
2098
 
  * 0: Neither an array nor an array-like collection.
2099
 
  * 1: Real array.
2100
 
  * 2: Array-like collection.
2101
 
 
2102
 
@static
2103
 
**/
2104
 
YArray.test = function (obj) {
2105
 
    var result = 0;
2106
 
 
2107
 
    if (Lang.isArray(obj)) {
2108
 
        result = 1;
2109
 
    } else if (Lang.isObject(obj)) {
2110
 
        try {
2111
 
            // indexed, but no tagName (element) or alert (window),
2112
 
            // or functions without apply/call (Safari
2113
 
            // HTMLElementCollection bug).
2114
 
            if ('length' in obj && !obj.tagName && !obj.alert && !obj.apply) {
2115
 
                result = 2;
2116
 
            }
2117
 
        } catch (ex) {}
2118
 
    }
2119
 
 
2120
 
    return result;
2121
 
};
2122
 
 
2123
 
/**
2124
 
Dedupes an array of strings, returning an array that's guaranteed to contain
2125
 
only one copy of a given string.
2126
 
 
2127
 
This method differs from `Array.unique()` in that it's optimized for use only
2128
 
with strings, whereas `unique` may be used with other types (but is slower).
2129
 
Using `dedupe()` with non-string values may result in unexpected behavior.
2130
 
 
2131
 
@method dedupe
2132
 
@param {String[]} array Array of strings to dedupe.
2133
 
@return {Array} Deduped copy of _array_.
2134
 
@static
2135
 
@since 3.4.0
2136
 
**/
2137
 
YArray.dedupe = function (array) {
2138
 
    var hash    = {},
2139
 
        results = [],
2140
 
        i, item, len;
2141
 
 
2142
 
    for (i = 0, len = array.length; i < len; ++i) {
2143
 
        item = array[i];
2144
 
 
2145
 
        if (!hasOwn.call(hash, item)) {
2146
 
            hash[item] = 1;
2147
 
            results.push(item);
2148
 
        }
2149
 
    }
2150
 
 
2151
 
    return results;
2152
 
};
2153
 
 
2154
 
/**
2155
 
Executes the supplied function on each item in the array. This method wraps
2156
 
the native ES5 `Array.forEach()` method if available.
2157
 
 
2158
 
@method each
2159
 
@param {Array} array Array to iterate.
2160
 
@param {Function} fn Function to execute on each item in the array. The function
2161
 
  will receive the following arguments:
2162
 
    @param {Any} fn.item Current array item.
2163
 
    @param {Number} fn.index Current array index.
2164
 
    @param {Array} fn.array Array being iterated.
2165
 
@param {Object} [thisObj] `this` object to use when calling _fn_.
2166
 
@return {YUI} The YUI instance.
2167
 
@static
2168
 
**/
2169
 
YArray.each = YArray.forEach = Native.forEach ? function (array, fn, thisObj) {
2170
 
    Native.forEach.call(array || [], fn, thisObj || Y);
2171
 
    return Y;
2172
 
} : function (array, fn, thisObj) {
2173
 
    for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
2174
 
        if (i in array) {
2175
 
            fn.call(thisObj || Y, array[i], i, array);
2176
 
        }
2177
 
    }
2178
 
 
2179
 
    return Y;
2180
 
};
2181
 
 
2182
 
/**
2183
 
Alias for `each()`.
2184
 
 
2185
 
@method forEach
2186
 
@static
2187
 
**/
2188
 
 
2189
 
/**
2190
 
Returns an object using the first array as keys and the second as values. If
2191
 
the second array is not provided, or if it doesn't contain the same number of
2192
 
values as the first array, then `true` will be used in place of the missing
2193
 
values.
2194
 
 
2195
 
@example
2196
 
 
2197
 
    Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
2198
 
    // => {a: 'foo', b: 'bar', c: true}
2199
 
 
2200
 
@method hash
2201
 
@param {String[]} keys Array of strings to use as keys.
2202
 
@param {Array} [values] Array to use as values.
2203
 
@return {Object} Hash using the first array as keys and the second as values.
2204
 
@static
2205
 
**/
2206
 
YArray.hash = function (keys, values) {
2207
 
    var hash = {},
2208
 
        vlen = (values && values.length) || 0,
2209
 
        i, len;
2210
 
 
2211
 
    for (i = 0, len = keys.length; i < len; ++i) {
2212
 
        if (i in keys) {
2213
 
            hash[keys[i]] = vlen > i && i in values ? values[i] : true;
2214
 
        }
2215
 
    }
2216
 
 
2217
 
    return hash;
2218
 
};
2219
 
 
2220
 
/**
2221
 
Returns the index of the first item in the array that's equal (using a strict
2222
 
equality check) to the specified _value_, or `-1` if the value isn't found.
2223
 
 
2224
 
This method wraps the native ES5 `Array.indexOf()` method if available.
2225
 
 
2226
 
@method indexOf
2227
 
@param {Array} array Array to search.
2228
 
@param {Any} value Value to search for.
2229
 
@return {Number} Index of the item strictly equal to _value_, or `-1` if not
2230
 
  found.
2231
 
@static
2232
 
**/
2233
 
YArray.indexOf = Native.indexOf ? function (array, value) {
2234
 
    // TODO: support fromIndex
2235
 
    return Native.indexOf.call(array, value);
2236
 
} : function (array, value) {
2237
 
    for (var i = 0, len = array.length; i < len; ++i) {
2238
 
        if (array[i] === value) {
2239
 
            return i;
2240
 
        }
2241
 
    }
2242
 
 
2243
 
    return -1;
2244
 
};
2245
 
 
2246
 
/**
2247
 
Numeric sort convenience function.
2248
 
 
2249
 
The native `Array.prototype.sort()` function converts values to strings and
2250
 
sorts them in lexicographic order, which is unsuitable for sorting numeric
2251
 
values. Provide `Array.numericSort` as a custom sort function when you want
2252
 
to sort values in numeric order.
2253
 
 
2254
 
@example
2255
 
 
2256
 
    [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
2257
 
    // => [4, 8, 15, 16, 23, 42]
2258
 
 
2259
 
@method numericSort
2260
 
@param {Number} a First value to compare.
2261
 
@param {Number} b Second value to compare.
2262
 
@return {Number} Difference between _a_ and _b_.
2263
 
@static
2264
 
**/
2265
 
YArray.numericSort = function (a, b) {
2266
 
    return a - b;
2267
 
};
2268
 
 
2269
 
/**
2270
 
Executes the supplied function on each item in the array. Returning a truthy
2271
 
value from the function will stop the processing of remaining items.
2272
 
 
2273
 
@method some
2274
 
@param {Array} array Array to iterate over.
2275
 
@param {Function} fn Function to execute on each item. The function will receive
2276
 
  the following arguments:
2277
 
    @param {Any} fn.value Current array item.
2278
 
    @param {Number} fn.index Current array index.
2279
 
    @param {Array} fn.array Array being iterated over.
2280
 
@param {Object} [thisObj] `this` object to use when calling _fn_.
2281
 
@return {Boolean} `true` if the function returns a truthy value on any of the
2282
 
  items in the array; `false` otherwise.
2283
 
@static
2284
 
**/
2285
 
YArray.some = Native.some ? function (array, fn, thisObj) {
2286
 
    return Native.some.call(array, fn, thisObj);
2287
 
} : function (array, fn, thisObj) {
2288
 
    for (var i = 0, len = array.length; i < len; ++i) {
2289
 
        if (i in array && fn.call(thisObj, array[i], i, array)) {
2290
 
            return true;
2291
 
        }
2292
 
    }
2293
 
 
2294
 
    return false;
2295
 
};
2296
 
/**
2297
 
 * The YUI module contains the components required for building the YUI
2298
 
 * seed file.  This includes the script loading mechanism, a simple queue,
2299
 
 * and the core utilities for the library.
2300
 
 * @module yui
2301
 
 * @submodule yui-base
2302
 
 */
2303
 
 
2304
 
/**
2305
 
 * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
2306
 
 * removed using next().
2307
 
 *
2308
 
 * @class Queue
2309
 
 * @constructor
2310
 
 * @param {MIXED} item* 0..n items to seed the queue.
2311
 
 */
2312
 
function Queue() {
2313
 
    this._init();
2314
 
    this.add.apply(this, arguments);
2315
 
}
2316
 
 
2317
 
Queue.prototype = {
2318
 
    /**
2319
 
     * Initialize the queue
2320
 
     *
2321
 
     * @method _init
2322
 
     * @protected
2323
 
     */
2324
 
    _init: function() {
2325
 
        /**
2326
 
         * The collection of enqueued items
2327
 
         *
2328
 
         * @property _q
2329
 
         * @type Array
2330
 
         * @protected
2331
 
         */
2332
 
        this._q = [];
2333
 
    },
2334
 
 
2335
 
    /**
2336
 
     * Get the next item in the queue. FIFO support
2337
 
     *
2338
 
     * @method next
2339
 
     * @return {MIXED} the next item in the queue.
2340
 
     */
2341
 
    next: function() {
2342
 
        return this._q.shift();
2343
 
    },
2344
 
 
2345
 
    /**
2346
 
     * Get the last in the queue. LIFO support.
2347
 
     *
2348
 
     * @method last
2349
 
     * @return {MIXED} the last item in the queue.
2350
 
     */
2351
 
    last: function() {
2352
 
        return this._q.pop();
2353
 
    },
2354
 
 
2355
 
    /**
2356
 
     * Add 0..n items to the end of the queue.
2357
 
     *
2358
 
     * @method add
2359
 
     * @param {MIXED} item* 0..n items.
2360
 
     * @return {object} this queue.
2361
 
     */
2362
 
    add: function() {
2363
 
        this._q.push.apply(this._q, arguments);
2364
 
 
2365
 
        return this;
2366
 
    },
2367
 
 
2368
 
    /**
2369
 
     * Returns the current number of queued items.
2370
 
     *
2371
 
     * @method size
2372
 
     * @return {Number} The size.
2373
 
     */
2374
 
    size: function() {
2375
 
        return this._q.length;
2376
 
    }
2377
 
};
2378
 
 
2379
 
Y.Queue = Queue;
2380
 
 
2381
 
YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
2382
 
 
2383
 
/**
2384
 
The YUI module contains the components required for building the YUI seed file.
2385
 
This includes the script loading mechanism, a simple queue, and the core
2386
 
utilities for the library.
2387
 
 
2388
 
@module yui
2389
 
@submodule yui-base
2390
 
**/
2391
 
 
2392
 
var CACHED_DELIMITER = '__',
2393
 
 
2394
 
    hasOwn   = Object.prototype.hasOwnProperty,
2395
 
    isObject = Y.Lang.isObject;
2396
 
 
2397
 
/**
2398
 
Returns a wrapper for a function which caches the return value of that function,
2399
 
keyed off of the combined string representation of the argument values provided
2400
 
when the wrapper is called.
2401
 
 
2402
 
Calling this function again with the same arguments will return the cached value
2403
 
rather than executing the wrapped function.
2404
 
 
2405
 
Note that since the cache is keyed off of the string representation of arguments
2406
 
passed to the wrapper function, arguments that aren't strings and don't provide
2407
 
a meaningful `toString()` method may result in unexpected caching behavior. For
2408
 
example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
2409
 
string `[object Object]` when used as a cache key.
2410
 
 
2411
 
@method cached
2412
 
@param {Function} source The function to memoize.
2413
 
@param {Object} [cache={}] Object in which to store cached values. You may seed
2414
 
  this object with pre-existing cached values if desired.
2415
 
@param {any} [refetch] If supplied, this value is compared with the cached value
2416
 
  using a `==` comparison. If the values are equal, the wrapped function is
2417
 
  executed again even though a cached value exists.
2418
 
@return {Function} Wrapped function.
2419
 
@for YUI
2420
 
**/
2421
 
Y.cached = function (source, cache, refetch) {
2422
 
    cache || (cache = {});
2423
 
 
2424
 
    return function (arg) {
2425
 
        var key = arguments.length > 1 ?
2426
 
                Array.prototype.join.call(arguments, CACHED_DELIMITER) :
2427
 
                arg.toString();
2428
 
 
2429
 
        if (!(key in cache) || (refetch && cache[key] == refetch)) {
2430
 
            cache[key] = source.apply(source, arguments);
2431
 
        }
2432
 
 
2433
 
        return cache[key];
2434
 
    };
2435
 
};
2436
 
 
2437
 
/**
2438
 
Returns a new object containing all of the properties of all the supplied
2439
 
objects. The properties from later objects will overwrite those in earlier
2440
 
objects.
2441
 
 
2442
 
Passing in a single object will create a shallow copy of it. For a deep copy,
2443
 
use `clone()`.
2444
 
 
2445
 
@method merge
2446
 
@param {Object} objects* One or more objects to merge.
2447
 
@return {Object} A new merged object.
2448
 
**/
2449
 
Y.merge = function () {
2450
 
    var args   = arguments,
2451
 
        i      = 0,
2452
 
        len    = args.length,
2453
 
        result = {};
2454
 
 
2455
 
    for (; i < len; ++i) {
2456
 
        Y.mix(result, args[i], true);
2457
 
    }
2458
 
 
2459
 
    return result;
2460
 
};
2461
 
 
2462
 
/**
2463
 
Mixes _supplier_'s properties into _receiver_. Properties will not be
2464
 
overwritten or merged unless the _overwrite_ or _merge_ parameters are `true`,
2465
 
respectively.
2466
 
 
2467
 
In the default mode (0), only properties the supplier owns are copied (prototype
2468
 
properties are not copied). The following copying modes are available:
2469
 
 
2470
 
  * `0`: _Default_. Object to object.
2471
 
  * `1`: Prototype to prototype.
2472
 
  * `2`: Prototype to prototype and object to object.
2473
 
  * `3`: Prototype to object.
2474
 
  * `4`: Object to prototype.
2475
 
 
2476
 
@method mix
2477
 
@param {Function|Object} receiver The object or function to receive the mixed
2478
 
  properties.
2479
 
@param {Function|Object} supplier The object or function supplying the
2480
 
  properties to be mixed.
2481
 
@param {Boolean} [overwrite=false] If `true`, properties that already exist
2482
 
  on the receiver will be overwritten with properties from the supplier.
2483
 
@param {String[]} [whitelist] An array of property names to copy. If
2484
 
  specified, only the whitelisted properties will be copied, and all others
2485
 
  will be ignored.
2486
 
@param {Int} [mode=0] Mix mode to use. See above for available modes.
2487
 
@param {Boolean} [merge=false] If `true`, objects and arrays that already
2488
 
  exist on the receiver will have the corresponding object/array from the
2489
 
  supplier merged into them, rather than being skipped or overwritten. When
2490
 
  both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
2491
 
@return {Function|Object|YUI} The receiver, or the YUI instance if the
2492
 
  specified receiver is falsy.
2493
 
**/
2494
 
Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
2495
 
    var alwaysOverwrite, exists, from, i, key, len, to;
2496
 
 
2497
 
    // If no supplier is given, we return the receiver. If no receiver is given,
2498
 
    // we return Y. Returning Y doesn't make much sense to me, but it's
2499
 
    // grandfathered in for backcompat reasons.
2500
 
    if (!receiver || !supplier) {
2501
 
        return receiver || Y;
2502
 
    }
2503
 
 
2504
 
    if (mode) {
2505
 
        // In mode 2 (prototype to prototype and object to object), we recurse
2506
 
        // once to do the proto to proto mix. The object to object mix will be
2507
 
        // handled later on.
2508
 
        if (mode === 2) {
2509
 
            Y.mix(receiver.prototype, supplier.prototype, overwrite,
2510
 
                    whitelist, 0, merge);
2511
 
        }
2512
 
 
2513
 
        // Depending on which mode is specified, we may be copying from or to
2514
 
        // the prototypes of the supplier and receiver.
2515
 
        from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
2516
 
        to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
2517
 
 
2518
 
        // If either the supplier or receiver doesn't actually have a
2519
 
        // prototype property, then we could end up with an undefined `from`
2520
 
        // or `to`. If that happens, we abort and return the receiver.
2521
 
        if (!from || !to) {
2522
 
            return receiver;
2523
 
        }
2524
 
    } else {
2525
 
        from = supplier;
2526
 
        to   = receiver;
2527
 
    }
2528
 
 
2529
 
    // If `overwrite` is truthy and `merge` is falsy, then we can skip a call
2530
 
    // to `hasOwnProperty` on each iteration and save some time.
2531
 
    alwaysOverwrite = overwrite && !merge;
2532
 
 
2533
 
    if (whitelist) {
2534
 
        for (i = 0, len = whitelist.length; i < len; ++i) {
2535
 
            key = whitelist[i];
2536
 
 
2537
 
            // We call `Object.prototype.hasOwnProperty` instead of calling
2538
 
            // `hasOwnProperty` on the object itself, since the object's
2539
 
            // `hasOwnProperty` method may have been overridden or removed.
2540
 
            // Also, some native objects don't implement a `hasOwnProperty`
2541
 
            // method.
2542
 
            if (!hasOwn.call(from, key)) {
2543
 
                continue;
2544
 
            }
2545
 
 
2546
 
            exists = alwaysOverwrite ? false : hasOwn.call(to, key);
2547
 
 
2548
 
            if (merge && exists && isObject(to[key], true)
2549
 
                    && isObject(from[key], true)) {
2550
 
                // If we're in merge mode, and the key is present on both
2551
 
                // objects, and the value on both objects is either an object or
2552
 
                // an array (but not a function), then we recurse to merge the
2553
 
                // `from` value into the `to` value instead of overwriting it.
2554
 
                //
2555
 
                // Note: It's intentional that the whitelist isn't passed to the
2556
 
                // recursive call here. This is legacy behavior that lots of
2557
 
                // code still depends on.
2558
 
                Y.mix(to[key], from[key], overwrite, null, 0, merge);
2559
 
            } else if (overwrite || !exists) {
2560
 
                // We're not in merge mode, so we'll only copy the `from` value
2561
 
                // to the `to` value if we're in overwrite mode or if the
2562
 
                // current key doesn't exist on the `to` object.
2563
 
                to[key] = from[key];
2564
 
            }
2565
 
        }
2566
 
    } else {
2567
 
        for (key in from) {
2568
 
            // The code duplication here is for runtime performance reasons.
2569
 
            // Combining whitelist and non-whitelist operations into a single
2570
 
            // loop or breaking the shared logic out into a function both result
2571
 
            // in worse performance, and Y.mix is critical enough that the byte
2572
 
            // tradeoff is worth it.
2573
 
            if (!hasOwn.call(from, key)) {
2574
 
                continue;
2575
 
            }
2576
 
 
2577
 
            exists = alwaysOverwrite ? false : hasOwn.call(to, key);
2578
 
 
2579
 
            if (merge && exists && isObject(to[key], true)
2580
 
                    && isObject(from[key], true)) {
2581
 
                Y.mix(to[key], from[key], overwrite, null, 0, merge);
2582
 
            } else if (overwrite || !exists) {
2583
 
                to[key] = from[key];
2584
 
            }
2585
 
        }
2586
 
 
2587
 
        // If this is an IE browser with the JScript enumeration bug, force
2588
 
        // enumeration of the buggy properties by making a recursive call with
2589
 
        // the buggy properties as the whitelist.
2590
 
        if (Y.Object._hasEnumBug) {
2591
 
            Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
2592
 
        }
2593
 
    }
2594
 
 
2595
 
    return receiver;
2596
 
};
2597
 
/**
2598
 
 * The YUI module contains the components required for building the YUI
2599
 
 * seed file.  This includes the script loading mechanism, a simple queue,
2600
 
 * and the core utilities for the library.
2601
 
 * @module yui
2602
 
 * @submodule yui-base
2603
 
 */
2604
 
 
2605
 
/**
2606
 
 * Adds utilities to the YUI instance for working with objects.
2607
 
 *
2608
 
 * @class Object
2609
 
 */
2610
 
 
2611
 
var hasOwn = Object.prototype.hasOwnProperty,
2612
 
 
2613
 
// If either MooTools or Prototype is on the page, then there's a chance that we
2614
 
// can't trust "native" language features to actually be native. When this is
2615
 
// the case, we take the safe route and fall back to our own non-native
2616
 
// implementations.
2617
 
win           = Y.config.win,
2618
 
unsafeNatives = win && !!(win.MooTools || win.Prototype),
2619
 
 
2620
 
UNDEFINED, // <-- Note the comma. We're still declaring vars.
2621
 
 
2622
 
/**
2623
 
 * Returns a new object that uses _obj_ as its prototype. This method wraps the
2624
 
 * native ES5 `Object.create()` method if available, but doesn't currently
2625
 
 * pass through `Object.create()`'s second argument (properties) in order to
2626
 
 * ensure compatibility with older browsers.
2627
 
 *
2628
 
 * @method ()
2629
 
 * @param {Object} obj Prototype object.
2630
 
 * @return {Object} New object using _obj_ as its prototype.
2631
 
 * @static
2632
 
 */
2633
 
O = Y.Object = (!unsafeNatives && Object.create) ? function (obj) {
2634
 
    // We currently wrap the native Object.create instead of simply aliasing it
2635
 
    // to ensure consistency with our fallback shim, which currently doesn't
2636
 
    // support Object.create()'s second argument (properties). Once we have a
2637
 
    // safe fallback for the properties arg, we can stop wrapping
2638
 
    // Object.create().
2639
 
    return Object.create(obj);
2640
 
} : (function () {
2641
 
    // Reusable constructor function for the Object.create() shim.
2642
 
    function F() {}
2643
 
 
2644
 
    // The actual shim.
2645
 
    return function (obj) {
2646
 
        F.prototype = obj;
2647
 
        return new F();
2648
 
    };
2649
 
}()),
2650
 
 
2651
 
/**
2652
 
 * Property names that IE doesn't enumerate in for..in loops, even when they
2653
 
 * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
2654
 
 * manually enumerate these properties.
2655
 
 *
2656
 
 * @property _forceEnum
2657
 
 * @type String[]
2658
 
 * @protected
2659
 
 * @static
2660
 
 */
2661
 
forceEnum = O._forceEnum = [
2662
 
    'hasOwnProperty',
2663
 
    'isPrototypeOf',
2664
 
    'propertyIsEnumerable',
2665
 
    'toString',
2666
 
    'toLocaleString',
2667
 
    'valueOf'
2668
 
],
2669
 
 
2670
 
/**
2671
 
 * `true` if this browser has the JScript enumeration bug that prevents
2672
 
 * enumeration of the properties named in the `_forceEnum` array, `false`
2673
 
 * otherwise.
2674
 
 *
2675
 
 * See:
2676
 
 *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
2677
 
 *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
2678
 
 *
2679
 
 * @property _hasEnumBug
2680
 
 * @type {Boolean}
2681
 
 * @protected
2682
 
 * @static
2683
 
 */
2684
 
hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
2685
 
 
2686
 
/**
2687
 
 * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
2688
 
 * exists only on _obj_'s prototype. This is essentially a safer version of
2689
 
 * `obj.hasOwnProperty()`.
2690
 
 *
2691
 
 * @method owns
2692
 
 * @param {Object} obj Object to test.
2693
 
 * @param {String} key Property name to look for.
2694
 
 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2695
 
 * @static
2696
 
 */
2697
 
owns = O.owns = function (obj, key) {
2698
 
    return !!obj && hasOwn.call(obj, key);
2699
 
}; // <-- End of var declarations.
2700
 
 
2701
 
/**
2702
 
 * Alias for `owns()`.
2703
 
 *
2704
 
 * @method hasKey
2705
 
 * @param {Object} obj Object to test.
2706
 
 * @param {String} key Property name to look for.
2707
 
 * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
2708
 
 * @static
2709
 
 */
2710
 
O.hasKey = owns;
2711
 
 
2712
 
/**
2713
 
 * Returns an array containing the object's enumerable keys. Does not include
2714
 
 * prototype keys or non-enumerable keys.
2715
 
 *
2716
 
 * Note that keys are returned in enumeration order (that is, in the same order
2717
 
 * that they would be enumerated by a `for-in` loop), which may not be the same
2718
 
 * as the order in which they were defined.
2719
 
 *
2720
 
 * This method is an alias for the native ES5 `Object.keys()` method if
2721
 
 * available.
2722
 
 *
2723
 
 * @example
2724
 
 *
2725
 
 *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
2726
 
 *     // => ['a', 'b', 'c']
2727
 
 *
2728
 
 * @method keys
2729
 
 * @param {Object} obj An object.
2730
 
 * @return {String[]} Array of keys.
2731
 
 * @static
2732
 
 */
2733
 
O.keys = (!unsafeNatives && Object.keys) || function (obj) {
2734
 
    if (!Y.Lang.isObject(obj)) {
2735
 
        throw new TypeError('Object.keys called on a non-object');
2736
 
    }
2737
 
 
2738
 
    var keys = [],
2739
 
        i, key, len;
2740
 
 
2741
 
    for (key in obj) {
2742
 
        if (owns(obj, key)) {
2743
 
            keys.push(key);
2744
 
        }
2745
 
    }
2746
 
 
2747
 
    if (hasEnumBug) {
2748
 
        for (i = 0, len = forceEnum.length; i < len; ++i) {
2749
 
            key = forceEnum[i];
2750
 
 
2751
 
            if (owns(obj, key)) {
2752
 
                keys.push(key);
2753
 
            }
2754
 
        }
2755
 
    }
2756
 
 
2757
 
    return keys;
2758
 
};
2759
 
 
2760
 
/**
2761
 
 * Returns an array containing the values of the object's enumerable keys.
2762
 
 *
2763
 
 * Note that values are returned in enumeration order (that is, in the same
2764
 
 * order that they would be enumerated by a `for-in` loop), which may not be the
2765
 
 * same as the order in which they were defined.
2766
 
 *
2767
 
 * @example
2768
 
 *
2769
 
 *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
2770
 
 *     // => ['foo', 'bar', 'baz']
2771
 
 *
2772
 
 * @method values
2773
 
 * @param {Object} obj An object.
2774
 
 * @return {Array} Array of values.
2775
 
 * @static
2776
 
 */
2777
 
O.values = function (obj) {
2778
 
    var keys   = O.keys(obj),
2779
 
        i      = 0,
2780
 
        len    = keys.length,
2781
 
        values = [];
2782
 
 
2783
 
    for (; i < len; ++i) {
2784
 
        values.push(obj[keys[i]]);
2785
 
    }
2786
 
 
2787
 
    return values;
2788
 
};
2789
 
 
2790
 
/**
2791
 
 * Returns the number of enumerable keys owned by an object.
2792
 
 *
2793
 
 * @method size
2794
 
 * @param {Object} obj An object.
2795
 
 * @return {Number} The object's size.
2796
 
 * @static
2797
 
 */
2798
 
O.size = function (obj) {
2799
 
    return O.keys(obj).length;
2800
 
};
2801
 
 
2802
 
/**
2803
 
 * Returns `true` if the object owns an enumerable property with the specified
2804
 
 * value.
2805
 
 *
2806
 
 * @method hasValue
2807
 
 * @param {Object} obj An object.
2808
 
 * @param {any} value The value to search for.
2809
 
 * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
2810
 
 * @static
2811
 
 */
2812
 
O.hasValue = function (obj, value) {
2813
 
    return Y.Array.indexOf(O.values(obj), value) > -1;
2814
 
};
2815
 
 
2816
 
/**
2817
 
 * Executes a function on each enumerable property in _obj_. The function
2818
 
 * receives the value, the key, and the object itself as parameters (in that
2819
 
 * order).
2820
 
 *
2821
 
 * By default, only properties owned by _obj_ are enumerated. To include
2822
 
 * prototype properties, set the _proto_ parameter to `true`.
2823
 
 *
2824
 
 * @method each
2825
 
 * @param {Object} obj Object to enumerate.
2826
 
 * @param {Function} fn Function to execute on each enumerable property.
2827
 
 *   @param {mixed} fn.value Value of the current property.
2828
 
 *   @param {String} fn.key Key of the current property.
2829
 
 *   @param {Object} fn.obj Object being enumerated.
2830
 
 * @param {Object} [thisObj] `this` object to use when calling _fn_.
2831
 
 * @param {Boolean} [proto=false] Include prototype properties.
2832
 
 * @return {YUI} the YUI instance.
2833
 
 * @chainable
2834
 
 * @static
2835
 
 */
2836
 
O.each = function (obj, fn, thisObj, proto) {
2837
 
    var key;
2838
 
 
2839
 
    for (key in obj) {
2840
 
        if (proto || owns(obj, key)) {
2841
 
            fn.call(thisObj || Y, obj[key], key, obj);
2842
 
        }
2843
 
    }
2844
 
 
2845
 
    return Y;
2846
 
};
2847
 
 
2848
 
/**
2849
 
 * Executes a function on each enumerable property in _obj_, but halts if the
2850
 
 * function returns a truthy value. The function receives the value, the key,
2851
 
 * and the object itself as paramters (in that order).
2852
 
 *
2853
 
 * By default, only properties owned by _obj_ are enumerated. To include
2854
 
 * prototype properties, set the _proto_ parameter to `true`.
2855
 
 *
2856
 
 * @method some
2857
 
 * @param {Object} obj Object to enumerate.
2858
 
 * @param {Function} fn Function to execute on each enumerable property.
2859
 
 *   @param {mixed} fn.value Value of the current property.
2860
 
 *   @param {String} fn.key Key of the current property.
2861
 
 *   @param {Object} fn.obj Object being enumerated.
2862
 
 * @param {Object} [thisObj] `this` object to use when calling _fn_.
2863
 
 * @param {Boolean} [proto=false] Include prototype properties.
2864
 
 * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
2865
 
 *   `false` otherwise.
2866
 
 * @static
2867
 
 */
2868
 
O.some = function (obj, fn, thisObj, proto) {
2869
 
    var key;
2870
 
 
2871
 
    for (key in obj) {
2872
 
        if (proto || owns(obj, key)) {
2873
 
            if (fn.call(thisObj || Y, obj[key], key, obj)) {
2874
 
                return true;
2875
 
            }
2876
 
        }
2877
 
    }
2878
 
 
2879
 
    return false;
2880
 
};
2881
 
 
2882
 
/**
2883
 
 * Retrieves the sub value at the provided path,
2884
 
 * from the value object provided.
2885
 
 *
2886
 
 * @method getValue
2887
 
 * @static
2888
 
 * @param o The object from which to extract the property value.
2889
 
 * @param path {Array} A path array, specifying the object traversal path
2890
 
 * from which to obtain the sub value.
2891
 
 * @return {Any} The value stored in the path, undefined if not found,
2892
 
 * undefined if the source is not an object.  Returns the source object
2893
 
 * if an empty path is provided.
2894
 
 */
2895
 
O.getValue = function(o, path) {
2896
 
    if (!Y.Lang.isObject(o)) {
2897
 
        return UNDEFINED;
2898
 
    }
2899
 
 
2900
 
    var i,
2901
 
        p = Y.Array(path),
2902
 
        l = p.length;
2903
 
 
2904
 
    for (i = 0; o !== UNDEFINED && i < l; i++) {
2905
 
        o = o[p[i]];
2906
 
    }
2907
 
 
2908
 
    return o;
2909
 
};
2910
 
 
2911
 
/**
2912
 
 * Sets the sub-attribute value at the provided path on the
2913
 
 * value object.  Returns the modified value object, or
2914
 
 * undefined if the path is invalid.
2915
 
 *
2916
 
 * @method setValue
2917
 
 * @static
2918
 
 * @param o             The object on which to set the sub value.
2919
 
 * @param path {Array}  A path array, specifying the object traversal path
2920
 
 *                      at which to set the sub value.
2921
 
 * @param val {Any}     The new value for the sub-attribute.
2922
 
 * @return {Object}     The modified object, with the new sub value set, or
2923
 
 *                      undefined, if the path was invalid.
2924
 
 */
2925
 
O.setValue = function(o, path, val) {
2926
 
    var i,
2927
 
        p = Y.Array(path),
2928
 
        leafIdx = p.length - 1,
2929
 
        ref = o;
2930
 
 
2931
 
    if (leafIdx >= 0) {
2932
 
        for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
2933
 
            ref = ref[p[i]];
2934
 
        }
2935
 
 
2936
 
        if (ref !== UNDEFINED) {
2937
 
            ref[p[i]] = val;
2938
 
        } else {
2939
 
            return UNDEFINED;
2940
 
        }
2941
 
    }
2942
 
 
2943
 
    return o;
2944
 
};
2945
 
 
2946
 
/**
2947
 
 * Returns `true` if the object has no enumerable properties of its own.
2948
 
 *
2949
 
 * @method isEmpty
2950
 
 * @param {Object} obj An object.
2951
 
 * @return {Boolean} `true` if the object is empty.
2952
 
 * @static
2953
 
 * @since 3.2.0
2954
 
 */
2955
 
O.isEmpty = function (obj) {
2956
 
    return !O.keys(obj).length;
2957
 
};
2958
 
/**
2959
 
 * The YUI module contains the components required for building the YUI seed
2960
 
 * file.  This includes the script loading mechanism, a simple queue, and the
2961
 
 * core utilities for the library.
2962
 
 * @module yui
2963
 
 * @submodule yui-base
2964
 
 */
2965
 
 
2966
 
/**
2967
 
 * YUI user agent detection.
2968
 
 * Do not fork for a browser if it can be avoided.  Use feature detection when
2969
 
 * you can.  Use the user agent as a last resort.  For all fields listed
2970
 
 * as @type float, UA stores a version number for the browser engine,
2971
 
 * 0 otherwise.  This value may or may not map to the version number of
2972
 
 * the browser using the engine.  The value is presented as a float so
2973
 
 * that it can easily be used for boolean evaluation as well as for
2974
 
 * looking for a particular range of versions.  Because of this,
2975
 
 * some of the granularity of the version info may be lost.  The fields that
2976
 
 * are @type string default to null.  The API docs list the values that
2977
 
 * these fields can have.
2978
 
 * @class UA
2979
 
 * @static
2980
 
 */
2981
 
/**
2982
 
* Static method for parsing the UA string. Defaults to assigning it's value to Y.UA
2983
 
* @static
2984
 
* @method Env.parseUA
2985
 
* @param {String} subUA Parse this UA string instead of navigator.userAgent
2986
 
* @returns {Object} The Y.UA object
2987
 
*/
2988
 
YUI.Env.parseUA = function(subUA) {
2989
 
 
2990
 
    var numberify = function(s) {
2991
 
            var c = 0;
2992
 
            return parseFloat(s.replace(/\./g, function() {
2993
 
                return (c++ == 1) ? '' : '.';
2994
 
            }));
2995
 
        },
2996
 
 
2997
 
        win = Y.config.win,
2998
 
 
2999
 
        nav = win && win.navigator,
3000
 
 
3001
 
        o = {
3002
 
 
3003
 
        /**
3004
 
         * Internet Explorer version number or 0.  Example: 6
3005
 
         * @property ie
3006
 
         * @type float
3007
 
         * @static
3008
 
         */
3009
 
        ie: 0,
3010
 
 
3011
 
        /**
3012
 
         * Opera version number or 0.  Example: 9.2
3013
 
         * @property opera
3014
 
         * @type float
3015
 
         * @static
3016
 
         */
3017
 
        opera: 0,
3018
 
 
3019
 
        /**
3020
 
         * Gecko engine revision number.  Will evaluate to 1 if Gecko
3021
 
         * is detected but the revision could not be found. Other browsers
3022
 
         * will be 0.  Example: 1.8
3023
 
         * <pre>
3024
 
         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
3025
 
         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
3026
 
         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
3027
 
         * Firefox 3.0   <-- 1.9
3028
 
         * Firefox 3.5   <-- 1.91
3029
 
         * </pre>
3030
 
         * @property gecko
3031
 
         * @type float
3032
 
         * @static
3033
 
         */
3034
 
        gecko: 0,
3035
 
 
3036
 
        /**
3037
 
         * AppleWebKit version.  KHTML browsers that are not WebKit browsers
3038
 
         * will evaluate to 1, other browsers 0.  Example: 418.9
3039
 
         * <pre>
3040
 
         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
3041
 
         *                                   latest available for Mac OSX 10.3.
3042
 
         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
3043
 
         * Safari 2.0.4:         418     <-- preventDefault fixed
3044
 
         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
3045
 
         *                                   different versions of webkit
3046
 
         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
3047
 
         *                                   updated, but not updated
3048
 
         *                                   to the latest patch.
3049
 
         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
3050
 
         * SVG and many major issues fixed).
3051
 
         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
3052
 
         * update from 2.x via the 10.4.11 OS patch.
3053
 
         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
3054
 
         *                                   yahoo.com user agent hack removed.
3055
 
         * </pre>
3056
 
         * http://en.wikipedia.org/wiki/Safari_version_history
3057
 
         * @property webkit
3058
 
         * @type float
3059
 
         * @static
3060
 
         */
3061
 
        webkit: 0,
3062
 
 
3063
 
        /**
3064
 
         * Safari will be detected as webkit, but this property will also
3065
 
         * be populated with the Safari version number
3066
 
         * @property safari
3067
 
         * @type float
3068
 
         * @static
3069
 
         */
3070
 
        safari: 0,
3071
 
 
3072
 
        /**
3073
 
         * Chrome will be detected as webkit, but this property will also
3074
 
         * be populated with the Chrome version number
3075
 
         * @property chrome
3076
 
         * @type float
3077
 
         * @static
3078
 
         */
3079
 
        chrome: 0,
3080
 
 
3081
 
        /**
3082
 
         * The mobile property will be set to a string containing any relevant
3083
 
         * user agent information when a modern mobile browser is detected.
3084
 
         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
3085
 
         * devices with the WebKit-based browser, and Opera Mini.
3086
 
         * @property mobile
3087
 
         * @type string
3088
 
         * @default null
3089
 
         * @static
3090
 
         */
3091
 
        mobile: null,
3092
 
 
3093
 
        /**
3094
 
         * Adobe AIR version number or 0.  Only populated if webkit is detected.
3095
 
         * Example: 1.0
3096
 
         * @property air
3097
 
         * @type float
3098
 
         */
3099
 
        air: 0,
3100
 
        /**
3101
 
         * Detects Apple iPad's OS version
3102
 
         * @property ipad
3103
 
         * @type float
3104
 
         * @static
3105
 
         */
3106
 
        ipad: 0,
3107
 
        /**
3108
 
         * Detects Apple iPhone's OS version
3109
 
         * @property iphone
3110
 
         * @type float
3111
 
         * @static
3112
 
         */
3113
 
        iphone: 0,
3114
 
        /**
3115
 
         * Detects Apples iPod's OS version
3116
 
         * @property ipod
3117
 
         * @type float
3118
 
         * @static
3119
 
         */
3120
 
        ipod: 0,
3121
 
        /**
3122
 
         * General truthy check for iPad, iPhone or iPod
3123
 
         * @property ios
3124
 
         * @type float
3125
 
         * @default null
3126
 
         * @static
3127
 
         */
3128
 
        ios: null,
3129
 
        /**
3130
 
         * Detects Googles Android OS version
3131
 
         * @property android
3132
 
         * @type float
3133
 
         * @static
3134
 
         */
3135
 
        android: 0,
3136
 
        /**
3137
 
         * Detects Palms WebOS version
3138
 
         * @property webos
3139
 
         * @type float
3140
 
         * @static
3141
 
         */
3142
 
        webos: 0,
3143
 
 
3144
 
        /**
3145
 
         * Google Caja version number or 0.
3146
 
         * @property caja
3147
 
         * @type float
3148
 
         */
3149
 
        caja: nav && nav.cajaVersion,
3150
 
 
3151
 
        /**
3152
 
         * Set to true if the page appears to be in SSL
3153
 
         * @property secure
3154
 
         * @type boolean
3155
 
         * @static
3156
 
         */
3157
 
        secure: false,
3158
 
 
3159
 
        /**
3160
 
         * The operating system.  Currently only detecting windows or macintosh
3161
 
         * @property os
3162
 
         * @type string
3163
 
         * @default null
3164
 
         * @static
3165
 
         */
3166
 
        os: null
3167
 
 
3168
 
    },
3169
 
 
3170
 
    ua = subUA || nav && nav.userAgent,
3171
 
 
3172
 
    loc = win && win.location,
3173
 
 
3174
 
    href = loc && loc.href,
3175
 
 
3176
 
    m;
3177
 
 
3178
 
    o.secure = href && (href.toLowerCase().indexOf('https') === 0);
3179
 
 
3180
 
    if (ua) {
3181
 
 
3182
 
        if ((/windows|win32/i).test(ua)) {
3183
 
            o.os = 'windows';
3184
 
        } else if ((/macintosh/i).test(ua)) {
3185
 
            o.os = 'macintosh';
3186
 
        } else if ((/rhino/i).test(ua)) {
3187
 
            o.os = 'rhino';
3188
 
        }
3189
 
 
3190
 
        // Modern KHTML browsers should qualify as Safari X-Grade
3191
 
        if ((/KHTML/).test(ua)) {
3192
 
            o.webkit = 1;
3193
 
        }
3194
 
        // Modern WebKit browsers are at least X-Grade
3195
 
        m = ua.match(/AppleWebKit\/([^\s]*)/);
3196
 
        if (m && m[1]) {
3197
 
            o.webkit = numberify(m[1]);
3198
 
            o.safari = o.webkit;
3199
 
 
3200
 
            // Mobile browser check
3201
 
            if (/ Mobile\//.test(ua)) {
3202
 
                o.mobile = 'Apple'; // iPhone or iPod Touch
3203
 
 
3204
 
                m = ua.match(/OS ([^\s]*)/);
3205
 
                if (m && m[1]) {
3206
 
                    m = numberify(m[1].replace('_', '.'));
3207
 
                }
3208
 
                o.ios = m;
3209
 
                o.ipad = o.ipod = o.iphone = 0;
3210
 
 
3211
 
                m = ua.match(/iPad|iPod|iPhone/);
3212
 
                if (m && m[0]) {
3213
 
                    o[m[0].toLowerCase()] = o.ios;
3214
 
                }
3215
 
            } else {
3216
 
                m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
3217
 
                if (m) {
3218
 
                    // Nokia N-series, webOS, ex: NokiaN95
3219
 
                    o.mobile = m[0];
3220
 
                }
3221
 
                if (/webOS/.test(ua)) {
3222
 
                    o.mobile = 'WebOS';
3223
 
                    m = ua.match(/webOS\/([^\s]*);/);
3224
 
                    if (m && m[1]) {
3225
 
                        o.webos = numberify(m[1]);
3226
 
                    }
3227
 
                }
3228
 
                if (/ Android/.test(ua)) {
3229
 
                    if (/Mobile/.test(ua)) {
3230
 
                        o.mobile = 'Android';
3231
 
                    }
3232
 
                    m = ua.match(/Android ([^\s]*);/);
3233
 
                    if (m && m[1]) {
3234
 
                        o.android = numberify(m[1]);
3235
 
                    }
3236
 
 
3237
 
                }
3238
 
            }
3239
 
 
3240
 
            m = ua.match(/Chrome\/([^\s]*)/);
3241
 
            if (m && m[1]) {
3242
 
                o.chrome = numberify(m[1]); // Chrome
3243
 
                o.safari = 0; //Reset safari back to 0
3244
 
            } else {
3245
 
                m = ua.match(/AdobeAIR\/([^\s]*)/);
3246
 
                if (m) {
3247
 
                    o.air = m[0]; // Adobe AIR 1.0 or better
3248
 
                }
3249
 
            }
3250
 
        }
3251
 
 
3252
 
        if (!o.webkit) { // not webkit
3253
 
// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
3254
 
            m = ua.match(/Opera[\s\/]([^\s]*)/);
3255
 
            if (m && m[1]) {
3256
 
                o.opera = numberify(m[1]);
3257
 
                m = ua.match(/Version\/([^\s]*)/);
3258
 
                if (m && m[1]) {
3259
 
                    o.opera = numberify(m[1]); // opera 10+
3260
 
                }
3261
 
 
3262
 
                m = ua.match(/Opera Mini[^;]*/);
3263
 
 
3264
 
                if (m) {
3265
 
                    o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
3266
 
                }
3267
 
            } else { // not opera or webkit
3268
 
                m = ua.match(/MSIE\s([^;]*)/);
3269
 
                if (m && m[1]) {
3270
 
                    o.ie = numberify(m[1]);
3271
 
                } else { // not opera, webkit, or ie
3272
 
                    m = ua.match(/Gecko\/([^\s]*)/);
3273
 
                    if (m) {
3274
 
                        o.gecko = 1; // Gecko detected, look for revision
3275
 
                        m = ua.match(/rv:([^\s\)]*)/);
3276
 
                        if (m && m[1]) {
3277
 
                            o.gecko = numberify(m[1]);
3278
 
                        }
3279
 
                    }
3280
 
                }
3281
 
            }
3282
 
        }
3283
 
    }
3284
 
 
3285
 
    YUI.Env.UA = o;
3286
 
 
3287
 
    return o;
3288
 
};
3289
 
 
3290
 
 
3291
 
Y.UA = YUI.Env.UA || YUI.Env.parseUA();
3292
 
YUI.Env.aliases = {
3293
 
    "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
3294
 
    "app": ["controller","model","model-list","view"],
3295
 
    "attribute": ["attribute-base","attribute-complex"],
3296
 
    "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
3297
 
    "base": ["base-base","base-pluginhost","base-build"],
3298
 
    "cache": ["cache-base","cache-offline","cache-plugin"],
3299
 
    "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
3300
 
    "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
3301
 
    "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
3302
 
    "datatable": ["datatable-base","datatable-datasource","datatable-sort","datatable-scroll"],
3303
 
    "datatype": ["datatype-number","datatype-date","datatype-xml"],
3304
 
    "datatype-date": ["datatype-date-parse","datatype-date-format"],
3305
 
    "datatype-number": ["datatype-number-parse","datatype-number-format"],
3306
 
    "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
3307
 
    "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
3308
 
    "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
3309
 
    "editor": ["frame","selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
3310
 
    "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside"],
3311
 
    "event-custom": ["event-custom-base","event-custom-complex"],
3312
 
    "event-gestures": ["event-flick","event-move"],
3313
 
    "highlight": ["highlight-base","highlight-accentfold"],
3314
 
    "history": ["history-base","history-hash","history-hash-ie","history-html5"],
3315
 
    "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
3316
 
    "json": ["json-parse","json-stringify"],
3317
 
    "loader": ["loader-base","loader-rollup","loader-yui3"],
3318
 
    "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
3319
 
    "pluginhost": ["pluginhost-base","pluginhost-config"],
3320
 
    "querystring": ["querystring-parse","querystring-stringify"],
3321
 
    "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
3322
 
    "resize": ["resize-base","resize-proxy","resize-constrain"],
3323
 
    "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
3324
 
    "text": ["text-accentfold","text-wordbreak"],
3325
 
    "widget": ["widget-base","widget-htmlparser","widget-uievents","widget-skin"]
3326
 
};
3327
 
 
3328
 
 
3329
 
}, '3.4.1' );
3330
 
YUI.add('get', function(Y) {
3331
 
 
3332
 
/**
3333
 
 * Provides a mechanism to fetch remote resources and
3334
 
 * insert them into a document.
3335
 
 * @module yui
3336
 
 * @submodule get
3337
 
 */
3338
 
 
3339
 
/**
3340
 
 * Fetches and inserts one or more script or link nodes into the document
3341
 
 * @class Get
3342
 
 * @static
3343
 
 */
3344
 
 
3345
 
var ua = Y.UA,
3346
 
    L = Y.Lang,
3347
 
    TYPE_JS = 'text/javascript',
3348
 
    TYPE_CSS = 'text/css',
3349
 
    STYLESHEET = 'stylesheet',
3350
 
    SCRIPT = 'script',
3351
 
    AUTOPURGE = 'autopurge',
3352
 
    UTF8 = 'utf-8',
3353
 
    LINK = 'link',
3354
 
    ASYNC = 'async',
3355
 
    ALL = true,
3356
 
 
3357
 
    // FireFox does not support the onload event for link nodes, so
3358
 
    // there is no way to make the css requests synchronous. This means
3359
 
    // that the css rules in multiple files could be applied out of order
3360
 
    // in this browser if a later request returns before an earlier one.
3361
 
 
3362
 
    // Safari too.
3363
 
 
3364
 
    ONLOAD_SUPPORTED = {
3365
 
        script: ALL,
3366
 
        css: !(ua.webkit || ua.gecko)
3367
 
    },
3368
 
 
3369
 
    /**
3370
 
     * hash of queues to manage multiple requests
3371
 
     * @property queues
3372
 
     * @private
3373
 
     */
3374
 
    queues = {},
3375
 
 
3376
 
    /**
3377
 
     * queue index used to generate transaction ids
3378
 
     * @property qidx
3379
 
     * @type int
3380
 
     * @private
3381
 
     */
3382
 
    qidx = 0,
3383
 
 
3384
 
    /**
3385
 
     * interal property used to prevent multiple simultaneous purge
3386
 
     * processes
3387
 
     * @property purging
3388
 
     * @type boolean
3389
 
     * @private
3390
 
     */
3391
 
    purging,
3392
 
 
3393
 
    /**
3394
 
     * Clear timeout state 
3395
 
     * 
3396
 
     * @method _clearTimeout
3397
 
     * @param {Object} q Queue data
3398
 
     * @private
3399
 
     */
3400
 
    _clearTimeout = function(q) {
3401
 
        var timer = q.timer;
3402
 
        if (timer) {
3403
 
            clearTimeout(timer);
3404
 
            q.timer = null;
3405
 
        }
3406
 
    },
3407
 
 
3408
 
    /**
3409
 
     * Generates an HTML element, this is not appended to a document
3410
 
     * @method _node
3411
 
     * @param {string} type the type of element.
3412
 
     * @param {Object} attr the fixed set of attribute for the type.
3413
 
     * @param {Object} custAttrs optional Any custom attributes provided by the user.
3414
 
     * @param {Window} win optional window to create the element in.
3415
 
     * @return {HTMLElement} the generated node.
3416
 
     * @private
3417
 
     */
3418
 
    _node = function(type, attr, custAttrs, win) {
3419
 
        var w = win || Y.config.win,
3420
 
            d = w.document,
3421
 
            n = d.createElement(type),
3422
 
            i;
3423
 
 
3424
 
        if (custAttrs) {
3425
 
            Y.mix(attr, custAttrs);
3426
 
        }
3427
 
 
3428
 
        for (i in attr) {
3429
 
            if (attr[i] && attr.hasOwnProperty(i)) {
3430
 
                n.setAttribute(i, attr[i]);
3431
 
            }
3432
 
        }
3433
 
 
3434
 
        return n;
3435
 
    },
3436
 
 
3437
 
    /**
3438
 
     * Generates a link node
3439
 
     * @method _linkNode
3440
 
     * @param {string} url the url for the css file.
3441
 
     * @param {Window} win optional window to create the node in.
3442
 
     * @param {object} attributes optional attributes collection to apply to the
3443
 
     * new node.
3444
 
     * @return {HTMLElement} the generated node.
3445
 
     * @private
3446
 
     */
3447
 
    _linkNode = function(url, win, attributes) {
3448
 
        return _node(LINK, {
3449
 
                        id: Y.guid(),
3450
 
                        type: TYPE_CSS,
3451
 
                        rel: STYLESHEET,
3452
 
                        href: url
3453
 
                    }, attributes, win);
3454
 
    },
3455
 
 
3456
 
    /**
3457
 
     * Generates a script node
3458
 
     * @method _scriptNode
3459
 
     * @param {string} url the url for the script file.
3460
 
     * @param {Window} win optional window to create the node in.
3461
 
     * @param {object} attributes optional attributes collection to apply to the
3462
 
     * new node.
3463
 
     * @return {HTMLElement} the generated node.
3464
 
     * @private
3465
 
     */
3466
 
    _scriptNode = function(url, win, attributes) {
3467
 
        return _node(SCRIPT, {
3468
 
                        id: Y.guid(),
3469
 
                        type: TYPE_JS,
3470
 
                        src: url
3471
 
                    }, attributes, win);
3472
 
    },
3473
 
 
3474
 
    /**
3475
 
     * Returns the data payload for callback functions.
3476
 
     * @method _returnData
3477
 
     * @param {object} q the queue.
3478
 
     * @param {string} msg the result message.
3479
 
     * @param {string} result the status message from the request.
3480
 
     * @return {object} the state data from the request.
3481
 
     * @private
3482
 
     */
3483
 
    _returnData = function(q, msg, result) {
3484
 
        return {
3485
 
            tId: q.tId,
3486
 
            win: q.win,
3487
 
            data: q.data,
3488
 
            nodes: q.nodes,
3489
 
            msg: msg,
3490
 
            statusText: result,
3491
 
 
3492
 
            purge: function() {
3493
 
                _purge(this.tId);
3494
 
            }
3495
 
        };
3496
 
    },
3497
 
 
3498
 
    /**
3499
 
     * The transaction is finished
3500
 
     * @method _end
3501
 
     * @param {string} id the id of the request.
3502
 
     * @param {string} msg the result message.
3503
 
     * @param {string} result the status message from the request.
3504
 
     * @private
3505
 
     */
3506
 
    _end = function(id, msg, result) {
3507
 
        var q = queues[id],
3508
 
            onEnd = q && q.onEnd;
3509
 
 
3510
 
        q.finished = true;
3511
 
 
3512
 
        if (onEnd) {
3513
 
            onEnd.call(q.context, _returnData(q, msg, result));
3514
 
        }
3515
 
    },
3516
 
 
3517
 
    /**
3518
 
     * The request failed, execute fail handler with whatever
3519
 
     * was accomplished.  There isn't a failure case at the
3520
 
     * moment unless you count aborted transactions
3521
 
     * @method _fail
3522
 
     * @param {string} id the id of the request
3523
 
     * @private
3524
 
     */
3525
 
    _fail = function(id, msg) {
3526
 
        Y.log('get failure: ' + msg, 'warn', 'get');
3527
 
 
3528
 
        var q = queues[id],
3529
 
            onFailure = q.onFailure;
3530
 
 
3531
 
        _clearTimeout(q);
3532
 
 
3533
 
        if (onFailure) {
3534
 
            onFailure.call(q.context, _returnData(q, msg));
3535
 
        }
3536
 
 
3537
 
        _end(id, msg, 'failure');
3538
 
    },
3539
 
 
3540
 
 
3541
 
    /**
3542
 
     * Abort the transaction
3543
 
     * 
3544
 
     * @method _abort
3545
 
     * @param {Object} id
3546
 
     * @private
3547
 
     */
3548
 
    _abort = function(id) {
3549
 
        _fail(id, 'transaction ' + id + ' was aborted');
3550
 
    },
3551
 
 
3552
 
    /**
3553
 
     * The request is complete, so executing the requester's callback
3554
 
     * @method _complete
3555
 
     * @param {string} id the id of the request.
3556
 
     * @private
3557
 
     */
3558
 
    _complete = function(id) {
3559
 
        Y.log("Finishing transaction " + id, "info", "get");
3560
 
 
3561
 
        var q = queues[id],
3562
 
            onSuccess = q.onSuccess;
3563
 
 
3564
 
        _clearTimeout(q);
3565
 
 
3566
 
        if (q.aborted) {
3567
 
            _abort(id);
3568
 
        } else {
3569
 
 
3570
 
            if (onSuccess) {
3571
 
                onSuccess.call(q.context, _returnData(q));
3572
 
            }
3573
 
 
3574
 
            // 3.3.0 had undefined msg for this path.
3575
 
            _end(id, undefined, 'OK');
3576
 
        }
3577
 
    },
3578
 
 
3579
 
    /**
3580
 
     * Get node reference, from string
3581
 
     * 
3582
 
     * @method _getNodeRef
3583
 
     * @param {String|HTMLElement} nId The node id to find. If an HTMLElement is passed in, it will be returned.
3584
 
     * @param {String} tId Queue id, used to determine document for queue
3585
 
     * @private
3586
 
     */
3587
 
    _getNodeRef = function(nId, tId) {
3588
 
        var q = queues[tId],
3589
 
            n = (L.isString(nId)) ? q.win.document.getElementById(nId) : nId;
3590
 
        if (!n) {
3591
 
            _fail(tId, 'target node not found: ' + nId);
3592
 
        }
3593
 
 
3594
 
        return n;
3595
 
    },
3596
 
 
3597
 
    /**
3598
 
     * Removes the nodes for the specified queue
3599
 
     * @method _purge
3600
 
     * @param {string} tId the transaction id.
3601
 
     * @private
3602
 
     */
3603
 
    _purge = function(tId) {
3604
 
        var nodes, doc, parent, sibling, node, attr, insertBefore,
3605
 
            i, l,
3606
 
            q = queues[tId];
3607
 
 
3608
 
        if (q) {
3609
 
            nodes = q.nodes;
3610
 
            l = nodes.length;
3611
 
 
3612
 
            // TODO: Why is node.parentNode undefined? Which forces us to do this...
3613
 
            /*
3614
 
            doc = q.win.document;
3615
 
            parent = doc.getElementsByTagName('head')[0];
3616
 
            insertBefore = q.insertBefore || doc.getElementsByTagName('base')[0];
3617
 
 
3618
 
            if (insertBefore) {
3619
 
                sibling = _getNodeRef(insertBefore, tId);
3620
 
                if (sibling) {
3621
 
                    parent = sibling.parentNode;
3622
 
                }
3623
 
            }
3624
 
            */
3625
 
 
3626
 
            for (i = 0; i < l; i++) {
3627
 
                node = nodes[i];
3628
 
                parent = node.parentNode;
3629
 
 
3630
 
                if (node.clearAttributes) {
3631
 
                    node.clearAttributes();
3632
 
                } else {
3633
 
                    // This destroys parentNode ref, so we hold onto it above first.
3634
 
                    for (attr in node) {
3635
 
                        if (node.hasOwnProperty(attr)) {
3636
 
                            delete node[attr];
3637
 
                        }
3638
 
                    }
3639
 
                }
3640
 
 
3641
 
                parent.removeChild(node);
3642
 
            }
3643
 
        }
3644
 
 
3645
 
        q.nodes = [];
3646
 
    },
3647
 
 
3648
 
    /**
3649
 
     * Progress callback
3650
 
     * 
3651
 
     * @method _progress
3652
 
     * @param {string} id The id of the request.
3653
 
     * @param {string} The url which just completed.
3654
 
     * @private
3655
 
     */
3656
 
    _progress = function(id, url) {
3657
 
        var q = queues[id],
3658
 
            onProgress = q.onProgress,
3659
 
            o;
3660
 
 
3661
 
        if (onProgress) {
3662
 
            o = _returnData(q);
3663
 
            o.url = url;
3664
 
            onProgress.call(q.context, o);
3665
 
        }
3666
 
    },
3667
 
 
3668
 
    /**
3669
 
     * Timeout detected
3670
 
     * @method _timeout
3671
 
     * @param {string} id the id of the request.
3672
 
     * @private
3673
 
     */
3674
 
    _timeout = function(id) {
3675
 
        Y.log('Timeout ' + id, 'info', 'get');
3676
 
 
3677
 
        var q = queues[id],
3678
 
            onTimeout = q.onTimeout;
3679
 
 
3680
 
        if (onTimeout) {
3681
 
            onTimeout.call(q.context, _returnData(q));
3682
 
        }
3683
 
 
3684
 
        _end(id, 'timeout', 'timeout');
3685
 
    },
3686
 
 
3687
 
    /**
3688
 
     * onload callback
3689
 
     * @method _loaded
3690
 
     * @param {string} id the id of the request.
3691
 
     * @return {string} the result.
3692
 
     * @private
3693
 
     */
3694
 
    _loaded = function(id, url) {
3695
 
 
3696
 
        var q = queues[id],
3697
 
            sync = (q && !q.async);
3698
 
 
3699
 
        if (!q) {
3700
 
            return;
3701
 
        }
3702
 
 
3703
 
        if (sync) {
3704
 
            _clearTimeout(q);
3705
 
        }
3706
 
 
3707
 
        _progress(id, url);
3708
 
 
3709
 
        // TODO: Cleaning up flow to have a consistent end point
3710
 
 
3711
 
        // !q.finished check is for the async case,
3712
 
        // where scripts may still be loading when we've 
3713
 
        // already aborted. Ideally there should be a single path
3714
 
        // for this.
3715
 
 
3716
 
        if (!q.finished) { 
3717
 
            if (q.aborted) {
3718
 
                _abort(id);
3719
 
            } else {
3720
 
                if ((--q.remaining) === 0) {
3721
 
                    _complete(id);
3722
 
                } else if (sync) {
3723
 
                    _next(id);
3724
 
                }
3725
 
            }
3726
 
        }
3727
 
    },
3728
 
 
3729
 
    /**
3730
 
     * Detects when a node has been loaded.  In the case of
3731
 
     * script nodes, this does not guarantee that contained
3732
 
     * script is ready to use.
3733
 
     * @method _trackLoad
3734
 
     * @param {string} type the type of node to track.
3735
 
     * @param {HTMLElement} n the node to track.
3736
 
     * @param {string} id the id of the request.
3737
 
     * @param {string} url the url that is being loaded.
3738
 
     * @private
3739
 
     */
3740
 
    _trackLoad = function(type, n, id, url) {
3741
 
 
3742
 
        // TODO: Can we massage this to use ONLOAD_SUPPORTED[type]?
3743
 
 
3744
 
        // IE supports the readystatechange event for script and css nodes
3745
 
        // Opera only for script nodes.  Opera support onload for script
3746
 
        // nodes, but this doesn't fire when there is a load failure.
3747
 
        // The onreadystatechange appears to be a better way to respond
3748
 
        // to both success and failure.
3749
 
 
3750
 
        if (ua.ie) {
3751
 
 
3752
 
            n.onreadystatechange = function() {
3753
 
                var rs = this.readyState;
3754
 
                if ('loaded' === rs || 'complete' === rs) {
3755
 
                    // Y.log(id + " onreadstatechange " + url, "info", "get");
3756
 
                    n.onreadystatechange = null;
3757
 
                    _loaded(id, url);
3758
 
                }
3759
 
            };
3760
 
 
3761
 
        } else if (ua.webkit) {
3762
 
 
3763
 
            // webkit prior to 3.x is no longer supported
3764
 
            if (type === SCRIPT) {
3765
 
                // Safari 3.x supports the load event for script nodes (DOM2)
3766
 
                n.addEventListener('load', function() {
3767
 
                    _loaded(id, url);
3768
 
                }, false);
3769
 
            }
3770
 
 
3771
 
        } else {
3772
 
 
3773
 
            // FireFox and Opera support onload (but not DOM2 in FF) handlers for
3774
 
            // script nodes. Opera, but not FF, supports the onload event for link nodes.
3775
 
 
3776
 
            n.onload = function() {
3777
 
                // Y.log(id + " onload " + url, "info", "get");
3778
 
                _loaded(id, url);
3779
 
            };
3780
 
 
3781
 
            n.onerror = function(e) {
3782
 
                _fail(id, e + ': ' + url);
3783
 
            };
3784
 
        }
3785
 
    },
3786
 
 
3787
 
    _insertInDoc = function(node, id, win) {
3788
 
 
3789
 
        // Add it to the head or insert it before 'insertBefore'.  
3790
 
        // Work around IE bug if there is a base tag.
3791
 
        var q = queues[id],
3792
 
            doc = win.document,
3793
 
            insertBefore = q.insertBefore || doc.getElementsByTagName('base')[0],
3794
 
            sibling;
3795
 
 
3796
 
        if (insertBefore) {
3797
 
            sibling = _getNodeRef(insertBefore, id);
3798
 
            if (sibling) {
3799
 
                Y.log('inserting before: ' + insertBefore, 'info', 'get');
3800
 
                sibling.parentNode.insertBefore(node, sibling);
3801
 
            }
3802
 
        } else {
3803
 
            // 3.3.0 assumed head is always around.
3804
 
            doc.getElementsByTagName('head')[0].appendChild(node);
3805
 
        }
3806
 
    },
3807
 
 
3808
 
    /**
3809
 
     * Loads the next item for a given request
3810
 
     * @method _next
3811
 
     * @param {string} id the id of the request.
3812
 
     * @return {string} the result.
3813
 
     * @private
3814
 
     */
3815
 
    _next = function(id) {
3816
 
 
3817
 
        // Assigning out here for readability
3818
 
        var q = queues[id],
3819
 
            type = q.type,
3820
 
            attrs = q.attributes,
3821
 
            win = q.win,
3822
 
            timeout = q.timeout,
3823
 
            node,
3824
 
            url;
3825
 
 
3826
 
        if (q.url.length > 0) {
3827
 
 
3828
 
            url = q.url.shift();
3829
 
 
3830
 
            Y.log('attempting to load ' + url, 'info', 'get');
3831
 
 
3832
 
            // !q.timer ensures that this only happens once for async
3833
 
            if (timeout && !q.timer) {
3834
 
                q.timer = setTimeout(function() {
3835
 
                    _timeout(id);
3836
 
                }, timeout);
3837
 
            }
3838
 
 
3839
 
            if (type === SCRIPT) {
3840
 
                node = _scriptNode(url, win, attrs);
3841
 
            } else {
3842
 
                node = _linkNode(url, win, attrs);
3843
 
            }
3844
 
 
3845
 
            // add the node to the queue so we can return it in the callback 
3846
 
            q.nodes.push(node);
3847
 
 
3848
 
            _trackLoad(type, node, id, url);
3849
 
            _insertInDoc(node, id, win);
3850
 
    
3851
 
            if (!ONLOAD_SUPPORTED[type]) {
3852
 
                _loaded(id, url);
3853
 
            }
3854
 
 
3855
 
            if (q.async) {
3856
 
                // For sync, the _next call is chained in _loaded 
3857
 
                _next(id);
3858
 
            }
3859
 
        }
3860
 
    },
3861
 
 
3862
 
    /**
3863
 
     * Removes processed queues and corresponding nodes
3864
 
     * @method _autoPurge
3865
 
     * @private
3866
 
     */
3867
 
    _autoPurge = function() {
3868
 
        if (purging) {
3869
 
            return;
3870
 
        }
3871
 
        purging = true;
3872
 
 
3873
 
        var i, q;
3874
 
 
3875
 
        for (i in queues) {
3876
 
            if (queues.hasOwnProperty(i)) {
3877
 
                q = queues[i];
3878
 
                if (q.autopurge && q.finished) {
3879
 
                    _purge(q.tId);
3880
 
                    delete queues[i];
3881
 
                }
3882
 
            }
3883
 
        }
3884
 
 
3885
 
        purging = false;
3886
 
    },
3887
 
 
3888
 
    /**
3889
 
     * Saves the state for the request and begins loading
3890
 
     * the requested urls
3891
 
     * @method queue
3892
 
     * @param {string} type the type of node to insert.
3893
 
     * @param {string} url the url to load.
3894
 
     * @param {object} opts the hash of options for this request.
3895
 
     * @return {object} transaction object.
3896
 
     * @private
3897
 
     */
3898
 
    _queue = function(type, url, opts) {
3899
 
 
3900
 
        opts = opts || {};
3901
 
 
3902
 
        var id = 'q' + (qidx++),
3903
 
            thresh = opts.purgethreshold || Y.Get.PURGE_THRESH, 
3904
 
            q;
3905
 
 
3906
 
        if (qidx % thresh === 0) {
3907
 
            _autoPurge();
3908
 
        }
3909
 
 
3910
 
        // Merge to protect opts (grandfathered in).
3911
 
        q = queues[id] = Y.merge(opts);
3912
 
 
3913
 
        // Avoid mix, merge overhead. Known set of props.
3914
 
        q.tId = id;
3915
 
        q.type = type;
3916
 
        q.url = url;
3917
 
        q.finished = false;
3918
 
        q.nodes = [];
3919
 
 
3920
 
        q.win = q.win || Y.config.win;
3921
 
        q.context = q.context || q;
3922
 
        q.autopurge = (AUTOPURGE in q) ? q.autopurge : (type === SCRIPT) ? true : false;
3923
 
        q.attributes = q.attributes || {};
3924
 
        q.attributes.charset = opts.charset || q.attributes.charset || UTF8;
3925
 
 
3926
 
        if (ASYNC in q && type === SCRIPT) {
3927
 
            q.attributes.async = q.async;
3928
 
        }
3929
 
 
3930
 
        q.url = (L.isString(q.url)) ? [q.url] : q.url;
3931
 
 
3932
 
        // TODO: Do we really need to account for this developer error? 
3933
 
        // If the url is undefined, this is probably a trailing comma problem in IE.
3934
 
        if (!q.url[0]) {
3935
 
            q.url.shift();
3936
 
            Y.log('skipping empty url');
3937
 
        }
3938
 
 
3939
 
        q.remaining = q.url.length;
3940
 
 
3941
 
        _next(id);
3942
 
 
3943
 
        return {
3944
 
            tId: id
3945
 
        };
3946
 
    };
3947
 
 
3948
 
 
3949
 
Y.Get = {
3950
 
 
3951
 
    /**
3952
 
     * The number of request required before an automatic purge.
3953
 
     * Can be configured via the 'purgethreshold' config
3954
 
     * @property PURGE_THRESH
3955
 
     * @static
3956
 
     * @type int
3957
 
     * @default 20
3958
 
     * @private
3959
 
     */
3960
 
    PURGE_THRESH: 20,
3961
 
 
3962
 
    /**
3963
 
     * Abort a transaction
3964
 
     * @method abort
3965
 
     * @static
3966
 
     * @param {string|object} o Either the tId or the object returned from
3967
 
     * script() or css().
3968
 
     */
3969
 
    abort : function(o) {
3970
 
        var id = (L.isString(o)) ? o : o.tId,
3971
 
            q = queues[id];
3972
 
 
3973
 
        if (q) {
3974
 
            Y.log('Aborting ' + id, 'info', 'get');
3975
 
            q.aborted = true;
3976
 
        }
3977
 
    },
3978
 
 
3979
 
    /**
3980
 
     * Fetches and inserts one or more script nodes into the head
3981
 
     * of the current document or the document in a specified window.
3982
 
     *
3983
 
     * @method script
3984
 
     * @static
3985
 
     * @param {string|string[]} url the url or urls to the script(s).
3986
 
     * @param {object} opts Options:
3987
 
     * <dl>
3988
 
     * <dt>onSuccess</dt>
3989
 
     * <dd>
3990
 
     * callback to execute when the script(s) are finished loading
3991
 
     * The callback receives an object back with the following
3992
 
     * data:
3993
 
     * <dl>
3994
 
     * <dt>win</dt>
3995
 
     * <dd>the window the script(s) were inserted into</dd>
3996
 
     * <dt>data</dt>
3997
 
     * <dd>the data object passed in when the request was made</dd>
3998
 
     * <dt>nodes</dt>
3999
 
     * <dd>An array containing references to the nodes that were
4000
 
     * inserted</dd>
4001
 
     * <dt>purge</dt>
4002
 
     * <dd>A function that, when executed, will remove the nodes
4003
 
     * that were inserted</dd>
4004
 
     * <dt>
4005
 
     * </dl>
4006
 
     * </dd>
4007
 
     * <dt>onTimeout</dt>
4008
 
     * <dd>
4009
 
     * callback to execute when a timeout occurs.
4010
 
     * The callback receives an object back with the following
4011
 
     * data:
4012
 
     * <dl>
4013
 
     * <dt>win</dt>
4014
 
     * <dd>the window the script(s) were inserted into</dd>
4015
 
     * <dt>data</dt>
4016
 
     * <dd>the data object passed in when the request was made</dd>
4017
 
     * <dt>nodes</dt>
4018
 
     * <dd>An array containing references to the nodes that were
4019
 
     * inserted</dd>
4020
 
     * <dt>purge</dt>
4021
 
     * <dd>A function that, when executed, will remove the nodes
4022
 
     * that were inserted</dd>
4023
 
     * <dt>
4024
 
     * </dl>
4025
 
     * </dd>
4026
 
     * <dt>onEnd</dt>
4027
 
     * <dd>a function that executes when the transaction finishes,
4028
 
     * regardless of the exit path</dd>
4029
 
     * <dt>onFailure</dt>
4030
 
     * <dd>
4031
 
     * callback to execute when the script load operation fails
4032
 
     * The callback receives an object back with the following
4033
 
     * data:
4034
 
     * <dl>
4035
 
     * <dt>win</dt>
4036
 
     * <dd>the window the script(s) were inserted into</dd>
4037
 
     * <dt>data</dt>
4038
 
     * <dd>the data object passed in when the request was made</dd>
4039
 
     * <dt>nodes</dt>
4040
 
     * <dd>An array containing references to the nodes that were
4041
 
     * inserted successfully</dd>
4042
 
     * <dt>purge</dt>
4043
 
     * <dd>A function that, when executed, will remove any nodes
4044
 
     * that were inserted</dd>
4045
 
     * <dt>
4046
 
     * </dl>
4047
 
     * </dd>
4048
 
     * <dt>onProgress</dt>
4049
 
     * <dd>callback to execute when each individual file is done loading 
4050
 
     * (useful when passing in an array of js files). Receives the same
4051
 
     * payload as onSuccess, with the addition of a <code>url</code> 
4052
 
     * property, which identifies the file which was loaded.</dd>
4053
 
     * <dt>async</dt>
4054
 
     * <dd>
4055
 
     * <p>When passing in an array of JS files, setting this flag to true 
4056
 
     * will insert them into the document in parallel, as opposed to the 
4057
 
     * default behavior, which is to chain load them serially. It will also
4058
 
     * set the async attribute on the script node to true.</p> 
4059
 
     * <p>Setting async:true
4060
 
     * will lead to optimal file download performance allowing the browser to
4061
 
     * download multiple scripts in parallel, and execute them as soon as they
4062
 
     * are available.</p>  
4063
 
     * <p>Note that async:true does not guarantee execution order of the 
4064
 
     * scripts being downloaded. They are executed in whichever order they 
4065
 
     * are received.</p>
4066
 
     * </dd>
4067
 
     * <dt>context</dt>
4068
 
     * <dd>the execution context for the callbacks</dd>
4069
 
     * <dt>win</dt>
4070
 
     * <dd>a window other than the one the utility occupies</dd>
4071
 
     * <dt>autopurge</dt>
4072
 
     * <dd>
4073
 
     * setting to true will let the utilities cleanup routine purge
4074
 
     * the script once loaded
4075
 
     * </dd>
4076
 
     * <dt>purgethreshold</dt>
4077
 
     * <dd>
4078
 
     * The number of transaction before autopurge should be initiated
4079
 
     * </dd>
4080
 
     * <dt>data</dt>
4081
 
     * <dd>
4082
 
     * data that is supplied to the callback when the script(s) are
4083
 
     * loaded.
4084
 
     * </dd>
4085
 
     * <dt>insertBefore</dt>
4086
 
     * <dd>node or node id that will become the new node's nextSibling.
4087
 
     * If this is not specified, nodes will be inserted before a base
4088
 
     * tag should it exist.  Otherwise, the nodes will be appended to the
4089
 
     * end of the document head.</dd>
4090
 
     * </dl>
4091
 
     * <dt>charset</dt>
4092
 
     * <dd>Node charset, default utf-8 (deprecated, use the attributes
4093
 
     * config)</dd>
4094
 
     * <dt>attributes</dt>
4095
 
     * <dd>An object literal containing additional attributes to add to
4096
 
     * the link tags</dd>
4097
 
     * <dt>timeout</dt>
4098
 
     * <dd>Number of milliseconds to wait before aborting and firing
4099
 
     * the timeout event</dd>
4100
 
     * <pre>
4101
 
     * &nbsp; Y.Get.script(
4102
 
     * &nbsp; ["http://yui.yahooapis.com/2.5.2/build/yahoo/yahoo-min.js",
4103
 
     * &nbsp;  "http://yui.yahooapis.com/2.5.2/build/event/event-min.js"],
4104
 
     * &nbsp; &#123;
4105
 
     * &nbsp;   onSuccess: function(o) &#123;
4106
 
     * &nbsp;     this.log("won't cause error because Y is the context");
4107
 
     * &nbsp;     Y.log(o.data); // foo
4108
 
     * &nbsp;     Y.log(o.nodes.length === 2) // true
4109
 
     * &nbsp;     // o.purge(); // optionally remove the script nodes
4110
 
     * &nbsp;                   // immediately
4111
 
     * &nbsp;   &#125;,
4112
 
     * &nbsp;   onFailure: function(o) &#123;
4113
 
     * &nbsp;     Y.log("transaction failed");
4114
 
     * &nbsp;   &#125;,
4115
 
     * &nbsp;   onTimeout: function(o) &#123;
4116
 
     * &nbsp;     Y.log("transaction timed out");
4117
 
     * &nbsp;   &#125;,
4118
 
     * &nbsp;   data: "foo",
4119
 
     * &nbsp;   timeout: 10000, // 10 second timeout
4120
 
     * &nbsp;   context: Y, // make the YUI instance
4121
 
     * &nbsp;   // win: otherframe // target another window/frame
4122
 
     * &nbsp;   autopurge: true // allow the utility to choose when to
4123
 
     * &nbsp;                   // remove the nodes
4124
 
     * &nbsp;   purgetheshold: 1 // purge previous transaction before
4125
 
     * &nbsp;                    // next transaction
4126
 
     * &nbsp; &#125;);.
4127
 
     * </pre>
4128
 
     * @return {tId: string} an object containing info about the
4129
 
     * transaction.
4130
 
     */
4131
 
    script: function(url, opts) {
4132
 
        return _queue(SCRIPT, url, opts);
4133
 
    },
4134
 
 
4135
 
    /**
4136
 
     * Fetches and inserts one or more css link nodes into the
4137
 
     * head of the current document or the document in a specified
4138
 
     * window.
4139
 
     * @method css
4140
 
     * @static
4141
 
     * @param {string} url the url or urls to the css file(s).
4142
 
     * @param {object} opts Options:
4143
 
     * <dl>
4144
 
     * <dt>onSuccess</dt>
4145
 
     * <dd>
4146
 
     * callback to execute when the css file(s) are finished loading
4147
 
     * The callback receives an object back with the following
4148
 
     * data:
4149
 
     * <dl>win</dl>
4150
 
     * <dd>the window the link nodes(s) were inserted into</dd>
4151
 
     * <dt>data</dt>
4152
 
     * <dd>the data object passed in when the request was made</dd>
4153
 
     * <dt>nodes</dt>
4154
 
     * <dd>An array containing references to the nodes that were
4155
 
     * inserted</dd>
4156
 
     * <dt>purge</dt>
4157
 
     * <dd>A function that, when executed, will remove the nodes
4158
 
     * that were inserted</dd>
4159
 
     * <dt>
4160
 
     * </dl>
4161
 
     * </dd>
4162
 
     * <dt>onProgress</dt>
4163
 
     * <dd>callback to execute when each individual file is done loading (useful when passing in an array of css files). Receives the same
4164
 
     * payload as onSuccess, with the addition of a <code>url</code> property, which identifies the file which was loaded. Currently only useful for non Webkit/Gecko browsers,
4165
 
     * where onload for css is detected accurately.</dd>
4166
 
     * <dt>async</dt>
4167
 
     * <dd>When passing in an array of css files, setting this flag to true will insert them
4168
 
     * into the document in parallel, as oppposed to the default behavior, which is to chain load them (where possible). 
4169
 
     * This flag is more useful for scripts currently, since for css Get only chains if not Webkit/Gecko.</dd>
4170
 
     * <dt>context</dt>
4171
 
     * <dd>the execution context for the callbacks</dd>
4172
 
     * <dt>win</dt>
4173
 
     * <dd>a window other than the one the utility occupies</dd>
4174
 
     * <dt>data</dt>
4175
 
     * <dd>
4176
 
     * data that is supplied to the callbacks when the nodes(s) are
4177
 
     * loaded.
4178
 
     * </dd>
4179
 
     * <dt>insertBefore</dt>
4180
 
     * <dd>node or node id that will become the new node's nextSibling</dd>
4181
 
     * <dt>charset</dt>
4182
 
     * <dd>Node charset, default utf-8 (deprecated, use the attributes
4183
 
     * config)</dd>
4184
 
     * <dt>attributes</dt>
4185
 
     * <dd>An object literal containing additional attributes to add to
4186
 
     * the link tags</dd>
4187
 
     * </dl>
4188
 
     * <pre>
4189
 
     * Y.Get.css("http://localhost/css/menu.css");
4190
 
     * </pre>
4191
 
     * <pre>
4192
 
     * &nbsp; Y.Get.css(
4193
 
     * &nbsp; ["http://localhost/css/menu.css",
4194
 
     * &nbsp;  "http://localhost/css/logger.css"], &#123;
4195
 
     * &nbsp;   insertBefore: 'custom-styles' // nodes will be inserted
4196
 
     * &nbsp;                                 // before the specified node
4197
 
     * &nbsp; &#125;);.
4198
 
     * </pre>
4199
 
     * @return {tId: string} an object containing info about the
4200
 
     * transaction.
4201
 
     */
4202
 
    css: function(url, opts) {
4203
 
        return _queue('css', url, opts);
4204
 
    }
4205
 
};
4206
 
 
4207
 
 
4208
 
}, '3.4.1' ,{requires:['yui-base']});
4209
 
YUI.add('features', function(Y) {
4210
 
 
4211
 
var feature_tests = {};
4212
 
 
4213
 
Y.mix(Y.namespace('Features'), {
4214
 
 
4215
 
    tests: feature_tests,
4216
 
 
4217
 
    add: function(cat, name, o) {
4218
 
        feature_tests[cat] = feature_tests[cat] || {};
4219
 
        feature_tests[cat][name] = o;
4220
 
    },
4221
 
 
4222
 
    all: function(cat, args) {
4223
 
        var cat_o = feature_tests[cat],
4224
 
            // results = {};
4225
 
            result = [];
4226
 
        if (cat_o) {
4227
 
            Y.Object.each(cat_o, function(v, k) {
4228
 
                result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
4229
 
            });
4230
 
        }
4231
 
 
4232
 
        return (result.length) ? result.join(';') : '';
4233
 
    },
4234
 
 
4235
 
    test: function(cat, name, args) {
4236
 
        args = args || [];
4237
 
        var result, ua, test,
4238
 
            cat_o = feature_tests[cat],
4239
 
            feature = cat_o && cat_o[name];
4240
 
 
4241
 
        if (!feature) {
4242
 
            Y.log('Feature test ' + cat + ', ' + name + ' not found');
4243
 
        } else {
4244
 
 
4245
 
            result = feature.result;
4246
 
 
4247
 
            if (Y.Lang.isUndefined(result)) {
4248
 
 
4249
 
                ua = feature.ua;
4250
 
                if (ua) {
4251
 
                    result = (Y.UA[ua]);
4252
 
                }
4253
 
 
4254
 
                test = feature.test;
4255
 
                if (test && ((!ua) || result)) {
4256
 
                    result = test.apply(Y, args);
4257
 
                }
4258
 
 
4259
 
                feature.result = result;
4260
 
            }
4261
 
        }
4262
 
 
4263
 
        return result;
4264
 
    }
4265
 
});
4266
 
 
4267
 
// Y.Features.add("load", "1", {});
4268
 
// Y.Features.test("load", "1");
4269
 
// caps=1:1;2:0;3:1;
4270
 
 
4271
 
/* This file is auto-generated by src/loader/scripts/meta_join.py */
4272
 
var add = Y.Features.add;
4273
 
// graphics-svg.js
4274
 
add('load', '0', {
4275
 
    "name": "graphics-svg", 
4276
 
    "test": function(Y) {
4277
 
    var DOCUMENT = Y.config.doc;
4278
 
        return (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
4279
 
}, 
4280
 
    "trigger": "graphics"
4281
 
});
4282
 
// ie-base-test.js
4283
 
add('load', '1', {
4284
 
    "name": "event-base-ie", 
4285
 
    "test": function(Y) {
4286
 
    var imp = Y.config.doc && Y.config.doc.implementation;
4287
 
    return (imp && (!imp.hasFeature('Events', '2.0')));
4288
 
}, 
4289
 
    "trigger": "node-base"
4290
 
});
4291
 
// graphics-vml.js
4292
 
add('load', '2', {
4293
 
    "name": "graphics-vml", 
4294
 
    "test": function(Y) {
4295
 
    var DOCUMENT = Y.config.doc,
4296
 
                canvas = DOCUMENT && DOCUMENT.createElement("canvas");
4297
 
    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
4298
 
}, 
4299
 
    "trigger": "graphics"
4300
 
});
4301
 
// ie-style-test.js
4302
 
add('load', '3', {
4303
 
    "name": "dom-style-ie", 
4304
 
    "test": function (Y) {
4305
 
 
4306
 
    var testFeature = Y.Features.test,
4307
 
        addFeature = Y.Features.add,
4308
 
        WINDOW = Y.config.win,
4309
 
        DOCUMENT = Y.config.doc,
4310
 
        DOCUMENT_ELEMENT = 'documentElement',
4311
 
        ret = false;
4312
 
 
4313
 
    addFeature('style', 'computedStyle', {
4314
 
        test: function() {
4315
 
            return WINDOW && 'getComputedStyle' in WINDOW;
4316
 
        }
4317
 
    });
4318
 
 
4319
 
    addFeature('style', 'opacity', {
4320
 
        test: function() {
4321
 
            return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
4322
 
        }
4323
 
    });
4324
 
 
4325
 
    ret =  (!testFeature('style', 'opacity') &&
4326
 
            !testFeature('style', 'computedStyle'));
4327
 
 
4328
 
    return ret;
4329
 
}, 
4330
 
    "trigger": "dom-style"
4331
 
});
4332
 
// transition-test.js
4333
 
add('load', '4', {
4334
 
    "name": "transition-timer", 
4335
 
    "test": function (Y) {
4336
 
    var DOCUMENT = Y.config.doc,
4337
 
        node = (DOCUMENT) ? DOCUMENT.documentElement: null,
4338
 
        ret = true;
4339
 
 
4340
 
    if (node && node.style) {
4341
 
        ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style);
4342
 
    } 
4343
 
 
4344
 
    return ret;
4345
 
}, 
4346
 
    "trigger": "transition"
4347
 
});
4348
 
// 0
4349
 
add('load', '5', {
4350
 
    "name": "widget-base-ie", 
4351
 
    "trigger": "widget-base", 
4352
 
    "ua": "ie"
4353
 
});
4354
 
// autocomplete-list-keys-sniff.js
4355
 
add('load', '6', {
4356
 
    "name": "autocomplete-list-keys", 
4357
 
    "test": function (Y) {
4358
 
    // Only add keyboard support to autocomplete-list if this doesn't appear to
4359
 
    // be an iOS or Android-based mobile device.
4360
 
    //
4361
 
    // There's currently no feasible way to actually detect whether a device has
4362
 
    // a hardware keyboard, so this sniff will have to do. It can easily be
4363
 
    // overridden by manually loading the autocomplete-list-keys module.
4364
 
    //
4365
 
    // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
4366
 
    // doesn't fire the keyboard events used by AutoCompleteList, so there's
4367
 
    // no point loading the -keys module even when a bluetooth keyboard may be
4368
 
    // available.
4369
 
    return !(Y.UA.ios || Y.UA.android);
4370
 
}, 
4371
 
    "trigger": "autocomplete-list"
4372
 
});
4373
 
// graphics-canvas.js
4374
 
add('load', '7', {
4375
 
    "name": "graphics-canvas-default", 
4376
 
    "test": function(Y) {
4377
 
    var DOCUMENT = Y.config.doc,
4378
 
                canvas = DOCUMENT && DOCUMENT.createElement("canvas");
4379
 
        return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (canvas && canvas.getContext && canvas.getContext("2d")));
4380
 
}, 
4381
 
    "trigger": "graphics"
4382
 
});
4383
 
// dd-gestures-test.js
4384
 
add('load', '8', {
4385
 
    "name": "dd-gestures", 
4386
 
    "test": function(Y) {
4387
 
    return (Y.config.win && ('ontouchstart' in Y.config.win && !Y.UA.chrome));
4388
 
}, 
4389
 
    "trigger": "dd-drag"
4390
 
});
4391
 
// selector-test.js
4392
 
add('load', '9', {
4393
 
    "name": "selector-css2", 
4394
 
    "test": function (Y) {
4395
 
    var DOCUMENT = Y.config.doc,
4396
 
        ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
4397
 
 
4398
 
    return ret;
4399
 
}, 
4400
 
    "trigger": "selector"
4401
 
});
4402
 
// history-hash-ie-test.js
4403
 
add('load', '10', {
4404
 
    "name": "history-hash-ie", 
4405
 
    "test": function (Y) {
4406
 
    var docMode = Y.config.doc && Y.config.doc.documentMode;
4407
 
 
4408
 
    return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
4409
 
            !docMode || docMode < 8);
4410
 
}, 
4411
 
    "trigger": "history-hash"
4412
 
});
4413
 
 
4414
 
 
4415
 
}, '3.4.1' ,{requires:['yui-base']});
4416
 
YUI.add('intl-base', function(Y) {
4417
 
 
4418
 
/**
4419
 
 * The Intl utility provides a central location for managing sets of
4420
 
 * localized resources (strings and formatting patterns).
4421
 
 *
4422
 
 * @class Intl
4423
 
 * @uses EventTarget
4424
 
 * @static
4425
 
 */
4426
 
 
4427
 
var SPLIT_REGEX = /[, ]/;
4428
 
 
4429
 
Y.mix(Y.namespace('Intl'), {
4430
 
 
4431
 
 /**
4432
 
    * Returns the language among those available that
4433
 
    * best matches the preferred language list, using the Lookup
4434
 
    * algorithm of BCP 47.
4435
 
    * If none of the available languages meets the user's preferences,
4436
 
    * then "" is returned.
4437
 
    * Extended language ranges are not supported.
4438
 
    *
4439
 
    * @method lookupBestLang
4440
 
    * @param {String[] | String} preferredLanguages The list of preferred
4441
 
    * languages in descending preference order, represented as BCP 47
4442
 
    * language tags. A string array or a comma-separated list.
4443
 
    * @param {String[]} availableLanguages The list of languages
4444
 
    * that the application supports, represented as BCP 47 language
4445
 
    * tags.
4446
 
    *
4447
 
    * @return {String} The available language that best matches the
4448
 
    * preferred language list, or "".
4449
 
    * @since 3.1.0
4450
 
    */
4451
 
    lookupBestLang: function(preferredLanguages, availableLanguages) {
4452
 
 
4453
 
        var i, language, result, index;
4454
 
 
4455
 
        // check whether the list of available languages contains language;
4456
 
        // if so return it
4457
 
        function scan(language) {
4458
 
            var i;
4459
 
            for (i = 0; i < availableLanguages.length; i += 1) {
4460
 
                if (language.toLowerCase() ===
4461
 
                            availableLanguages[i].toLowerCase()) {
4462
 
                    return availableLanguages[i];
4463
 
                }
4464
 
            }
4465
 
        }
4466
 
 
4467
 
        if (Y.Lang.isString(preferredLanguages)) {
4468
 
            preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
4469
 
        }
4470
 
 
4471
 
        for (i = 0; i < preferredLanguages.length; i += 1) {
4472
 
            language = preferredLanguages[i];
4473
 
            if (!language || language === '*') {
4474
 
                continue;
4475
 
            }
4476
 
            // check the fallback sequence for one language
4477
 
            while (language.length > 0) {
4478
 
                result = scan(language);
4479
 
                if (result) {
4480
 
                    return result;
4481
 
                } else {
4482
 
                    index = language.lastIndexOf('-');
4483
 
                    if (index >= 0) {
4484
 
                        language = language.substring(0, index);
4485
 
                        // one-character subtags get cut along with the
4486
 
                        // following subtag
4487
 
                        if (index >= 2 && language.charAt(index - 2) === '-') {
4488
 
                            language = language.substring(0, index - 2);
4489
 
                        }
4490
 
                    } else {
4491
 
                        // nothing available for this language
4492
 
                        break;
4493
 
                    }
4494
 
                }
4495
 
            }
4496
 
        }
4497
 
 
4498
 
        return '';
4499
 
    }
4500
 
});
4501
 
 
4502
 
 
4503
 
}, '3.4.1' ,{requires:['yui-base']});
4504
 
YUI.add('yui-log', function(Y) {
4505
 
 
4506
 
/**
4507
 
 * Provides console log capability and exposes a custom event for
4508
 
 * console implementations. This module is a `core` YUI module, <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
4509
 
 *
4510
 
 * @module yui
4511
 
 * @submodule yui-log
4512
 
 */
4513
 
 
4514
 
var INSTANCE = Y,
4515
 
    LOGEVENT = 'yui:log',
4516
 
    UNDEFINED = 'undefined',
4517
 
    LEVELS = { debug: 1,
4518
 
               info: 1,
4519
 
               warn: 1,
4520
 
               error: 1 };
4521
 
 
4522
 
/**
4523
 
 * If the 'debug' config is true, a 'yui:log' event will be
4524
 
 * dispatched, which the Console widget and anything else
4525
 
 * can consume.  If the 'useBrowserConsole' config is true, it will
4526
 
 * write to the browser console if available.  YUI-specific log
4527
 
 * messages will only be present in the -debug versions of the
4528
 
 * JS files.  The build system is supposed to remove log statements
4529
 
 * from the raw and minified versions of the files.
4530
 
 *
4531
 
 * @method log
4532
 
 * @for YUI
4533
 
 * @param  {String}  msg  The message to log.
4534
 
 * @param  {String}  cat  The log category for the message.  Default
4535
 
 *                        categories are "info", "warn", "error", time".
4536
 
 *                        Custom categories can be used as well. (opt).
4537
 
 * @param  {String}  src  The source of the the message (opt).
4538
 
 * @param  {boolean} silent If true, the log event won't fire.
4539
 
 * @return {YUI}      YUI instance.
4540
 
 */
4541
 
INSTANCE.log = function(msg, cat, src, silent) {
4542
 
    var bail, excl, incl, m, f,
4543
 
        Y = INSTANCE,
4544
 
        c = Y.config,
4545
 
        publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
4546
 
    // suppress log message if the config is off or the event stack
4547
 
    // or the event call stack contains a consumer of the yui:log event
4548
 
    if (c.debug) {
4549
 
        // apply source filters
4550
 
        if (src) {
4551
 
            excl = c.logExclude;
4552
 
            incl = c.logInclude;
4553
 
            if (incl && !(src in incl)) {
4554
 
                bail = 1;
4555
 
            } else if (incl && (src in incl)) {
4556
 
                bail = !incl[src];
4557
 
            } else if (excl && (src in excl)) {
4558
 
                bail = excl[src];
4559
 
            }
4560
 
        }
4561
 
        if (!bail) {
4562
 
            if (c.useBrowserConsole) {
4563
 
                m = (src) ? src + ': ' + msg : msg;
4564
 
                if (Y.Lang.isFunction(c.logFn)) {
4565
 
                    c.logFn.call(Y, msg, cat, src);
4566
 
                } else if (typeof console != UNDEFINED && console.log) {
4567
 
                    f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
4568
 
                    console[f](m);
4569
 
                } else if (typeof opera != UNDEFINED) {
4570
 
                    opera.postError(m);
4571
 
                }
4572
 
            }
4573
 
 
4574
 
            if (publisher && !silent) {
4575
 
 
4576
 
                if (publisher == Y && (!publisher.getEvent(LOGEVENT))) {
4577
 
                    publisher.publish(LOGEVENT, {
4578
 
                        broadcast: 2
4579
 
                    });
4580
 
                }
4581
 
 
4582
 
                publisher.fire(LOGEVENT, {
4583
 
                    msg: msg,
4584
 
                    cat: cat,
4585
 
                    src: src
4586
 
                });
4587
 
            }
4588
 
        }
4589
 
    }
4590
 
 
4591
 
    return Y;
4592
 
};
4593
 
 
4594
 
/**
4595
 
 * Write a system message.  This message will be preserved in the
4596
 
 * minified and raw versions of the YUI files, unlike log statements.
4597
 
 * @method message
4598
 
 * @for YUI
4599
 
 * @param  {String}  msg  The message to log.
4600
 
 * @param  {String}  cat  The log category for the message.  Default
4601
 
 *                        categories are "info", "warn", "error", time".
4602
 
 *                        Custom categories can be used as well. (opt).
4603
 
 * @param  {String}  src  The source of the the message (opt).
4604
 
 * @param  {boolean} silent If true, the log event won't fire.
4605
 
 * @return {YUI}      YUI instance.
4606
 
 */
4607
 
INSTANCE.message = function() {
4608
 
    return INSTANCE.log.apply(INSTANCE, arguments);
4609
 
};
4610
 
 
4611
 
 
4612
 
}, '3.4.1' ,{requires:['yui-base']});
4613
 
YUI.add('yui-later', function(Y) {
4614
 
 
4615
 
/**
4616
 
 * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module, <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
4617
 
 *
4618
 
 * @module yui
4619
 
 * @submodule yui-later
4620
 
 */
4621
 
 
4622
 
var NO_ARGS = [];
4623
 
 
4624
 
/**
4625
 
 * Executes the supplied function in the context of the supplied
4626
 
 * object 'when' milliseconds later.  Executes the function a
4627
 
 * single time unless periodic is set to true.
4628
 
 * @for YUI
4629
 
 * @method later
4630
 
 * @param when {int} the number of milliseconds to wait until the fn
4631
 
 * is executed.
4632
 
 * @param o the context object.
4633
 
 * @param fn {Function|String} the function to execute or the name of
4634
 
 * the method in the 'o' object to execute.
4635
 
 * @param data [Array] data that is provided to the function.  This
4636
 
 * accepts either a single item or an array.  If an array is provided,
4637
 
 * the function is executed with one parameter for each array item.
4638
 
 * If you need to pass a single array parameter, it needs to be wrapped
4639
 
 * in an array [myarray].
4640
 
 *
4641
 
 * Note: native methods in IE may not have the call and apply methods.
4642
 
 * In this case, it will work, but you are limited to four arguments.
4643
 
 *
4644
 
 * @param periodic {boolean} if true, executes continuously at supplied
4645
 
 * interval until canceled.
4646
 
 * @return {object} a timer object. Call the cancel() method on this
4647
 
 * object to stop the timer.
4648
 
 */
4649
 
Y.later = function(when, o, fn, data, periodic) {
4650
 
    when = when || 0;
4651
 
    data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : data;
4652
 
 
4653
 
    var cancelled = false,
4654
 
        method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
4655
 
        wrapper = function() {
4656
 
            // IE 8- may execute a setInterval callback one last time
4657
 
            // after clearInterval was called, so in order to preserve
4658
 
            // the cancel() === no more runny-run, we have to jump through
4659
 
            // an extra hoop.
4660
 
            if (!cancelled) {
4661
 
                if (!method.apply) {
4662
 
                    method(data[0], data[1], data[2], data[3]);
4663
 
                } else {
4664
 
                    method.apply(o, data || NO_ARGS);
4665
 
                }
4666
 
            }
4667
 
        },
4668
 
        id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
4669
 
 
4670
 
    return {
4671
 
        id: id,
4672
 
        interval: periodic,
4673
 
        cancel: function() {
4674
 
            cancelled = true;
4675
 
            if (this.interval) {
4676
 
                clearInterval(id);
4677
 
            } else {
4678
 
                clearTimeout(id);
4679
 
            }
4680
 
        }
4681
 
    };
4682
 
};
4683
 
 
4684
 
Y.Lang.later = Y.later;
4685
 
 
4686
 
 
4687
 
 
4688
 
}, '3.4.1' ,{requires:['yui-base']});
4689
 
 
4690
 
 
4691
 
YUI.add('yui', function(Y){}, '3.4.1' ,{use:['yui-base','get','features','intl-base','yui-log','yui-later']});
4692
 
 
4693
 
YUI.add('oop', function(Y) {
4694
 
 
4695
 
/**
4696
 
Adds object inheritance and manipulation utilities to the YUI instance. This
4697
 
module is required by most YUI components.
4698
 
 
4699
 
@module oop
4700
 
**/
4701
 
 
4702
 
var L            = Y.Lang,
4703
 
    A            = Y.Array,
4704
 
    OP           = Object.prototype,
4705
 
    CLONE_MARKER = '_~yuim~_',
4706
 
 
4707
 
    hasOwn   = OP.hasOwnProperty,
4708
 
    toString = OP.toString;
4709
 
 
4710
 
function dispatch(o, f, c, proto, action) {
4711
 
    if (o && o[action] && o !== Y) {
4712
 
        return o[action].call(o, f, c);
4713
 
    } else {
4714
 
        switch (A.test(o)) {
4715
 
            case 1:
4716
 
                return A[action](o, f, c);
4717
 
            case 2:
4718
 
                return A[action](Y.Array(o, 0, true), f, c);
4719
 
            default:
4720
 
                return Y.Object[action](o, f, c, proto);
4721
 
        }
4722
 
    }
4723
 
}
4724
 
 
4725
 
/**
4726
 
Augments the _receiver_ with prototype properties from the _supplier_. The
4727
 
receiver may be a constructor function or an object. The supplier must be a
4728
 
constructor function.
4729
 
 
4730
 
If the _receiver_ is an object, then the _supplier_ constructor will be called
4731
 
immediately after _receiver_ is augmented, with _receiver_ as the `this` object.
4732
 
 
4733
 
If the _receiver_ is a constructor function, then all prototype methods of
4734
 
_supplier_ that are copied to _receiver_ will be sequestered, and the
4735
 
_supplier_ constructor will not be called immediately. The first time any
4736
 
sequestered method is called on the _receiver_'s prototype, all sequestered
4737
 
methods will be immediately copied to the _receiver_'s prototype, the
4738
 
_supplier_'s constructor will be executed, and finally the newly unsequestered
4739
 
method that was called will be executed.
4740
 
 
4741
 
This sequestering logic sounds like a bunch of complicated voodoo, but it makes
4742
 
it cheap to perform frequent augmentation by ensuring that suppliers'
4743
 
constructors are only called if a supplied method is actually used. If none of
4744
 
the supplied methods is ever used, then there's no need to take the performance
4745
 
hit of calling the _supplier_'s constructor.
4746
 
 
4747
 
@method augment
4748
 
@param {Function|Object} receiver Object or function to be augmented.
4749
 
@param {Function} supplier Function that supplies the prototype properties with
4750
 
  which to augment the _receiver_.
4751
 
@param {Boolean} [overwrite=false] If `true`, properties already on the receiver
4752
 
  will be overwritten if found on the supplier's prototype.
4753
 
@param {String[]} [whitelist] An array of property names. If specified,
4754
 
  only the whitelisted prototype properties will be applied to the receiver, and
4755
 
  all others will be ignored.
4756
 
@param {Array|any} [args] Argument or array of arguments to pass to the
4757
 
  supplier's constructor when initializing.
4758
 
@return {Function} Augmented object.
4759
 
@for YUI
4760
 
**/
4761
 
Y.augment = function (receiver, supplier, overwrite, whitelist, args) {
4762
 
    var rProto    = receiver.prototype,
4763
 
        sequester = rProto && supplier,
4764
 
        sProto    = supplier.prototype,
4765
 
        to        = rProto || receiver,
4766
 
 
4767
 
        copy,
4768
 
        newPrototype,
4769
 
        replacements,
4770
 
        sequestered,
4771
 
        unsequester;
4772
 
 
4773
 
    args = args ? Y.Array(args) : [];
4774
 
 
4775
 
    if (sequester) {
4776
 
        newPrototype = {};
4777
 
        replacements = {};
4778
 
        sequestered  = {};
4779
 
 
4780
 
        copy = function (value, key) {
4781
 
            if (overwrite || !(key in rProto)) {
4782
 
                if (toString.call(value) === '[object Function]') {
4783
 
                    sequestered[key] = value;
4784
 
 
4785
 
                    newPrototype[key] = replacements[key] = function () {
4786
 
                        return unsequester(this, value, arguments);
4787
 
                    };
4788
 
                } else {
4789
 
                    newPrototype[key] = value;
4790
 
                }
4791
 
            }
4792
 
        };
4793
 
 
4794
 
        unsequester = function (instance, fn, fnArgs) {
4795
 
            // Unsequester all sequestered functions.
4796
 
            for (var key in sequestered) {
4797
 
                if (hasOwn.call(sequestered, key)
4798
 
                        && instance[key] === replacements[key]) {
4799
 
 
4800
 
                    instance[key] = sequestered[key];
4801
 
                }
4802
 
            }
4803
 
 
4804
 
            // Execute the supplier constructor.
4805
 
            supplier.apply(instance, args);
4806
 
 
4807
 
            // Finally, execute the original sequestered function.
4808
 
            return fn.apply(instance, fnArgs);
4809
 
        };
4810
 
 
4811
 
        if (whitelist) {
4812
 
            Y.Array.each(whitelist, function (name) {
4813
 
                if (name in sProto) {
4814
 
                    copy(sProto[name], name);
4815
 
                }
4816
 
            });
4817
 
        } else {
4818
 
            Y.Object.each(sProto, copy, null, true);
4819
 
        }
4820
 
    }
4821
 
 
4822
 
    Y.mix(to, newPrototype || sProto, overwrite, whitelist);
4823
 
 
4824
 
    if (!sequester) {
4825
 
        supplier.apply(to, args);
4826
 
    }
4827
 
 
4828
 
    return receiver;
4829
 
};
4830
 
 
4831
 
/**
4832
 
 * Applies object properties from the supplier to the receiver.  If
4833
 
 * the target has the property, and the property is an object, the target
4834
 
 * object will be augmented with the supplier's value.  If the property
4835
 
 * is an array, the suppliers value will be appended to the target.
4836
 
 * @method aggregate
4837
 
 * @param {function} r  the object to receive the augmentation.
4838
 
 * @param {function} s  the object that supplies the properties to augment.
4839
 
 * @param {boolean} ov if true, properties already on the receiver
4840
 
 * will be overwritten if found on the supplier.
4841
 
 * @param {string[]} wl a whitelist.  If supplied, only properties in
4842
 
 * this list will be applied to the receiver.
4843
 
 * @return {object} the extended object.
4844
 
 */
4845
 
Y.aggregate = function(r, s, ov, wl) {
4846
 
    return Y.mix(r, s, ov, wl, 0, true);
4847
 
};
4848
 
 
4849
 
/**
4850
 
 * Utility to set up the prototype, constructor and superclass properties to
4851
 
 * support an inheritance strategy that can chain constructors and methods.
4852
 
 * Static members will not be inherited.
4853
 
 *
4854
 
 * @method extend
4855
 
 * @param {function} r   the object to modify.
4856
 
 * @param {function} s the object to inherit.
4857
 
 * @param {object} px prototype properties to add/override.
4858
 
 * @param {object} sx static properties to add/override.
4859
 
 * @return {object} the extended object.
4860
 
 */
4861
 
Y.extend = function(r, s, px, sx) {
4862
 
    if (!s || !r) {
4863
 
        Y.error('extend failed, verify dependencies');
4864
 
    }
4865
 
 
4866
 
    var sp = s.prototype, rp = Y.Object(sp);
4867
 
    r.prototype = rp;
4868
 
 
4869
 
    rp.constructor = r;
4870
 
    r.superclass = sp;
4871
 
 
4872
 
    // assign constructor property
4873
 
    if (s != Object && sp.constructor == OP.constructor) {
4874
 
        sp.constructor = s;
4875
 
    }
4876
 
 
4877
 
    // add prototype overrides
4878
 
    if (px) {
4879
 
        Y.mix(rp, px, true);
4880
 
    }
4881
 
 
4882
 
    // add object overrides
4883
 
    if (sx) {
4884
 
        Y.mix(r, sx, true);
4885
 
    }
4886
 
 
4887
 
    return r;
4888
 
};
4889
 
 
4890
 
/**
4891
 
 * Executes the supplied function for each item in
4892
 
 * a collection.  Supports arrays, objects, and
4893
 
 * NodeLists
4894
 
 * @method each
4895
 
 * @param {object} o the object to iterate.
4896
 
 * @param {function} f the function to execute.  This function
4897
 
 * receives the value, key, and object as parameters.
4898
 
 * @param {object} c the execution context for the function.
4899
 
 * @param {boolean} proto if true, prototype properties are
4900
 
 * iterated on objects.
4901
 
 * @return {YUI} the YUI instance.
4902
 
 */
4903
 
Y.each = function(o, f, c, proto) {
4904
 
    return dispatch(o, f, c, proto, 'each');
4905
 
};
4906
 
 
4907
 
/**
4908
 
 * Executes the supplied function for each item in
4909
 
 * a collection.  The operation stops if the function
4910
 
 * returns true. Supports arrays, objects, and
4911
 
 * NodeLists.
4912
 
 * @method some
4913
 
 * @param {object} o the object to iterate.
4914
 
 * @param {function} f the function to execute.  This function
4915
 
 * receives the value, key, and object as parameters.
4916
 
 * @param {object} c the execution context for the function.
4917
 
 * @param {boolean} proto if true, prototype properties are
4918
 
 * iterated on objects.
4919
 
 * @return {boolean} true if the function ever returns true,
4920
 
 * false otherwise.
4921
 
 */
4922
 
Y.some = function(o, f, c, proto) {
4923
 
    return dispatch(o, f, c, proto, 'some');
4924
 
};
4925
 
 
4926
 
/**
4927
 
 * Deep object/array copy.  Function clones are actually
4928
 
 * wrappers around the original function.
4929
 
 * Array-like objects are treated as arrays.
4930
 
 * Primitives are returned untouched.  Optionally, a
4931
 
 * function can be provided to handle other data types,
4932
 
 * filter keys, validate values, etc.
4933
 
 *
4934
 
 * @method clone
4935
 
 * @param {object} o what to clone.
4936
 
 * @param {boolean} safe if true, objects will not have prototype
4937
 
 * items from the source.  If false, they will.  In this case, the
4938
 
 * original is initially protected, but the clone is not completely
4939
 
 * immune from changes to the source object prototype.  Also, cloned
4940
 
 * prototype items that are deleted from the clone will result
4941
 
 * in the value of the source prototype being exposed.  If operating
4942
 
 * on a non-safe clone, items should be nulled out rather than deleted.
4943
 
 * @param {function} f optional function to apply to each item in a
4944
 
 * collection; it will be executed prior to applying the value to
4945
 
 * the new object.  Return false to prevent the copy.
4946
 
 * @param {object} c optional execution context for f.
4947
 
 * @param {object} owner Owner object passed when clone is iterating
4948
 
 * an object.  Used to set up context for cloned functions.
4949
 
 * @param {object} cloned hash of previously cloned objects to avoid
4950
 
 * multiple clones.
4951
 
 * @return {Array|Object} the cloned object.
4952
 
 */
4953
 
Y.clone = function(o, safe, f, c, owner, cloned) {
4954
 
 
4955
 
    if (!L.isObject(o)) {
4956
 
        return o;
4957
 
    }
4958
 
 
4959
 
    // @todo cloning YUI instances doesn't currently work
4960
 
    if (Y.instanceOf(o, YUI)) {
4961
 
        return o;
4962
 
    }
4963
 
 
4964
 
    var o2, marked = cloned || {}, stamp,
4965
 
        yeach = Y.each;
4966
 
 
4967
 
    switch (L.type(o)) {
4968
 
        case 'date':
4969
 
            return new Date(o);
4970
 
        case 'regexp':
4971
 
            // if we do this we need to set the flags too
4972
 
            // return new RegExp(o.source);
4973
 
            return o;
4974
 
        case 'function':
4975
 
            // o2 = Y.bind(o, owner);
4976
 
            // break;
4977
 
            return o;
4978
 
        case 'array':
4979
 
            o2 = [];
4980
 
            break;
4981
 
        default:
4982
 
 
4983
 
            // #2528250 only one clone of a given object should be created.
4984
 
            if (o[CLONE_MARKER]) {
4985
 
                return marked[o[CLONE_MARKER]];
4986
 
            }
4987
 
 
4988
 
            stamp = Y.guid();
4989
 
 
4990
 
            o2 = (safe) ? {} : Y.Object(o);
4991
 
 
4992
 
            o[CLONE_MARKER] = stamp;
4993
 
            marked[stamp] = o;
4994
 
    }
4995
 
 
4996
 
    // #2528250 don't try to clone element properties
4997
 
    if (!o.addEventListener && !o.attachEvent) {
4998
 
        yeach(o, function(v, k) {
4999
 
if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
5000
 
                if (k !== CLONE_MARKER) {
5001
 
                    if (k == 'prototype') {
5002
 
                        // skip the prototype
5003
 
                    // } else if (o[k] === o) {
5004
 
                    //     this[k] = this;
5005
 
                    } else {
5006
 
                        this[k] =
5007
 
                            Y.clone(v, safe, f, c, owner || o, marked);
5008
 
                    }
5009
 
                }
5010
 
            }
5011
 
        }, o2);
5012
 
    }
5013
 
 
5014
 
    if (!cloned) {
5015
 
        Y.Object.each(marked, function(v, k) {
5016
 
            if (v[CLONE_MARKER]) {
5017
 
                try {
5018
 
                    delete v[CLONE_MARKER];
5019
 
                } catch (e) {
5020
 
                    v[CLONE_MARKER] = null;
5021
 
                }
5022
 
            }
5023
 
        }, this);
5024
 
        marked = null;
5025
 
    }
5026
 
 
5027
 
    return o2;
5028
 
};
5029
 
 
5030
 
 
5031
 
/**
5032
 
 * Returns a function that will execute the supplied function in the
5033
 
 * supplied object's context, optionally adding any additional
5034
 
 * supplied parameters to the beginning of the arguments collection the
5035
 
 * supplied to the function.
5036
 
 *
5037
 
 * @method bind
5038
 
 * @param {Function|String} f the function to bind, or a function name
5039
 
 * to execute on the context object.
5040
 
 * @param {object} c the execution context.
5041
 
 * @param {any} args* 0..n arguments to include before the arguments the
5042
 
 * function is executed with.
5043
 
 * @return {function} the wrapped function.
5044
 
 */
5045
 
Y.bind = function(f, c) {
5046
 
    var xargs = arguments.length > 2 ?
5047
 
            Y.Array(arguments, 2, true) : null;
5048
 
    return function() {
5049
 
        var fn = L.isString(f) ? c[f] : f,
5050
 
            args = (xargs) ?
5051
 
                xargs.concat(Y.Array(arguments, 0, true)) : arguments;
5052
 
        return fn.apply(c || fn, args);
5053
 
    };
5054
 
};
5055
 
 
5056
 
/**
5057
 
 * Returns a function that will execute the supplied function in the
5058
 
 * supplied object's context, optionally adding any additional
5059
 
 * supplied parameters to the end of the arguments the function
5060
 
 * is executed with.
5061
 
 *
5062
 
 * @method rbind
5063
 
 * @param {Function|String} f the function to bind, or a function name
5064
 
 * to execute on the context object.
5065
 
 * @param {object} c the execution context.
5066
 
 * @param {any} args* 0..n arguments to append to the end of
5067
 
 * arguments collection supplied to the function.
5068
 
 * @return {function} the wrapped function.
5069
 
 */
5070
 
Y.rbind = function(f, c) {
5071
 
    var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
5072
 
    return function() {
5073
 
        var fn = L.isString(f) ? c[f] : f,
5074
 
            args = (xargs) ?
5075
 
                Y.Array(arguments, 0, true).concat(xargs) : arguments;
5076
 
        return fn.apply(c || fn, args);
5077
 
    };
5078
 
};
5079
 
 
5080
 
 
5081
 
}, '3.4.1' ,{requires:['yui-base']});
5082
 
YUI.add('features', function(Y) {
5083
 
 
5084
 
var feature_tests = {};
5085
 
 
5086
 
Y.mix(Y.namespace('Features'), {
5087
 
 
5088
 
    tests: feature_tests,
5089
 
 
5090
 
    add: function(cat, name, o) {
5091
 
        feature_tests[cat] = feature_tests[cat] || {};
5092
 
        feature_tests[cat][name] = o;
5093
 
    },
5094
 
 
5095
 
    all: function(cat, args) {
5096
 
        var cat_o = feature_tests[cat],
5097
 
            // results = {};
5098
 
            result = [];
5099
 
        if (cat_o) {
5100
 
            Y.Object.each(cat_o, function(v, k) {
5101
 
                result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
5102
 
            });
5103
 
        }
5104
 
 
5105
 
        return (result.length) ? result.join(';') : '';
5106
 
    },
5107
 
 
5108
 
    test: function(cat, name, args) {
5109
 
        args = args || [];
5110
 
        var result, ua, test,
5111
 
            cat_o = feature_tests[cat],
5112
 
            feature = cat_o && cat_o[name];
5113
 
 
5114
 
        if (!feature) {
5115
 
            Y.log('Feature test ' + cat + ', ' + name + ' not found');
5116
 
        } else {
5117
 
 
5118
 
            result = feature.result;
5119
 
 
5120
 
            if (Y.Lang.isUndefined(result)) {
5121
 
 
5122
 
                ua = feature.ua;
5123
 
                if (ua) {
5124
 
                    result = (Y.UA[ua]);
5125
 
                }
5126
 
 
5127
 
                test = feature.test;
5128
 
                if (test && ((!ua) || result)) {
5129
 
                    result = test.apply(Y, args);
5130
 
                }
5131
 
 
5132
 
                feature.result = result;
5133
 
            }
5134
 
        }
5135
 
 
5136
 
        return result;
5137
 
    }
5138
 
});
5139
 
 
5140
 
// Y.Features.add("load", "1", {});
5141
 
// Y.Features.test("load", "1");
5142
 
// caps=1:1;2:0;3:1;
5143
 
 
5144
 
/* This file is auto-generated by src/loader/scripts/meta_join.py */
5145
 
var add = Y.Features.add;
5146
 
// graphics-svg.js
5147
 
add('load', '0', {
5148
 
    "name": "graphics-svg", 
5149
 
    "test": function(Y) {
5150
 
    var DOCUMENT = Y.config.doc;
5151
 
        return (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
5152
 
}, 
5153
 
    "trigger": "graphics"
5154
 
});
5155
 
// ie-base-test.js
5156
 
add('load', '1', {
5157
 
    "name": "event-base-ie", 
5158
 
    "test": function(Y) {
5159
 
    var imp = Y.config.doc && Y.config.doc.implementation;
5160
 
    return (imp && (!imp.hasFeature('Events', '2.0')));
5161
 
}, 
5162
 
    "trigger": "node-base"
5163
 
});
5164
 
// graphics-vml.js
5165
 
add('load', '2', {
5166
 
    "name": "graphics-vml", 
5167
 
    "test": function(Y) {
5168
 
    var DOCUMENT = Y.config.doc,
5169
 
                canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5170
 
    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
5171
 
}, 
5172
 
    "trigger": "graphics"
5173
 
});
5174
 
// ie-style-test.js
5175
 
add('load', '3', {
5176
 
    "name": "dom-style-ie", 
5177
 
    "test": function (Y) {
5178
 
 
5179
 
    var testFeature = Y.Features.test,
5180
 
        addFeature = Y.Features.add,
5181
 
        WINDOW = Y.config.win,
5182
 
        DOCUMENT = Y.config.doc,
5183
 
        DOCUMENT_ELEMENT = 'documentElement',
5184
 
        ret = false;
5185
 
 
5186
 
    addFeature('style', 'computedStyle', {
5187
 
        test: function() {
5188
 
            return WINDOW && 'getComputedStyle' in WINDOW;
5189
 
        }
5190
 
    });
5191
 
 
5192
 
    addFeature('style', 'opacity', {
5193
 
        test: function() {
5194
 
            return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
5195
 
        }
5196
 
    });
5197
 
 
5198
 
    ret =  (!testFeature('style', 'opacity') &&
5199
 
            !testFeature('style', 'computedStyle'));
5200
 
 
5201
 
    return ret;
5202
 
}, 
5203
 
    "trigger": "dom-style"
5204
 
});
5205
 
// transition-test.js
5206
 
add('load', '4', {
5207
 
    "name": "transition-timer", 
5208
 
    "test": function (Y) {
5209
 
    var DOCUMENT = Y.config.doc,
5210
 
        node = (DOCUMENT) ? DOCUMENT.documentElement: null,
5211
 
        ret = true;
5212
 
 
5213
 
    if (node && node.style) {
5214
 
        ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style);
5215
 
    } 
5216
 
 
5217
 
    return ret;
5218
 
}, 
5219
 
    "trigger": "transition"
5220
 
});
5221
 
// 0
5222
 
add('load', '5', {
5223
 
    "name": "widget-base-ie", 
5224
 
    "trigger": "widget-base", 
5225
 
    "ua": "ie"
5226
 
});
5227
 
// autocomplete-list-keys-sniff.js
5228
 
add('load', '6', {
5229
 
    "name": "autocomplete-list-keys", 
5230
 
    "test": function (Y) {
5231
 
    // Only add keyboard support to autocomplete-list if this doesn't appear to
5232
 
    // be an iOS or Android-based mobile device.
5233
 
    //
5234
 
    // There's currently no feasible way to actually detect whether a device has
5235
 
    // a hardware keyboard, so this sniff will have to do. It can easily be
5236
 
    // overridden by manually loading the autocomplete-list-keys module.
5237
 
    //
5238
 
    // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
5239
 
    // doesn't fire the keyboard events used by AutoCompleteList, so there's
5240
 
    // no point loading the -keys module even when a bluetooth keyboard may be
5241
 
    // available.
5242
 
    return !(Y.UA.ios || Y.UA.android);
5243
 
}, 
5244
 
    "trigger": "autocomplete-list"
5245
 
});
5246
 
// graphics-canvas.js
5247
 
add('load', '7', {
5248
 
    "name": "graphics-canvas-default", 
5249
 
    "test": function(Y) {
5250
 
    var DOCUMENT = Y.config.doc,
5251
 
                canvas = DOCUMENT && DOCUMENT.createElement("canvas");
5252
 
        return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (canvas && canvas.getContext && canvas.getContext("2d")));
5253
 
}, 
5254
 
    "trigger": "graphics"
5255
 
});
5256
 
// dd-gestures-test.js
5257
 
add('load', '8', {
5258
 
    "name": "dd-gestures", 
5259
 
    "test": function(Y) {
5260
 
    return (Y.config.win && ('ontouchstart' in Y.config.win && !Y.UA.chrome));
5261
 
}, 
5262
 
    "trigger": "dd-drag"
5263
 
});
5264
 
// selector-test.js
5265
 
add('load', '9', {
5266
 
    "name": "selector-css2", 
5267
 
    "test": function (Y) {
5268
 
    var DOCUMENT = Y.config.doc,
5269
 
        ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
5270
 
 
5271
 
    return ret;
5272
 
}, 
5273
 
    "trigger": "selector"
5274
 
});
5275
 
// history-hash-ie-test.js
5276
 
add('load', '10', {
5277
 
    "name": "history-hash-ie", 
5278
 
    "test": function (Y) {
5279
 
    var docMode = Y.config.doc && Y.config.doc.documentMode;
5280
 
 
5281
 
    return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
5282
 
            !docMode || docMode < 8);
5283
 
}, 
5284
 
    "trigger": "history-hash"
5285
 
});
5286
 
 
5287
 
 
5288
 
}, '3.4.1' ,{requires:['yui-base']});
5289
 
YUI.add('dom-core', function(Y) {
5290
 
 
5291
 
var NODE_TYPE = 'nodeType',
5292
 
    OWNER_DOCUMENT = 'ownerDocument',
5293
 
    DOCUMENT_ELEMENT = 'documentElement',
5294
 
    DEFAULT_VIEW = 'defaultView',
5295
 
    PARENT_WINDOW = 'parentWindow',
5296
 
    TAG_NAME = 'tagName',
5297
 
    PARENT_NODE = 'parentNode',
5298
 
    PREVIOUS_SIBLING = 'previousSibling',
5299
 
    NEXT_SIBLING = 'nextSibling',
5300
 
    CONTAINS = 'contains',
5301
 
    COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
5302
 
    EMPTY_ARRAY = [],
5303
 
 
5304
 
/** 
5305
 
 * The DOM utility provides a cross-browser abtraction layer
5306
 
 * normalizing DOM tasks, and adds extra helper functionality
5307
 
 * for other common tasks. 
5308
 
 * @module dom
5309
 
 * @submodule dom-base
5310
 
 * @for DOM
5311
 
 *
5312
 
 */
5313
 
 
5314
 
/**
5315
 
 * Provides DOM helper methods.
5316
 
 * @class DOM
5317
 
 *
5318
 
 */
5319
 
    
5320
 
Y_DOM = {
5321
 
    /**
5322
 
     * Returns the HTMLElement with the given ID (Wrapper for document.getElementById).
5323
 
     * @method byId         
5324
 
     * @param {String} id the id attribute 
5325
 
     * @param {Object} doc optional The document to search. Defaults to current document 
5326
 
     * @return {HTMLElement | null} The HTMLElement with the id, or null if none found. 
5327
 
     */
5328
 
    byId: function(id, doc) {
5329
 
        // handle dupe IDs and IE name collision
5330
 
        return Y_DOM.allById(id, doc)[0] || null;
5331
 
    },
5332
 
 
5333
 
    /*
5334
 
     * Finds the ancestor of the element.
5335
 
     * @method ancestor
5336
 
     * @param {HTMLElement} element The html element.
5337
 
     * @param {Function} fn optional An optional boolean test to apply.
5338
 
     * The optional function is passed the current DOM node being tested as its only argument.
5339
 
     * If no function is given, the parentNode is returned.
5340
 
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
5341
 
     * @return {HTMLElement | null} The matching DOM node or null if none found. 
5342
 
     */
5343
 
    ancestor: function(element, fn, testSelf) {
5344
 
        var ret = null;
5345
 
        if (testSelf) {
5346
 
            ret = (!fn || fn(element)) ? element : null;
5347
 
 
5348
 
        }
5349
 
        return ret || Y_DOM.elementByAxis(element, PARENT_NODE, fn, null);
5350
 
    },
5351
 
 
5352
 
    /*
5353
 
     * Finds the ancestors of the element.
5354
 
     * @method ancestors
5355
 
     * @param {HTMLElement} element The html element.
5356
 
     * @param {Function} fn optional An optional boolean test to apply.
5357
 
     * The optional function is passed the current DOM node being tested as its only argument.
5358
 
     * If no function is given, all ancestors are returned.
5359
 
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
5360
 
     * @return {Array} An array containing all matching DOM nodes.
5361
 
     */
5362
 
    ancestors: function(element, fn, testSelf) {
5363
 
        var ancestor = Y_DOM.ancestor.apply(Y_DOM, arguments),
5364
 
            ret = (ancestor) ? [ancestor] : [];
5365
 
 
5366
 
        while ((ancestor = Y_DOM.ancestor(ancestor, fn))) {
5367
 
            if (ancestor) {
5368
 
                ret.unshift(ancestor);
5369
 
            }
5370
 
        }
5371
 
 
5372
 
        return ret;
5373
 
    },
5374
 
 
5375
 
    /**
5376
 
     * Searches the element by the given axis for the first matching element.
5377
 
     * @method elementByAxis
5378
 
     * @param {HTMLElement} element The html element.
5379
 
     * @param {String} axis The axis to search (parentNode, nextSibling, previousSibling).
5380
 
     * @param {Function} fn optional An optional boolean test to apply.
5381
 
     * @param {Boolean} all optional Whether all node types should be returned, or just element nodes.
5382
 
     * The optional function is passed the current HTMLElement being tested as its only argument.
5383
 
     * If no function is given, the first element is returned.
5384
 
     * @return {HTMLElement | null} The matching element or null if none found.
5385
 
     */
5386
 
    elementByAxis: function(element, axis, fn, all) {
5387
 
        while (element && (element = element[axis])) { // NOTE: assignment
5388
 
                if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
5389
 
                    return element;
5390
 
                }
5391
 
        }
5392
 
        return null;
5393
 
    },
5394
 
 
5395
 
    /**
5396
 
     * Determines whether or not one HTMLElement is or contains another HTMLElement.
5397
 
     * @method contains
5398
 
     * @param {HTMLElement} element The containing html element.
5399
 
     * @param {HTMLElement} needle The html element that may be contained.
5400
 
     * @return {Boolean} Whether or not the element is or contains the needle.
5401
 
     */
5402
 
    contains: function(element, needle) {
5403
 
        var ret = false;
5404
 
 
5405
 
        if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
5406
 
            ret = false;
5407
 
        } else if (element[CONTAINS])  {
5408
 
            if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
5409
 
                ret = element[CONTAINS](needle);
5410
 
            } else {
5411
 
                ret = Y_DOM._bruteContains(element, needle); 
5412
 
            }
5413
 
        } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
5414
 
            if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) { 
5415
 
                ret = true;
5416
 
            }
5417
 
        }
5418
 
 
5419
 
        return ret;
5420
 
    },
5421
 
 
5422
 
    /**
5423
 
     * Determines whether or not the HTMLElement is part of the document.
5424
 
     * @method inDoc
5425
 
     * @param {HTMLElement} element The containing html element.
5426
 
     * @param {HTMLElement} doc optional The document to check.
5427
 
     * @return {Boolean} Whether or not the element is attached to the document. 
5428
 
     */
5429
 
    inDoc: function(element, doc) {
5430
 
        var ret = false,
5431
 
            rootNode;
5432
 
 
5433
 
        if (element && element.nodeType) {
5434
 
            (doc) || (doc = element[OWNER_DOCUMENT]);
5435
 
 
5436
 
            rootNode = doc[DOCUMENT_ELEMENT];
5437
 
 
5438
 
            // contains only works with HTML_ELEMENT
5439
 
            if (rootNode && rootNode.contains && element.tagName) {
5440
 
                ret = rootNode.contains(element);
5441
 
            } else {
5442
 
                ret = Y_DOM.contains(rootNode, element);
5443
 
            }
5444
 
        }
5445
 
 
5446
 
        return ret;
5447
 
 
5448
 
    },
5449
 
 
5450
 
   allById: function(id, root) {
5451
 
        root = root || Y.config.doc;
5452
 
        var nodes = [],
5453
 
            ret = [],
5454
 
            i,
5455
 
            node;
5456
 
 
5457
 
        if (root.querySelectorAll) {
5458
 
            ret = root.querySelectorAll('[id="' + id + '"]');
5459
 
        } else if (root.all) {
5460
 
            nodes = root.all(id);
5461
 
 
5462
 
            if (nodes) {
5463
 
                // root.all may return HTMLElement or HTMLCollection.
5464
 
                // some elements are also HTMLCollection (FORM, SELECT).
5465
 
                if (nodes.nodeName) {
5466
 
                    if (nodes.id === id) { // avoid false positive on name
5467
 
                        ret.push(nodes);
5468
 
                        nodes = EMPTY_ARRAY; // done, no need to filter
5469
 
                    } else { //  prep for filtering
5470
 
                        nodes = [nodes];
5471
 
                    }
5472
 
                }
5473
 
 
5474
 
                if (nodes.length) {
5475
 
                    // filter out matches on node.name
5476
 
                    // and element.id as reference to element with id === 'id'
5477
 
                    for (i = 0; node = nodes[i++];) {
5478
 
                        if (node.id === id  || 
5479
 
                                (node.attributes && node.attributes.id &&
5480
 
                                node.attributes.id.value === id)) { 
5481
 
                            ret.push(node);
5482
 
                        }
5483
 
                    }
5484
 
                }
5485
 
            }
5486
 
        } else {
5487
 
            ret = [Y_DOM._getDoc(root).getElementById(id)];
5488
 
        }
5489
 
    
5490
 
        return ret;
5491
 
   },
5492
 
 
5493
 
 
5494
 
    isWindow: function(obj) {
5495
 
        return !!(obj && obj.alert && obj.document);
5496
 
    },
5497
 
 
5498
 
    _removeChildNodes: function(node) {
5499
 
        while (node.firstChild) {
5500
 
            node.removeChild(node.firstChild);
5501
 
        }
5502
 
    },
5503
 
 
5504
 
    siblings: function(node, fn) {
5505
 
        var nodes = [],
5506
 
            sibling = node;
5507
 
 
5508
 
        while ((sibling = sibling[PREVIOUS_SIBLING])) {
5509
 
            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
5510
 
                nodes.unshift(sibling);
5511
 
            }
5512
 
        }
5513
 
 
5514
 
        sibling = node;
5515
 
        while ((sibling = sibling[NEXT_SIBLING])) {
5516
 
            if (sibling[TAG_NAME] && (!fn || fn(sibling))) {
5517
 
                nodes.push(sibling);
5518
 
            }
5519
 
        }
5520
 
 
5521
 
        return nodes;
5522
 
    },
5523
 
 
5524
 
    /**
5525
 
     * Brute force version of contains.
5526
 
     * Used for browsers without contains support for non-HTMLElement Nodes (textNodes, etc).
5527
 
     * @method _bruteContains
5528
 
     * @private
5529
 
     * @param {HTMLElement} element The containing html element.
5530
 
     * @param {HTMLElement} needle The html element that may be contained.
5531
 
     * @return {Boolean} Whether or not the element is or contains the needle.
5532
 
     */
5533
 
    _bruteContains: function(element, needle) {
5534
 
        while (needle) {
5535
 
            if (element === needle) {
5536
 
                return true;
5537
 
            }
5538
 
            needle = needle.parentNode;
5539
 
        }
5540
 
        return false;
5541
 
    },
5542
 
 
5543
 
// TODO: move to Lang?
5544
 
    /**
5545
 
     * Memoizes dynamic regular expressions to boost runtime performance. 
5546
 
     * @method _getRegExp
5547
 
     * @private
5548
 
     * @param {String} str The string to convert to a regular expression.
5549
 
     * @param {String} flags optional An optinal string of flags.
5550
 
     * @return {RegExp} An instance of RegExp
5551
 
     */
5552
 
    _getRegExp: function(str, flags) {
5553
 
        flags = flags || '';
5554
 
        Y_DOM._regexCache = Y_DOM._regexCache || {};
5555
 
        if (!Y_DOM._regexCache[str + flags]) {
5556
 
            Y_DOM._regexCache[str + flags] = new RegExp(str, flags);
5557
 
        }
5558
 
        return Y_DOM._regexCache[str + flags];
5559
 
    },
5560
 
 
5561
 
// TODO: make getDoc/Win true privates?
5562
 
    /**
5563
 
     * returns the appropriate document.
5564
 
     * @method _getDoc
5565
 
     * @private
5566
 
     * @param {HTMLElement} element optional Target element.
5567
 
     * @return {Object} The document for the given element or the default document. 
5568
 
     */
5569
 
    _getDoc: function(element) {
5570
 
        var doc = Y.config.doc;
5571
 
        if (element) {
5572
 
            doc = (element[NODE_TYPE] === 9) ? element : // element === document
5573
 
                element[OWNER_DOCUMENT] || // element === DOM node
5574
 
                element.document || // element === window
5575
 
                Y.config.doc; // default
5576
 
        }
5577
 
 
5578
 
        return doc;
5579
 
    },
5580
 
 
5581
 
    /**
5582
 
     * returns the appropriate window.
5583
 
     * @method _getWin
5584
 
     * @private
5585
 
     * @param {HTMLElement} element optional Target element.
5586
 
     * @return {Object} The window for the given element or the default window. 
5587
 
     */
5588
 
    _getWin: function(element) {
5589
 
        var doc = Y_DOM._getDoc(element);
5590
 
        return doc[DEFAULT_VIEW] || doc[PARENT_WINDOW] || Y.config.win;
5591
 
    },
5592
 
 
5593
 
    _batch: function(nodes, fn, arg1, arg2, arg3, etc) {
5594
 
        fn = (typeof fn === 'string') ? Y_DOM[fn] : fn;
5595
 
        var result,
5596
 
            i = 0,
5597
 
            node,
5598
 
            ret;
5599
 
 
5600
 
        if (fn && nodes) {
5601
 
            while ((node = nodes[i++])) {
5602
 
                result = result = fn.call(Y_DOM, node, arg1, arg2, arg3, etc);
5603
 
                if (typeof result !== 'undefined') {
5604
 
                    (ret) || (ret = []);
5605
 
                    ret.push(result);
5606
 
                }
5607
 
            }
5608
 
        }
5609
 
 
5610
 
        return (typeof ret !== 'undefined') ? ret : nodes;
5611
 
    },
5612
 
 
5613
 
    wrap: function(node, html) {
5614
 
        var parent = Y.DOM.create(html),
5615
 
            nodes = parent.getElementsByTagName('*');
5616
 
 
5617
 
        if (nodes.length) {
5618
 
            parent = nodes[nodes.length - 1];
5619
 
        }
5620
 
 
5621
 
        if (node.parentNode) { 
5622
 
            node.parentNode.replaceChild(parent, node);
5623
 
        }
5624
 
        parent.appendChild(node);
5625
 
    },
5626
 
 
5627
 
    unwrap: function(node) {
5628
 
        var parent = node.parentNode,
5629
 
            lastChild = parent.lastChild,
5630
 
            next = node,
5631
 
            grandparent;
5632
 
 
5633
 
        if (parent) {
5634
 
            grandparent = parent.parentNode;
5635
 
            if (grandparent) {
5636
 
                node = parent.firstChild;
5637
 
                while (node !== lastChild) {
5638
 
                    next = node.nextSibling;
5639
 
                    grandparent.insertBefore(node, parent);
5640
 
                    node = next;
5641
 
                }
5642
 
                grandparent.replaceChild(lastChild, parent);
5643
 
            } else {
5644
 
                parent.removeChild(node);
5645
 
            }
5646
 
        }
5647
 
    },
5648
 
 
5649
 
    generateID: function(el) {
5650
 
        var id = el.id;
5651
 
 
5652
 
        if (!id) {
5653
 
            id = Y.stamp(el);
5654
 
            el.id = id; 
5655
 
        }   
5656
 
 
5657
 
        return id; 
5658
 
    }
5659
 
};
5660
 
 
5661
 
 
5662
 
Y.DOM = Y_DOM;
5663
 
 
5664
 
 
5665
 
}, '3.4.1' ,{requires:['oop','features']});
5666
 
YUI.add('dom-base', function(Y) {
5667
 
 
5668
 
var documentElement = Y.config.doc.documentElement,
5669
 
    Y_DOM = Y.DOM,
5670
 
    TAG_NAME = 'tagName',
5671
 
    OWNER_DOCUMENT = 'ownerDocument',
5672
 
    EMPTY_STRING = '',
5673
 
    addFeature = Y.Features.add,
5674
 
    testFeature = Y.Features.test;
5675
 
 
5676
 
Y.mix(Y_DOM, {
5677
 
    /**
5678
 
     * Returns the text content of the HTMLElement. 
5679
 
     * @method getText         
5680
 
     * @param {HTMLElement} element The html element. 
5681
 
     * @return {String} The text content of the element (includes text of any descending elements).
5682
 
     */
5683
 
    getText: (documentElement.textContent !== undefined) ?
5684
 
        function(element) {
5685
 
            var ret = '';
5686
 
            if (element) {
5687
 
                ret = element.textContent;
5688
 
            }
5689
 
            return ret || '';
5690
 
        } : function(element) {
5691
 
            var ret = '';
5692
 
            if (element) {
5693
 
                ret = element.innerText || element.nodeValue; // might be a textNode
5694
 
            }
5695
 
            return ret || '';
5696
 
        },
5697
 
 
5698
 
    /**
5699
 
     * Sets the text content of the HTMLElement. 
5700
 
     * @method setText         
5701
 
     * @param {HTMLElement} element The html element. 
5702
 
     * @param {String} content The content to add. 
5703
 
     */
5704
 
    setText: (documentElement.textContent !== undefined) ?
5705
 
        function(element, content) {
5706
 
            if (element) {
5707
 
                element.textContent = content;
5708
 
            }
5709
 
        } : function(element, content) {
5710
 
            if ('innerText' in element) {
5711
 
                element.innerText = content;
5712
 
            } else if ('nodeValue' in element) {
5713
 
                element.nodeValue = content;
5714
 
            }
5715
 
    },
5716
 
 
5717
 
    CUSTOM_ATTRIBUTES: (!documentElement.hasAttribute) ? { // IE < 8
5718
 
        'for': 'htmlFor',
5719
 
        'class': 'className'
5720
 
    } : { // w3c
5721
 
        'htmlFor': 'for',
5722
 
        'className': 'class'
5723
 
    },
5724
 
 
5725
 
    /**
5726
 
     * Provides a normalized attribute interface. 
5727
 
     * @method setAttribute
5728
 
     * @param {HTMLElement} el The target element for the attribute.
5729
 
     * @param {String} attr The attribute to set.
5730
 
     * @param {String} val The value of the attribute.
5731
 
     */
5732
 
    setAttribute: function(el, attr, val, ieAttr) {
5733
 
        if (el && attr && el.setAttribute) {
5734
 
            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
5735
 
            el.setAttribute(attr, val, ieAttr);
5736
 
        }
5737
 
        else { Y.log('bad input to setAttribute', 'warn', 'dom'); }
5738
 
    },
5739
 
 
5740
 
 
5741
 
    /**
5742
 
     * Provides a normalized attribute interface. 
5743
 
     * @method getAttibute
5744
 
     * @param {HTMLElement} el The target element for the attribute.
5745
 
     * @param {String} attr The attribute to get.
5746
 
     * @return {String} The current value of the attribute. 
5747
 
     */
5748
 
    getAttribute: function(el, attr, ieAttr) {
5749
 
        ieAttr = (ieAttr !== undefined) ? ieAttr : 2;
5750
 
        var ret = '';
5751
 
        if (el && attr && el.getAttribute) {
5752
 
            attr = Y_DOM.CUSTOM_ATTRIBUTES[attr] || attr;
5753
 
            ret = el.getAttribute(attr, ieAttr);
5754
 
 
5755
 
            if (ret === null) {
5756
 
                ret = ''; // per DOM spec
5757
 
            }
5758
 
        }
5759
 
        else { Y.log('bad input to getAttribute', 'warn', 'dom'); }
5760
 
        return ret;
5761
 
    },
5762
 
 
5763
 
    VALUE_SETTERS: {},
5764
 
 
5765
 
    VALUE_GETTERS: {},
5766
 
 
5767
 
    getValue: function(node) {
5768
 
        var ret = '', // TODO: return null?
5769
 
            getter;
5770
 
 
5771
 
        if (node && node[TAG_NAME]) {
5772
 
            getter = Y_DOM.VALUE_GETTERS[node[TAG_NAME].toLowerCase()];
5773
 
 
5774
 
            if (getter) {
5775
 
                ret = getter(node);
5776
 
            } else {
5777
 
                ret = node.value;
5778
 
            }
5779
 
        }
5780
 
 
5781
 
        // workaround for IE8 JSON stringify bug
5782
 
        // which converts empty string values to null
5783
 
        if (ret === EMPTY_STRING) {
5784
 
            ret = EMPTY_STRING; // for real
5785
 
        }
5786
 
 
5787
 
        return (typeof ret === 'string') ? ret : '';
5788
 
    },
5789
 
 
5790
 
    setValue: function(node, val) {
5791
 
        var setter;
5792
 
 
5793
 
        if (node && node[TAG_NAME]) {
5794
 
            setter = Y_DOM.VALUE_SETTERS[node[TAG_NAME].toLowerCase()];
5795
 
 
5796
 
            if (setter) {
5797
 
                setter(node, val);
5798
 
            } else {
5799
 
                node.value = val;
5800
 
            }
5801
 
        }
5802
 
    },
5803
 
 
5804
 
    creators: {}
5805
 
});
5806
 
 
5807
 
addFeature('value-set', 'select', {
5808
 
    test: function() {
5809
 
        var node = Y.config.doc.createElement('select');
5810
 
        node.innerHTML = '<option>1</option><option>2</option>';
5811
 
        node.value = '2';
5812
 
        return (node.value && node.value === '2');
5813
 
    }
5814
 
});
5815
 
 
5816
 
if (!testFeature('value-set', 'select')) {
5817
 
    Y_DOM.VALUE_SETTERS.select = function(node, val) {
5818
 
        for (var i = 0, options = node.getElementsByTagName('option'), option;
5819
 
                option = options[i++];) {
5820
 
            if (Y_DOM.getValue(option) === val) {
5821
 
                option.selected = true;
5822
 
                //Y_DOM.setAttribute(option, 'selected', 'selected');
5823
 
                break;
5824
 
            }
5825
 
        }
5826
 
    }
5827
 
}
5828
 
 
5829
 
Y.mix(Y_DOM.VALUE_GETTERS, {
5830
 
    button: function(node) {
5831
 
        return (node.attributes && node.attributes.value) ? node.attributes.value.value : '';
5832
 
    }
5833
 
});
5834
 
 
5835
 
Y.mix(Y_DOM.VALUE_SETTERS, {
5836
 
    // IE: node.value changes the button text, which should be handled via innerHTML
5837
 
    button: function(node, val) {
5838
 
        var attr = node.attributes.value;
5839
 
        if (!attr) {
5840
 
            attr = node[OWNER_DOCUMENT].createAttribute('value');
5841
 
            node.setAttributeNode(attr);
5842
 
        }
5843
 
 
5844
 
        attr.value = val;
5845
 
    }
5846
 
});
5847
 
 
5848
 
 
5849
 
Y.mix(Y_DOM.VALUE_GETTERS, {
5850
 
    option: function(node) {
5851
 
        var attrs = node.attributes;
5852
 
        return (attrs.value && attrs.value.specified) ? node.value : node.text;
5853
 
    },
5854
 
 
5855
 
    select: function(node) {
5856
 
        var val = node.value,
5857
 
            options = node.options;
5858
 
 
5859
 
        if (options && options.length) {
5860
 
            // TODO: implement multipe select
5861
 
            if (node.multiple) {
5862
 
                Y.log('multiple select normalization not implemented', 'warn', 'DOM');
5863
 
            } else {
5864
 
                val = Y_DOM.getValue(options[node.selectedIndex]);
5865
 
            }
5866
 
        }
5867
 
 
5868
 
        return val;
5869
 
    }
5870
 
});
5871
 
var addClass, hasClass, removeClass;
5872
 
 
5873
 
Y.mix(Y.DOM, {
5874
 
    /**
5875
 
     * Determines whether a DOM element has the given className.
5876
 
     * @method hasClass
5877
 
     * @for DOM
5878
 
     * @param {HTMLElement} element The DOM element. 
5879
 
     * @param {String} className the class name to search for
5880
 
     * @return {Boolean} Whether or not the element has the given class. 
5881
 
     */
5882
 
    hasClass: function(node, className) {
5883
 
        var re = Y.DOM._getRegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
5884
 
        return re.test(node.className);
5885
 
    },
5886
 
 
5887
 
    /**
5888
 
     * Adds a class name to a given DOM element.
5889
 
     * @method addClass         
5890
 
     * @for DOM
5891
 
     * @param {HTMLElement} element The DOM element. 
5892
 
     * @param {String} className the class name to add to the class attribute
5893
 
     */
5894
 
    addClass: function(node, className) {
5895
 
        if (!Y.DOM.hasClass(node, className)) { // skip if already present 
5896
 
            node.className = Y.Lang.trim([node.className, className].join(' '));
5897
 
        }
5898
 
    },
5899
 
 
5900
 
    /**
5901
 
     * Removes a class name from a given element.
5902
 
     * @method removeClass         
5903
 
     * @for DOM
5904
 
     * @param {HTMLElement} element The DOM element. 
5905
 
     * @param {String} className the class name to remove from the class attribute
5906
 
     */
5907
 
    removeClass: function(node, className) {
5908
 
        if (className && hasClass(node, className)) {
5909
 
            node.className = Y.Lang.trim(node.className.replace(Y.DOM._getRegExp('(?:^|\\s+)' +
5910
 
                            className + '(?:\\s+|$)'), ' '));
5911
 
 
5912
 
            if ( hasClass(node, className) ) { // in case of multiple adjacent
5913
 
                removeClass(node, className);
5914
 
            }
5915
 
        }                 
5916
 
    },
5917
 
 
5918
 
    /**
5919
 
     * Replace a class with another class for a given element.
5920
 
     * If no oldClassName is present, the newClassName is simply added.
5921
 
     * @method replaceClass  
5922
 
     * @for DOM
5923
 
     * @param {HTMLElement} element The DOM element 
5924
 
     * @param {String} oldClassName the class name to be replaced
5925
 
     * @param {String} newClassName the class name that will be replacing the old class name
5926
 
     */
5927
 
    replaceClass: function(node, oldC, newC) {
5928
 
        //Y.log('replaceClass replacing ' + oldC + ' with ' + newC, 'info', 'Node');
5929
 
        removeClass(node, oldC); // remove first in case oldC === newC
5930
 
        addClass(node, newC);
5931
 
    },
5932
 
 
5933
 
    /**
5934
 
     * If the className exists on the node it is removed, if it doesn't exist it is added.
5935
 
     * @method toggleClass  
5936
 
     * @for DOM
5937
 
     * @param {HTMLElement} element The DOM element
5938
 
     * @param {String} className the class name to be toggled
5939
 
     * @param {Boolean} addClass optional boolean to indicate whether class
5940
 
     * should be added or removed regardless of current state
5941
 
     */
5942
 
    toggleClass: function(node, className, force) {
5943
 
        var add = (force !== undefined) ? force :
5944
 
                !(hasClass(node, className));
5945
 
 
5946
 
        if (add) {
5947
 
            addClass(node, className);
5948
 
        } else {
5949
 
            removeClass(node, className);
5950
 
        }
5951
 
    }
5952
 
});
5953
 
 
5954
 
hasClass = Y.DOM.hasClass;
5955
 
removeClass = Y.DOM.removeClass;
5956
 
addClass = Y.DOM.addClass;
5957
 
 
5958
 
var re_tag = /<([a-z]+)/i,
5959
 
 
5960
 
    Y_DOM = Y.DOM,
5961
 
 
5962
 
    addFeature = Y.Features.add,
5963
 
    testFeature = Y.Features.test,
5964
 
 
5965
 
    creators = {},
5966
 
 
5967
 
    createFromDIV = function(html, tag) {
5968
 
        var div = Y.config.doc.createElement('div'),
5969
 
            ret = true;
5970
 
 
5971
 
        div.innerHTML = html;
5972
 
        if (!div.firstChild || div.firstChild.tagName !== tag.toUpperCase()) {
5973
 
            ret = false;
5974
 
        }
5975
 
 
5976
 
        return ret;
5977
 
    },
5978
 
 
5979
 
    re_tbody = /(?:\/(?:thead|tfoot|tbody|caption|col|colgroup)>)+\s*<tbody/,
5980
 
 
5981
 
    TABLE_OPEN = '<table>',
5982
 
    TABLE_CLOSE = '</table>';
5983
 
 
5984
 
Y.mix(Y.DOM, {
5985
 
    _fragClones: {},
5986
 
 
5987
 
    _create: function(html, doc, tag) {
5988
 
        tag = tag || 'div';
5989
 
 
5990
 
        var frag = Y_DOM._fragClones[tag];
5991
 
        if (frag) {
5992
 
            frag = frag.cloneNode(false);
5993
 
        } else {
5994
 
            frag = Y_DOM._fragClones[tag] = doc.createElement(tag);
5995
 
        }
5996
 
        frag.innerHTML = html;
5997
 
        return frag;
5998
 
    },
5999
 
 
6000
 
    /**
6001
 
     * Creates a new dom node using the provided markup string. 
6002
 
     * @method create
6003
 
     * @param {String} html The markup used to create the element
6004
 
     * @param {HTMLDocument} doc An optional document context 
6005
 
     * @return {HTMLElement|DocumentFragment} returns a single HTMLElement 
6006
 
     * when creating one node, and a documentFragment when creating
6007
 
     * multiple nodes.
6008
 
     */
6009
 
    create: function(html, doc) {
6010
 
        if (typeof html === 'string') {
6011
 
            html = Y.Lang.trim(html); // match IE which trims whitespace from innerHTML
6012
 
 
6013
 
        }
6014
 
 
6015
 
        doc = doc || Y.config.doc;
6016
 
        var m = re_tag.exec(html),
6017
 
            create = Y_DOM._create,
6018
 
            custom = creators,
6019
 
            ret = null,
6020
 
            creator,
6021
 
            tag, nodes;
6022
 
 
6023
 
        if (html != undefined) { // not undefined or null
6024
 
            if (m && m[1]) {
6025
 
                creator = custom[m[1].toLowerCase()];
6026
 
                if (typeof creator === 'function') {
6027
 
                    create = creator; 
6028
 
                } else {
6029
 
                    tag = creator;
6030
 
                }
6031
 
            }
6032
 
 
6033
 
            nodes = create(html, doc, tag).childNodes;
6034
 
 
6035
 
            if (nodes.length === 1) { // return single node, breaking parentNode ref from "fragment"
6036
 
                ret = nodes[0].parentNode.removeChild(nodes[0]);
6037
 
            } else if (nodes[0] && nodes[0].className === 'yui3-big-dummy') { // using dummy node to preserve some attributes (e.g. OPTION not selected)
6038
 
                if (nodes.length === 2) {
6039
 
                    ret = nodes[0].nextSibling;
6040
 
                } else {
6041
 
                    nodes[0].parentNode.removeChild(nodes[0]); 
6042
 
                     ret = Y_DOM._nl2frag(nodes, doc);
6043
 
                }
6044
 
            } else { // return multiple nodes as a fragment
6045
 
                 ret = Y_DOM._nl2frag(nodes, doc);
6046
 
            }
6047
 
        }
6048
 
 
6049
 
        return ret;
6050
 
    },
6051
 
 
6052
 
    _nl2frag: function(nodes, doc) {
6053
 
        var ret = null,
6054
 
            i, len;
6055
 
 
6056
 
        if (nodes && (nodes.push || nodes.item) && nodes[0]) {
6057
 
            doc = doc || nodes[0].ownerDocument; 
6058
 
            ret = doc.createDocumentFragment();
6059
 
 
6060
 
            if (nodes.item) { // convert live list to static array
6061
 
                nodes = Y.Array(nodes, 0, true);
6062
 
            }
6063
 
 
6064
 
            for (i = 0, len = nodes.length; i < len; i++) {
6065
 
                ret.appendChild(nodes[i]); 
6066
 
            }
6067
 
        } // else inline with log for minification
6068
 
        else { Y.log('unable to convert ' + nodes + ' to fragment', 'warn', 'dom'); }
6069
 
        return ret;
6070
 
    },
6071
 
 
6072
 
    /**
6073
 
     * Inserts content in a node at the given location 
6074
 
     * @method addHTML
6075
 
     * @param {HTMLElement} node The node to insert into
6076
 
     * @param {HTMLElement | Array | HTMLCollection} content The content to be inserted 
6077
 
     * @param {HTMLElement} where Where to insert the content
6078
 
     * If no "where" is given, content is appended to the node
6079
 
     * Possible values for "where"
6080
 
     * <dl>
6081
 
     * <dt>HTMLElement</dt>
6082
 
     * <dd>The element to insert before</dd>
6083
 
     * <dt>"replace"</dt>
6084
 
     * <dd>Replaces the existing HTML</dd>
6085
 
     * <dt>"before"</dt>
6086
 
     * <dd>Inserts before the existing HTML</dd>
6087
 
     * <dt>"before"</dt>
6088
 
     * <dd>Inserts content before the node</dd>
6089
 
     * <dt>"after"</dt>
6090
 
     * <dd>Inserts content after the node</dd>
6091
 
     * </dl>
6092
 
     */
6093
 
    addHTML: function(node, content, where) {
6094
 
        var nodeParent = node.parentNode,
6095
 
            i = 0,
6096
 
            item,
6097
 
            ret = content,
6098
 
            newNode;
6099
 
            
6100
 
 
6101
 
        if (content != undefined) { // not null or undefined (maybe 0)
6102
 
            if (content.nodeType) { // DOM node, just add it
6103
 
                newNode = content;
6104
 
            } else if (typeof content == 'string' || typeof content == 'number') {
6105
 
                ret = newNode = Y_DOM.create(content);
6106
 
            } else if (content[0] && content[0].nodeType) { // array or collection 
6107
 
                newNode = Y.config.doc.createDocumentFragment();
6108
 
                while ((item = content[i++])) {
6109
 
                    newNode.appendChild(item); // append to fragment for insertion
6110
 
                }
6111
 
            }
6112
 
        }
6113
 
 
6114
 
        if (where) {
6115
 
            if (where.nodeType) { // insert regardless of relationship to node
6116
 
                where.parentNode.insertBefore(newNode, where);
6117
 
            } else {
6118
 
                switch (where) {
6119
 
                    case 'replace':
6120
 
                        while (node.firstChild) {
6121
 
                            node.removeChild(node.firstChild);
6122
 
                        }
6123
 
                        if (newNode) { // allow empty content to clear node
6124
 
                            node.appendChild(newNode);
6125
 
                        }
6126
 
                        break;
6127
 
                    case 'before':
6128
 
                        nodeParent.insertBefore(newNode, node);
6129
 
                        break;
6130
 
                    case 'after':
6131
 
                        if (node.nextSibling) { // IE errors if refNode is null
6132
 
                            nodeParent.insertBefore(newNode, node.nextSibling);
6133
 
                        } else {
6134
 
                            nodeParent.appendChild(newNode);
6135
 
                        }
6136
 
                        break;
6137
 
                    default:
6138
 
                        node.appendChild(newNode);
6139
 
                }
6140
 
            }
6141
 
        } else if (newNode) {
6142
 
            node.appendChild(newNode);
6143
 
        }
6144
 
 
6145
 
        return ret;
6146
 
    }
6147
 
});
6148
 
 
6149
 
addFeature('innerhtml', 'table', {
6150
 
    test: function() {
6151
 
        var node = Y.config.doc.createElement('table');
6152
 
        try {
6153
 
            node.innerHTML = '<tbody></tbody>';
6154
 
        } catch(e) {
6155
 
            return false;
6156
 
        }
6157
 
        return (node.firstChild && node.firstChild.nodeName === 'TBODY');
6158
 
    }
6159
 
});
6160
 
 
6161
 
addFeature('innerhtml-div', 'tr', {
6162
 
    test: function() {
6163
 
        return createFromDIV('<tr></tr>', 'tr');
6164
 
    }
6165
 
});
6166
 
 
6167
 
addFeature('innerhtml-div', 'script', {
6168
 
    test: function() {
6169
 
        return createFromDIV('<script></script>', 'script');
6170
 
    }
6171
 
});
6172
 
 
6173
 
if (!testFeature('innerhtml', 'table')) {
6174
 
    // TODO: thead/tfoot with nested tbody
6175
 
        // IE adds TBODY when creating TABLE elements (which may share this impl)
6176
 
    creators.tbody = function(html, doc) {
6177
 
        var frag = Y_DOM.create(TABLE_OPEN + html + TABLE_CLOSE, doc),
6178
 
            tb = frag.children.tags('tbody')[0];
6179
 
 
6180
 
        if (frag.children.length > 1 && tb && !re_tbody.test(html)) {
6181
 
            tb.parentNode.removeChild(tb); // strip extraneous tbody
6182
 
        }
6183
 
        return frag;
6184
 
    };
6185
 
}
6186
 
 
6187
 
if (!testFeature('innerhtml-div', 'script')) {
6188
 
    creators.script = function(html, doc) {
6189
 
        var frag = doc.createElement('div');
6190
 
 
6191
 
        frag.innerHTML = '-' + html;
6192
 
        frag.removeChild(frag.firstChild);
6193
 
        return frag;
6194
 
    }
6195
 
 
6196
 
    creators.link = creators.style = creators.script;
6197
 
}
6198
 
 
6199
 
if (!testFeature('innerhtml-div', 'tr')) {
6200
 
    Y.mix(creators, {
6201
 
        option: function(html, doc) {
6202
 
            return Y_DOM.create('<select><option class="yui3-big-dummy" selected></option>' + html + '</select>', doc);
6203
 
        },
6204
 
 
6205
 
        tr: function(html, doc) {
6206
 
            return Y_DOM.create('<tbody>' + html + '</tbody>', doc);
6207
 
        },
6208
 
 
6209
 
        td: function(html, doc) {
6210
 
            return Y_DOM.create('<tr>' + html + '</tr>', doc);
6211
 
        }, 
6212
 
 
6213
 
        col: function(html, doc) {
6214
 
            return Y_DOM.create('<colgroup>' + html + '</colgroup>', doc);
6215
 
        }, 
6216
 
 
6217
 
        tbody: 'table'
6218
 
    });
6219
 
 
6220
 
    Y.mix(creators, {
6221
 
        legend: 'fieldset',
6222
 
        th: creators.td,
6223
 
        thead: creators.tbody,
6224
 
        tfoot: creators.tbody,
6225
 
        caption: creators.tbody,
6226
 
        colgroup: creators.tbody,
6227
 
        optgroup: creators.option
6228
 
    });
6229
 
}
6230
 
 
6231
 
Y_DOM.creators = creators;
6232
 
Y.mix(Y.DOM, {
6233
 
    /**
6234
 
     * Sets the width of the element to the given size, regardless
6235
 
     * of box model, border, padding, etc.
6236
 
     * @method setWidth
6237
 
     * @param {HTMLElement} element The DOM element. 
6238
 
     * @param {String|Int} size The pixel height to size to
6239
 
     */
6240
 
 
6241
 
    setWidth: function(node, size) {
6242
 
        Y.DOM._setSize(node, 'width', size);
6243
 
    },
6244
 
 
6245
 
    /**
6246
 
     * Sets the height of the element to the given size, regardless
6247
 
     * of box model, border, padding, etc.
6248
 
     * @method setHeight
6249
 
     * @param {HTMLElement} element The DOM element. 
6250
 
     * @param {String|Int} size The pixel height to size to
6251
 
     */
6252
 
 
6253
 
    setHeight: function(node, size) {
6254
 
        Y.DOM._setSize(node, 'height', size);
6255
 
    },
6256
 
 
6257
 
    _setSize: function(node, prop, val) {
6258
 
        val = (val > 0) ? val : 0;
6259
 
        var size = 0;
6260
 
 
6261
 
        node.style[prop] = val + 'px';
6262
 
        size = (prop === 'height') ? node.offsetHeight : node.offsetWidth;
6263
 
 
6264
 
        if (size > val) {
6265
 
            val = val - (size - val);
6266
 
 
6267
 
            if (val < 0) {
6268
 
                val = 0;
6269
 
            }
6270
 
 
6271
 
            node.style[prop] = val + 'px';
6272
 
        }
6273
 
    }
6274
 
});
6275
 
 
6276
 
 
6277
 
}, '3.4.1' ,{requires:['dom-core']});
6278
 
YUI.add('dom-style', function(Y) {
6279
 
 
6280
 
(function(Y) {
6281
 
/** 
6282
 
 * Add style management functionality to DOM.
6283
 
 * @module dom
6284
 
 * @submodule dom-style
6285
 
 * @for DOM
6286
 
 */
6287
 
 
6288
 
var DOCUMENT_ELEMENT = 'documentElement',
6289
 
    DEFAULT_VIEW = 'defaultView',
6290
 
    OWNER_DOCUMENT = 'ownerDocument',
6291
 
    STYLE = 'style',
6292
 
    FLOAT = 'float',
6293
 
    CSS_FLOAT = 'cssFloat',
6294
 
    STYLE_FLOAT = 'styleFloat',
6295
 
    TRANSPARENT = 'transparent',
6296
 
    GET_COMPUTED_STYLE = 'getComputedStyle',
6297
 
    GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
6298
 
 
6299
 
    WINDOW = Y.config.win,
6300
 
    DOCUMENT = Y.config.doc,
6301
 
    UNDEFINED = undefined,
6302
 
 
6303
 
    Y_DOM = Y.DOM,
6304
 
 
6305
 
    TRANSFORM = 'transform',
6306
 
    VENDOR_TRANSFORM = [
6307
 
        'WebkitTransform',
6308
 
        'MozTransform',
6309
 
        'OTransform'
6310
 
    ],
6311
 
 
6312
 
    re_color = /color$/i,
6313
 
    re_unit = /width|height|top|left|right|bottom|margin|padding/i;
6314
 
 
6315
 
Y.Array.each(VENDOR_TRANSFORM, function(val) {
6316
 
    if (val in DOCUMENT[DOCUMENT_ELEMENT].style) {
6317
 
        TRANSFORM = val;
6318
 
    }
6319
 
});
6320
 
 
6321
 
Y.mix(Y_DOM, {
6322
 
    DEFAULT_UNIT: 'px',
6323
 
 
6324
 
    CUSTOM_STYLES: {
6325
 
    },
6326
 
 
6327
 
 
6328
 
    /**
6329
 
     * Sets a style property for a given element.
6330
 
     * @method setStyle
6331
 
     * @param {HTMLElement} An HTMLElement to apply the style to.
6332
 
     * @param {String} att The style property to set. 
6333
 
     * @param {String|Number} val The value. 
6334
 
     */
6335
 
    setStyle: function(node, att, val, style) {
6336
 
        style = style || node.style;
6337
 
        var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES;
6338
 
 
6339
 
        if (style) {
6340
 
            if (val === null || val === '') { // normalize unsetting
6341
 
                val = '';
6342
 
            } else if (!isNaN(new Number(val)) && re_unit.test(att)) { // number values may need a unit
6343
 
                val += Y_DOM.DEFAULT_UNIT;
6344
 
            }
6345
 
 
6346
 
            if (att in CUSTOM_STYLES) {
6347
 
                if (CUSTOM_STYLES[att].set) {
6348
 
                    CUSTOM_STYLES[att].set(node, val, style);
6349
 
                    return; // NOTE: return
6350
 
                } else if (typeof CUSTOM_STYLES[att] === 'string') {
6351
 
                    att = CUSTOM_STYLES[att];
6352
 
                }
6353
 
            } else if (att === '') { // unset inline styles
6354
 
                att = 'cssText';
6355
 
                val = '';
6356
 
            }
6357
 
            style[att] = val; 
6358
 
        }
6359
 
    },
6360
 
 
6361
 
    /**
6362
 
     * Returns the current style value for the given property.
6363
 
     * @method getStyle
6364
 
     * @param {HTMLElement} An HTMLElement to get the style from.
6365
 
     * @param {String} att The style property to get. 
6366
 
     */
6367
 
    getStyle: function(node, att, style) {
6368
 
        style = style || node.style;
6369
 
        var CUSTOM_STYLES = Y_DOM.CUSTOM_STYLES,
6370
 
            val = '';
6371
 
 
6372
 
        if (style) {
6373
 
            if (att in CUSTOM_STYLES) {
6374
 
                if (CUSTOM_STYLES[att].get) {
6375
 
                    return CUSTOM_STYLES[att].get(node, att, style); // NOTE: return
6376
 
                } else if (typeof CUSTOM_STYLES[att] === 'string') {
6377
 
                    att = CUSTOM_STYLES[att];
6378
 
                }
6379
 
            }
6380
 
            val = style[att];
6381
 
            if (val === '') { // TODO: is empty string sufficient?
6382
 
                val = Y_DOM[GET_COMPUTED_STYLE](node, att);
6383
 
            }
6384
 
        }
6385
 
 
6386
 
        return val;
6387
 
    },
6388
 
 
6389
 
    /**
6390
 
     * Sets multiple style properties.
6391
 
     * @method setStyles
6392
 
     * @param {HTMLElement} node An HTMLElement to apply the styles to. 
6393
 
     * @param {Object} hash An object literal of property:value pairs. 
6394
 
     */
6395
 
    setStyles: function(node, hash) {
6396
 
        var style = node.style;
6397
 
        Y.each(hash, function(v, n) {
6398
 
            Y_DOM.setStyle(node, n, v, style);
6399
 
        }, Y_DOM);
6400
 
    },
6401
 
 
6402
 
    /**
6403
 
     * Returns the computed style for the given node.
6404
 
     * @method getComputedStyle
6405
 
     * @param {HTMLElement} An HTMLElement to get the style from.
6406
 
     * @param {String} att The style property to get. 
6407
 
     * @return {String} The computed value of the style property. 
6408
 
     */
6409
 
    getComputedStyle: function(node, att) {
6410
 
        var val = '',
6411
 
            doc = node[OWNER_DOCUMENT];
6412
 
 
6413
 
        if (node[STYLE] && doc[DEFAULT_VIEW] && doc[DEFAULT_VIEW][GET_COMPUTED_STYLE]) {
6414
 
            val = doc[DEFAULT_VIEW][GET_COMPUTED_STYLE](node, null)[att];
6415
 
        }
6416
 
        return val;
6417
 
    }
6418
 
});
6419
 
 
6420
 
// normalize reserved word float alternatives ("cssFloat" or "styleFloat")
6421
 
if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][CSS_FLOAT] !== UNDEFINED) {
6422
 
    Y_DOM.CUSTOM_STYLES[FLOAT] = CSS_FLOAT;
6423
 
} else if (DOCUMENT[DOCUMENT_ELEMENT][STYLE][STYLE_FLOAT] !== UNDEFINED) {
6424
 
    Y_DOM.CUSTOM_STYLES[FLOAT] = STYLE_FLOAT;
6425
 
}
6426
 
 
6427
 
// fix opera computedStyle default color unit (convert to rgb)
6428
 
if (Y.UA.opera) {
6429
 
    Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
6430
 
        var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
6431
 
            val = view[GET_COMPUTED_STYLE](node, '')[att];
6432
 
 
6433
 
        if (re_color.test(att)) {
6434
 
            val = Y.Color.toRGB(val);
6435
 
        }
6436
 
 
6437
 
        return val;
6438
 
    };
6439
 
 
6440
 
}
6441
 
 
6442
 
// safari converts transparent to rgba(), others use "transparent"
6443
 
if (Y.UA.webkit) {
6444
 
    Y_DOM[GET_COMPUTED_STYLE] = function(node, att) {
6445
 
        var view = node[OWNER_DOCUMENT][DEFAULT_VIEW],
6446
 
            val = view[GET_COMPUTED_STYLE](node, '')[att];
6447
 
 
6448
 
        if (val === 'rgba(0, 0, 0, 0)') {
6449
 
            val = TRANSPARENT; 
6450
 
        }
6451
 
 
6452
 
        return val;
6453
 
    };
6454
 
 
6455
 
}
6456
 
 
6457
 
Y.DOM._getAttrOffset = function(node, attr) {
6458
 
    var val = Y.DOM[GET_COMPUTED_STYLE](node, attr),
6459
 
        offsetParent = node.offsetParent,
6460
 
        position,
6461
 
        parentOffset,
6462
 
        offset;
6463
 
 
6464
 
    if (val === 'auto') {
6465
 
        position = Y.DOM.getStyle(node, 'position');
6466
 
        if (position === 'static' || position === 'relative') {
6467
 
            val = 0;    
6468
 
        } else if (offsetParent && offsetParent[GET_BOUNDING_CLIENT_RECT]) {
6469
 
            parentOffset = offsetParent[GET_BOUNDING_CLIENT_RECT]()[attr];
6470
 
            offset = node[GET_BOUNDING_CLIENT_RECT]()[attr];
6471
 
            if (attr === 'left' || attr === 'top') {
6472
 
                val = offset - parentOffset;
6473
 
            } else {
6474
 
                val = parentOffset - node[GET_BOUNDING_CLIENT_RECT]()[attr];
6475
 
            }
6476
 
        }
6477
 
    }
6478
 
 
6479
 
    return val;
6480
 
};
6481
 
 
6482
 
Y.DOM._getOffset = function(node) {
6483
 
    var pos,
6484
 
        xy = null;
6485
 
 
6486
 
    if (node) {
6487
 
        pos = Y_DOM.getStyle(node, 'position');
6488
 
        xy = [
6489
 
            parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'left'), 10),
6490
 
            parseInt(Y_DOM[GET_COMPUTED_STYLE](node, 'top'), 10)
6491
 
        ];
6492
 
 
6493
 
        if ( isNaN(xy[0]) ) { // in case of 'auto'
6494
 
            xy[0] = parseInt(Y_DOM.getStyle(node, 'left'), 10); // try inline
6495
 
            if ( isNaN(xy[0]) ) { // default to offset value
6496
 
                xy[0] = (pos === 'relative') ? 0 : node.offsetLeft || 0;
6497
 
            }
6498
 
        } 
6499
 
 
6500
 
        if ( isNaN(xy[1]) ) { // in case of 'auto'
6501
 
            xy[1] = parseInt(Y_DOM.getStyle(node, 'top'), 10); // try inline
6502
 
            if ( isNaN(xy[1]) ) { // default to offset value
6503
 
                xy[1] = (pos === 'relative') ? 0 : node.offsetTop || 0;
6504
 
            }
6505
 
        } 
6506
 
    }
6507
 
 
6508
 
    return xy;
6509
 
 
6510
 
};
6511
 
 
6512
 
Y_DOM.CUSTOM_STYLES.transform = {
6513
 
    set: function(node, val, style) {
6514
 
        style[TRANSFORM] = val;
6515
 
    },
6516
 
 
6517
 
    get: function(node, style) {
6518
 
        return Y_DOM[GET_COMPUTED_STYLE](node, TRANSFORM);
6519
 
    }
6520
 
};
6521
 
 
6522
 
 
6523
 
})(Y);
6524
 
(function(Y) {
6525
 
var PARSE_INT = parseInt,
6526
 
    RE = RegExp;
6527
 
 
6528
 
Y.Color = {
6529
 
    KEYWORDS: {
6530
 
        black: '000',
6531
 
        silver: 'c0c0c0',
6532
 
        gray: '808080',
6533
 
        white: 'fff',
6534
 
        maroon: '800000',
6535
 
        red: 'f00',
6536
 
        purple: '800080',
6537
 
        fuchsia: 'f0f',
6538
 
        green: '008000',
6539
 
        lime: '0f0',
6540
 
        olive: '808000',
6541
 
        yellow: 'ff0',
6542
 
        navy: '000080',
6543
 
        blue: '00f',
6544
 
        teal: '008080',
6545
 
        aqua: '0ff'
6546
 
    },
6547
 
 
6548
 
    re_RGB: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
6549
 
    re_hex: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
6550
 
    re_hex3: /([0-9A-F])/gi,
6551
 
 
6552
 
    toRGB: function(val) {
6553
 
        if (!Y.Color.re_RGB.test(val)) {
6554
 
            val = Y.Color.toHex(val);
6555
 
        }
6556
 
 
6557
 
        if(Y.Color.re_hex.exec(val)) {
6558
 
            val = 'rgb(' + [
6559
 
                PARSE_INT(RE.$1, 16),
6560
 
                PARSE_INT(RE.$2, 16),
6561
 
                PARSE_INT(RE.$3, 16)
6562
 
            ].join(', ') + ')';
6563
 
        }
6564
 
        return val;
6565
 
    },
6566
 
 
6567
 
    toHex: function(val) {
6568
 
        val = Y.Color.KEYWORDS[val] || val;
6569
 
        if (Y.Color.re_RGB.exec(val)) {
6570
 
            val = [
6571
 
                Number(RE.$1).toString(16),
6572
 
                Number(RE.$2).toString(16),
6573
 
                Number(RE.$3).toString(16)
6574
 
            ];
6575
 
 
6576
 
            for (var i = 0; i < val.length; i++) {
6577
 
                if (val[i].length < 2) {
6578
 
                    val[i] = '0' + val[i];
6579
 
                }
6580
 
            }
6581
 
 
6582
 
            val = val.join('');
6583
 
        }
6584
 
 
6585
 
        if (val.length < 6) {
6586
 
            val = val.replace(Y.Color.re_hex3, '$1$1');
6587
 
        }
6588
 
 
6589
 
        if (val !== 'transparent' && val.indexOf('#') < 0) {
6590
 
            val = '#' + val;
6591
 
        }
6592
 
 
6593
 
        return val.toUpperCase();
6594
 
    }
6595
 
};
6596
 
})(Y);
6597
 
 
6598
 
 
6599
 
 
6600
 
}, '3.4.1' ,{requires:['dom-base']});
6601
 
YUI.add('dom-style-ie', function(Y) {
6602
 
 
6603
 
(function(Y) {
6604
 
var HAS_LAYOUT = 'hasLayout',
6605
 
    PX = 'px',
6606
 
    FILTER = 'filter',
6607
 
    FILTERS = 'filters',
6608
 
    OPACITY = 'opacity',
6609
 
    AUTO = 'auto',
6610
 
 
6611
 
    BORDER_WIDTH = 'borderWidth',
6612
 
    BORDER_TOP_WIDTH = 'borderTopWidth',
6613
 
    BORDER_RIGHT_WIDTH = 'borderRightWidth',
6614
 
    BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
6615
 
    BORDER_LEFT_WIDTH = 'borderLeftWidth',
6616
 
    WIDTH = 'width',
6617
 
    HEIGHT = 'height',
6618
 
    TRANSPARENT = 'transparent',
6619
 
    VISIBLE = 'visible',
6620
 
    GET_COMPUTED_STYLE = 'getComputedStyle',
6621
 
    UNDEFINED = undefined,
6622
 
    documentElement = Y.config.doc.documentElement,
6623
 
 
6624
 
    testFeature = Y.Features.test,
6625
 
    addFeature = Y.Features.add,
6626
 
 
6627
 
    // TODO: unit-less lineHeight (e.g. 1.22)
6628
 
    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,
6629
 
 
6630
 
    isIE8 = (Y.UA.ie >= 8),
6631
 
 
6632
 
    _getStyleObj = function(node) {
6633
 
        return node.currentStyle || node.style;
6634
 
    },
6635
 
 
6636
 
    ComputedStyle = {
6637
 
        CUSTOM_STYLES: {},
6638
 
 
6639
 
        get: function(el, property) {
6640
 
            var value = '',
6641
 
                current;
6642
 
 
6643
 
            if (el) {
6644
 
                    current = _getStyleObj(el)[property];
6645
 
 
6646
 
                if (property === OPACITY && Y.DOM.CUSTOM_STYLES[OPACITY]) {
6647
 
                    value = Y.DOM.CUSTOM_STYLES[OPACITY].get(el);        
6648
 
                } else if (!current || (current.indexOf && current.indexOf(PX) > -1)) { // no need to convert
6649
 
                    value = current;
6650
 
                } else if (Y.DOM.IE.COMPUTED[property]) { // use compute function
6651
 
                    value = Y.DOM.IE.COMPUTED[property](el, property);
6652
 
                } else if (re_unit.test(current)) { // convert to pixel
6653
 
                    value = ComputedStyle.getPixel(el, property) + PX;
6654
 
                } else {
6655
 
                    value = current;
6656
 
                }
6657
 
            }
6658
 
 
6659
 
            return value;
6660
 
        },
6661
 
 
6662
 
        sizeOffsets: {
6663
 
            width: ['Left', 'Right'],
6664
 
            height: ['Top', 'Bottom'],
6665
 
            top: ['Top'],
6666
 
            bottom: ['Bottom']
6667
 
        },
6668
 
 
6669
 
        getOffset: function(el, prop) {
6670
 
            var current = _getStyleObj(el)[prop],                     // value of "width", "top", etc.
6671
 
                capped = prop.charAt(0).toUpperCase() + prop.substr(1), // "Width", "Top", etc.
6672
 
                offset = 'offset' + capped,                             // "offsetWidth", "offsetTop", etc.
6673
 
                pixel = 'pixel' + capped,                               // "pixelWidth", "pixelTop", etc.
6674
 
                sizeOffsets = ComputedStyle.sizeOffsets[prop], 
6675
 
                mode = el.ownerDocument.compatMode,
6676
 
                value = '';
6677
 
 
6678
 
            // IE pixelWidth incorrect for percent
6679
 
            // manually compute by subtracting padding and border from offset size
6680
 
            // NOTE: clientWidth/Height (size minus border) is 0 when current === AUTO so offsetHeight is used
6681
 
            // reverting to auto from auto causes position stacking issues (old impl)
6682
 
            if (current === AUTO || current.indexOf('%') > -1) {
6683
 
                value = el['offset' + capped];
6684
 
 
6685
 
                if (mode !== 'BackCompat') {
6686
 
                    if (sizeOffsets[0]) {
6687
 
                        value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[0]);
6688
 
                        value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[0] + 'Width', 1);
6689
 
                    }
6690
 
 
6691
 
                    if (sizeOffsets[1]) {
6692
 
                        value -= ComputedStyle.getPixel(el, 'padding' + sizeOffsets[1]);
6693
 
                        value -= ComputedStyle.getBorderWidth(el, 'border' + sizeOffsets[1] + 'Width', 1);
6694
 
                    }
6695
 
                }
6696
 
 
6697
 
            } else { // use style.pixelWidth, etc. to convert to pixels
6698
 
                // need to map style.width to currentStyle (no currentStyle.pixelWidth)
6699
 
                if (!el.style[pixel] && !el.style[prop]) {
6700
 
                    el.style[prop] = current;
6701
 
                }
6702
 
                value = el.style[pixel];
6703
 
                
6704
 
            }
6705
 
            return value + PX;
6706
 
        },
6707
 
 
6708
 
        borderMap: {
6709
 
            thin: (isIE8) ? '1px' : '2px',
6710
 
            medium: (isIE8) ? '3px': '4px', 
6711
 
            thick: (isIE8) ? '5px' : '6px'
6712
 
        },
6713
 
 
6714
 
        getBorderWidth: function(el, property, omitUnit) {
6715
 
            var unit = omitUnit ? '' : PX,
6716
 
                current = el.currentStyle[property];
6717
 
 
6718
 
            if (current.indexOf(PX) < 0) { // look up keywords if a border exists
6719
 
                if (ComputedStyle.borderMap[current] &&
6720
 
                        el.currentStyle.borderStyle !== 'none') {
6721
 
                    current = ComputedStyle.borderMap[current];
6722
 
                } else { // otherwise no border (default is "medium")
6723
 
                    current = 0;
6724
 
                }
6725
 
            }
6726
 
            return (omitUnit) ? parseFloat(current) : current;
6727
 
        },
6728
 
 
6729
 
        getPixel: function(node, att) {
6730
 
            // use pixelRight to convert to px
6731
 
            var val = null,
6732
 
                style = _getStyleObj(node),
6733
 
                styleRight = style.right,
6734
 
                current = style[att];
6735
 
 
6736
 
            node.style.right = current;
6737
 
            val = node.style.pixelRight;
6738
 
            node.style.right = styleRight; // revert
6739
 
 
6740
 
            return val;
6741
 
        },
6742
 
 
6743
 
        getMargin: function(node, att) {
6744
 
            var val,
6745
 
                style = _getStyleObj(node);
6746
 
 
6747
 
            if (style[att] == AUTO) {
6748
 
                val = 0;
6749
 
            } else {
6750
 
                val = ComputedStyle.getPixel(node, att);
6751
 
            }
6752
 
            return val + PX;
6753
 
        },
6754
 
 
6755
 
        getVisibility: function(node, att) {
6756
 
            var current;
6757
 
            while ( (current = node.currentStyle) && current[att] == 'inherit') { // NOTE: assignment in test
6758
 
                node = node.parentNode;
6759
 
            }
6760
 
            return (current) ? current[att] : VISIBLE;
6761
 
        },
6762
 
 
6763
 
        getColor: function(node, att) {
6764
 
            var current = _getStyleObj(node)[att];
6765
 
 
6766
 
            if (!current || current === TRANSPARENT) {
6767
 
                Y.DOM.elementByAxis(node, 'parentNode', null, function(parent) {
6768
 
                    current = _getStyleObj(parent)[att];
6769
 
                    if (current && current !== TRANSPARENT) {
6770
 
                        node = parent;
6771
 
                        return true;
6772
 
                    }
6773
 
                });
6774
 
            }
6775
 
 
6776
 
            return Y.Color.toRGB(current);
6777
 
        },
6778
 
 
6779
 
        getBorderColor: function(node, att) {
6780
 
            var current = _getStyleObj(node),
6781
 
                val = current[att] || current.color;
6782
 
            return Y.Color.toRGB(Y.Color.toHex(val));
6783
 
        }
6784
 
    },
6785
 
 
6786
 
    //fontSize: getPixelFont,
6787
 
    IEComputed = {};
6788
 
 
6789
 
addFeature('style', 'computedStyle', {
6790
 
    test: function() {
6791
 
        return 'getComputedStyle' in Y.config.win;
6792
 
    }
6793
 
});
6794
 
 
6795
 
addFeature('style', 'opacity', {
6796
 
    test: function() {
6797
 
        return 'opacity' in documentElement.style;
6798
 
    }
6799
 
});
6800
 
 
6801
 
addFeature('style', 'filter', {
6802
 
    test: function() {
6803
 
        return 'filters' in documentElement;
6804
 
    }
6805
 
});
6806
 
 
6807
 
// use alpha filter for IE opacity
6808
 
if (!testFeature('style', 'opacity') && testFeature('style', 'filter')) {
6809
 
    Y.DOM.CUSTOM_STYLES[OPACITY] = {
6810
 
        get: function(node) {
6811
 
            var val = 100;
6812
 
            try { // will error if no DXImageTransform
6813
 
                val = node[FILTERS]['DXImageTransform.Microsoft.Alpha'][OPACITY];
6814
 
 
6815
 
            } catch(e) {
6816
 
                try { // make sure its in the document
6817
 
                    val = node[FILTERS]('alpha')[OPACITY];
6818
 
                } catch(err) {
6819
 
                    Y.log('getStyle: IE opacity filter not found; returning 1', 'warn', 'dom-style');
6820
 
                }
6821
 
            }
6822
 
            return val / 100;
6823
 
        },
6824
 
 
6825
 
        set: function(node, val, style) {
6826
 
            var current,
6827
 
                styleObj = _getStyleObj(node),
6828
 
                currentFilter = styleObj[FILTER];
6829
 
 
6830
 
            style = style || node.style;
6831
 
            if (val === '') { // normalize inline style behavior
6832
 
                current = (OPACITY in styleObj) ? styleObj[OPACITY] : 1; // revert to original opacity
6833
 
                val = current;
6834
 
            }
6835
 
 
6836
 
            if (typeof currentFilter == 'string') { // in case not appended
6837
 
                style[FILTER] = currentFilter.replace(/alpha([^)]*\))/gi, '') +
6838
 
                        ((val < 1) ? 'alpha(' + OPACITY + '=' + val * 100 + ')' : '');
6839
 
 
6840
 
                if (!style[FILTER]) {
6841
 
                    style.removeAttribute(FILTER);
6842
 
                }
6843
 
 
6844
 
                if (!styleObj[HAS_LAYOUT]) {
6845
 
                    style.zoom = 1; // needs layout 
6846
 
                }
6847
 
            }
6848
 
        }
6849
 
    };
6850
 
}
6851
 
 
6852
 
try {
6853
 
    Y.config.doc.createElement('div').style.height = '-1px';
6854
 
} catch(e) { // IE throws error on invalid style set; trap common cases
6855
 
    Y.DOM.CUSTOM_STYLES.height = {
6856
 
        set: function(node, val, style) {
6857
 
            var floatVal = parseFloat(val);
6858
 
            if (floatVal >= 0 || val === 'auto' || val === '') {
6859
 
                style.height = val;
6860
 
            } else {
6861
 
                Y.log('invalid style value for height: ' + val, 'warn', 'dom-style');
6862
 
            }
6863
 
        }
6864
 
    };
6865
 
 
6866
 
    Y.DOM.CUSTOM_STYLES.width = {
6867
 
        set: function(node, val, style) {
6868
 
            var floatVal = parseFloat(val);
6869
 
            if (floatVal >= 0 || val === 'auto' || val === '') {
6870
 
                style.width = val;
6871
 
            } else {
6872
 
                Y.log('invalid style value for width: ' + val, 'warn', 'dom-style');
6873
 
            }
6874
 
        }
6875
 
    };
6876
 
}
6877
 
 
6878
 
if (!testFeature('style', 'computedStyle')) {
6879
 
    // TODO: top, right, bottom, left
6880
 
    IEComputed[WIDTH] = IEComputed[HEIGHT] = ComputedStyle.getOffset;
6881
 
 
6882
 
    IEComputed.color = IEComputed.backgroundColor = ComputedStyle.getColor;
6883
 
 
6884
 
    IEComputed[BORDER_WIDTH] = IEComputed[BORDER_TOP_WIDTH] = IEComputed[BORDER_RIGHT_WIDTH] =
6885
 
            IEComputed[BORDER_BOTTOM_WIDTH] = IEComputed[BORDER_LEFT_WIDTH] =
6886
 
            ComputedStyle.getBorderWidth;
6887
 
 
6888
 
    IEComputed.marginTop = IEComputed.marginRight = IEComputed.marginBottom =
6889
 
            IEComputed.marginLeft = ComputedStyle.getMargin;
6890
 
 
6891
 
    IEComputed.visibility = ComputedStyle.getVisibility;
6892
 
    IEComputed.borderColor = IEComputed.borderTopColor =
6893
 
            IEComputed.borderRightColor = IEComputed.borderBottomColor =
6894
 
            IEComputed.borderLeftColor = ComputedStyle.getBorderColor;
6895
 
 
6896
 
    Y.DOM[GET_COMPUTED_STYLE] = ComputedStyle.get; 
6897
 
 
6898
 
    Y.namespace('DOM.IE');
6899
 
    Y.DOM.IE.COMPUTED = IEComputed;
6900
 
    Y.DOM.IE.ComputedStyle = ComputedStyle;
6901
 
}
6902
 
 
6903
 
})(Y);
6904
 
 
6905
 
 
6906
 
}, '3.4.1' ,{requires:['dom-style']});
6907
 
YUI.add('dom-screen', function(Y) {
6908
 
 
6909
 
(function(Y) {
6910
 
 
6911
 
/**
6912
 
 * Adds position and region management functionality to DOM.
6913
 
 * @module dom
6914
 
 * @submodule dom-screen
6915
 
 * @for DOM
6916
 
 */
6917
 
 
6918
 
var DOCUMENT_ELEMENT = 'documentElement',
6919
 
    COMPAT_MODE = 'compatMode',
6920
 
    POSITION = 'position',
6921
 
    FIXED = 'fixed',
6922
 
    RELATIVE = 'relative',
6923
 
    LEFT = 'left',
6924
 
    TOP = 'top',
6925
 
    _BACK_COMPAT = 'BackCompat',
6926
 
    MEDIUM = 'medium',
6927
 
    BORDER_LEFT_WIDTH = 'borderLeftWidth',
6928
 
    BORDER_TOP_WIDTH = 'borderTopWidth',
6929
 
    GET_BOUNDING_CLIENT_RECT = 'getBoundingClientRect',
6930
 
    GET_COMPUTED_STYLE = 'getComputedStyle',
6931
 
 
6932
 
    Y_DOM = Y.DOM,
6933
 
 
6934
 
    // TODO: how about thead/tbody/tfoot/tr?
6935
 
    // TODO: does caption matter?
6936
 
    RE_TABLE = /^t(?:able|d|h)$/i,
6937
 
 
6938
 
    SCROLL_NODE;
6939
 
 
6940
 
if (Y.UA.ie) {
6941
 
    if (Y.config.doc[COMPAT_MODE] !== 'BackCompat') {
6942
 
        SCROLL_NODE = DOCUMENT_ELEMENT; 
6943
 
    } else {
6944
 
        SCROLL_NODE = 'body';
6945
 
    }
6946
 
}
6947
 
 
6948
 
Y.mix(Y_DOM, {
6949
 
    /**
6950
 
     * Returns the inner height of the viewport (exludes scrollbar). 
6951
 
     * @method winHeight
6952
 
     * @return {Number} The current height of the viewport.
6953
 
     */
6954
 
    winHeight: function(node) {
6955
 
        var h = Y_DOM._getWinSize(node).height;
6956
 
        Y.log('winHeight returning ' + h, 'info', 'dom-screen');
6957
 
        return h;
6958
 
    },
6959
 
 
6960
 
    /**
6961
 
     * Returns the inner width of the viewport (exludes scrollbar). 
6962
 
     * @method winWidth
6963
 
     * @return {Number} The current width of the viewport.
6964
 
     */
6965
 
    winWidth: function(node) {
6966
 
        var w = Y_DOM._getWinSize(node).width;
6967
 
        Y.log('winWidth returning ' + w, 'info', 'dom-screen');
6968
 
        return w;
6969
 
    },
6970
 
 
6971
 
    /**
6972
 
     * Document height 
6973
 
     * @method docHeight
6974
 
     * @return {Number} The current height of the document.
6975
 
     */
6976
 
    docHeight:  function(node) {
6977
 
        var h = Y_DOM._getDocSize(node).height;
6978
 
        Y.log('docHeight returning ' + h, 'info', 'dom-screen');
6979
 
        return Math.max(h, Y_DOM._getWinSize(node).height);
6980
 
    },
6981
 
 
6982
 
    /**
6983
 
     * Document width 
6984
 
     * @method docWidth
6985
 
     * @return {Number} The current width of the document.
6986
 
     */
6987
 
    docWidth:  function(node) {
6988
 
        var w = Y_DOM._getDocSize(node).width;
6989
 
        Y.log('docWidth returning ' + w, 'info', 'dom-screen');
6990
 
        return Math.max(w, Y_DOM._getWinSize(node).width);
6991
 
    },
6992
 
 
6993
 
    /**
6994
 
     * Amount page has been scroll horizontally 
6995
 
     * @method docScrollX
6996
 
     * @return {Number} The current amount the screen is scrolled horizontally.
6997
 
     */
6998
 
    docScrollX: function(node, doc) {
6999
 
        doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
7000
 
        var dv = doc.defaultView,
7001
 
            pageOffset = (dv) ? dv.pageXOffset : 0;
7002
 
        return Math.max(doc[DOCUMENT_ELEMENT].scrollLeft, doc.body.scrollLeft, pageOffset);
7003
 
    },
7004
 
 
7005
 
    /**
7006
 
     * Amount page has been scroll vertically 
7007
 
     * @method docScrollY
7008
 
     * @return {Number} The current amount the screen is scrolled vertically.
7009
 
     */
7010
 
    docScrollY:  function(node, doc) {
7011
 
        doc = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc; // perf optimization
7012
 
        var dv = doc.defaultView,
7013
 
            pageOffset = (dv) ? dv.pageYOffset : 0;
7014
 
        return Math.max(doc[DOCUMENT_ELEMENT].scrollTop, doc.body.scrollTop, pageOffset);
7015
 
    },
7016
 
 
7017
 
    /**
7018
 
     * Gets the current position of an element based on page coordinates. 
7019
 
     * Element must be part of the DOM tree to have page coordinates
7020
 
     * (display:none or elements not appended return false).
7021
 
     * @method getXY
7022
 
     * @param element The target element
7023
 
     * @return {Array} The XY position of the element
7024
 
 
7025
 
     TODO: test inDocument/display?
7026
 
     */
7027
 
    getXY: function() {
7028
 
        if (Y.config.doc[DOCUMENT_ELEMENT][GET_BOUNDING_CLIENT_RECT]) {
7029
 
            return function(node) {
7030
 
                var xy = null,
7031
 
                    scrollLeft,
7032
 
                    scrollTop,
7033
 
                    box,
7034
 
                    off1, off2,
7035
 
                    bLeft, bTop,
7036
 
                    mode,
7037
 
                    doc,
7038
 
                    inDoc,
7039
 
                    rootNode;
7040
 
 
7041
 
                if (node && node.tagName) {
7042
 
                    doc = node.ownerDocument;
7043
 
                    rootNode = doc[DOCUMENT_ELEMENT];
7044
 
 
7045
 
                    // inline inDoc check for perf
7046
 
                    if (rootNode.contains) {
7047
 
                        inDoc = rootNode.contains(node); 
7048
 
                    } else {
7049
 
                        inDoc = Y.DOM.contains(rootNode, node);
7050
 
                    }
7051
 
 
7052
 
                    if (inDoc) {
7053
 
                        scrollLeft = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollLeft : Y_DOM.docScrollX(node, doc);
7054
 
                        scrollTop = (SCROLL_NODE) ? doc[SCROLL_NODE].scrollTop : Y_DOM.docScrollY(node, doc);
7055
 
                        box = node[GET_BOUNDING_CLIENT_RECT]();
7056
 
                        xy = [box.left, box.top];
7057
 
 
7058
 
                            if (Y.UA.ie) {
7059
 
                                off1 = 2;
7060
 
                                off2 = 2;
7061
 
                                mode = doc[COMPAT_MODE];
7062
 
                                bLeft = Y_DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_LEFT_WIDTH);
7063
 
                                bTop = Y_DOM[GET_COMPUTED_STYLE](doc[DOCUMENT_ELEMENT], BORDER_TOP_WIDTH);
7064
 
 
7065
 
                                if (Y.UA.ie === 6) {
7066
 
                                    if (mode !== _BACK_COMPAT) {
7067
 
                                        off1 = 0;
7068
 
                                        off2 = 0;
7069
 
                                    }
7070
 
                                }
7071
 
                                
7072
 
                                if ((mode == _BACK_COMPAT)) {
7073
 
                                    if (bLeft !== MEDIUM) {
7074
 
                                        off1 = parseInt(bLeft, 10);
7075
 
                                    }
7076
 
                                    if (bTop !== MEDIUM) {
7077
 
                                        off2 = parseInt(bTop, 10);
7078
 
                                    }
7079
 
                                }
7080
 
                                
7081
 
                                xy[0] -= off1;
7082
 
                                xy[1] -= off2;
7083
 
 
7084
 
                            }
7085
 
 
7086
 
                        if ((scrollTop || scrollLeft)) {
7087
 
                            if (!Y.UA.ios || (Y.UA.ios >= 4.2)) {
7088
 
                                xy[0] += scrollLeft;
7089
 
                                xy[1] += scrollTop;
7090
 
                            }
7091
 
                            
7092
 
                        }
7093
 
                    } else {
7094
 
                        xy = Y_DOM._getOffset(node);       
7095
 
                    }
7096
 
                }
7097
 
                return xy;                   
7098
 
            }
7099
 
        } else {
7100
 
            return function(node) { // manually calculate by crawling up offsetParents
7101
 
                //Calculate the Top and Left border sizes (assumes pixels)
7102
 
                var xy = null,
7103
 
                    doc,
7104
 
                    parentNode,
7105
 
                    bCheck,
7106
 
                    scrollTop,
7107
 
                    scrollLeft;
7108
 
 
7109
 
                if (node) {
7110
 
                    if (Y_DOM.inDoc(node)) {
7111
 
                        xy = [node.offsetLeft, node.offsetTop];
7112
 
                        doc = node.ownerDocument;
7113
 
                        parentNode = node;
7114
 
                        // TODO: refactor with !! or just falsey
7115
 
                        bCheck = ((Y.UA.gecko || Y.UA.webkit > 519) ? true : false);
7116
 
 
7117
 
                        // TODO: worth refactoring for TOP/LEFT only?
7118
 
                        while ((parentNode = parentNode.offsetParent)) {
7119
 
                            xy[0] += parentNode.offsetLeft;
7120
 
                            xy[1] += parentNode.offsetTop;
7121
 
                            if (bCheck) {
7122
 
                                xy = Y_DOM._calcBorders(parentNode, xy);
7123
 
                            }
7124
 
                        }
7125
 
 
7126
 
                        // account for any scrolled ancestors
7127
 
                        if (Y_DOM.getStyle(node, POSITION) != FIXED) {
7128
 
                            parentNode = node;
7129
 
 
7130
 
                            while ((parentNode = parentNode.parentNode)) {
7131
 
                                scrollTop = parentNode.scrollTop;
7132
 
                                scrollLeft = parentNode.scrollLeft;
7133
 
 
7134
 
                                //Firefox does something funky with borders when overflow is not visible.
7135
 
                                if (Y.UA.gecko && (Y_DOM.getStyle(parentNode, 'overflow') !== 'visible')) {
7136
 
                                        xy = Y_DOM._calcBorders(parentNode, xy);
7137
 
                                }
7138
 
                                
7139
 
 
7140
 
                                if (scrollTop || scrollLeft) {
7141
 
                                    xy[0] -= scrollLeft;
7142
 
                                    xy[1] -= scrollTop;
7143
 
                                }
7144
 
                            }
7145
 
                            xy[0] += Y_DOM.docScrollX(node, doc);
7146
 
                            xy[1] += Y_DOM.docScrollY(node, doc);
7147
 
 
7148
 
                        } else {
7149
 
                            //Fix FIXED position -- add scrollbars
7150
 
                            xy[0] += Y_DOM.docScrollX(node, doc);
7151
 
                            xy[1] += Y_DOM.docScrollY(node, doc);
7152
 
                        }
7153
 
                    } else {
7154
 
                        xy = Y_DOM._getOffset(node);
7155
 
                    }
7156
 
                }
7157
 
 
7158
 
                return xy;                
7159
 
            };
7160
 
        }
7161
 
    }(),// NOTE: Executing for loadtime branching
7162
 
 
7163
 
    /**
7164
 
     * Gets the current X position of an element based on page coordinates. 
7165
 
     * Element must be part of the DOM tree to have page coordinates
7166
 
     * (display:none or elements not appended return false).
7167
 
     * @method getX
7168
 
     * @param element The target element
7169
 
     * @return {Int} The X position of the element
7170
 
     */
7171
 
 
7172
 
    getX: function(node) {
7173
 
        return Y_DOM.getXY(node)[0];
7174
 
    },
7175
 
 
7176
 
    /**
7177
 
     * Gets the current Y position of an element based on page coordinates. 
7178
 
     * Element must be part of the DOM tree to have page coordinates
7179
 
     * (display:none or elements not appended return false).
7180
 
     * @method getY
7181
 
     * @param element The target element
7182
 
     * @return {Int} The Y position of the element
7183
 
     */
7184
 
 
7185
 
    getY: function(node) {
7186
 
        return Y_DOM.getXY(node)[1];
7187
 
    },
7188
 
 
7189
 
    /**
7190
 
     * Set the position of an html element in page coordinates.
7191
 
     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7192
 
     * @method setXY
7193
 
     * @param element The target element
7194
 
     * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
7195
 
     * @param {Boolean} noRetry By default we try and set the position a second time if the first fails
7196
 
     */
7197
 
    setXY: function(node, xy, noRetry) {
7198
 
        var setStyle = Y_DOM.setStyle,
7199
 
            pos,
7200
 
            delta,
7201
 
            newXY,
7202
 
            currentXY;
7203
 
 
7204
 
        if (node && xy) {
7205
 
            pos = Y_DOM.getStyle(node, POSITION);
7206
 
 
7207
 
            delta = Y_DOM._getOffset(node);       
7208
 
            if (pos == 'static') { // default to relative
7209
 
                pos = RELATIVE;
7210
 
                setStyle(node, POSITION, pos);
7211
 
            }
7212
 
            currentXY = Y_DOM.getXY(node);
7213
 
 
7214
 
            if (xy[0] !== null) {
7215
 
                setStyle(node, LEFT, xy[0] - currentXY[0] + delta[0] + 'px');
7216
 
            }
7217
 
 
7218
 
            if (xy[1] !== null) {
7219
 
                setStyle(node, TOP, xy[1] - currentXY[1] + delta[1] + 'px');
7220
 
            }
7221
 
 
7222
 
            if (!noRetry) {
7223
 
                newXY = Y_DOM.getXY(node);
7224
 
                if (newXY[0] !== xy[0] || newXY[1] !== xy[1]) {
7225
 
                    Y_DOM.setXY(node, xy, true); 
7226
 
                }
7227
 
            }
7228
 
          
7229
 
            Y.log('setXY setting position to ' + xy, 'info', 'dom-screen');
7230
 
        } else {
7231
 
            Y.log('setXY failed to set ' + node + ' to ' + xy, 'info', 'dom-screen');
7232
 
        }
7233
 
    },
7234
 
 
7235
 
    /**
7236
 
     * Set the X position of an html element in page coordinates, regardless of how the element is positioned.
7237
 
     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7238
 
     * @method setX
7239
 
     * @param element The target element
7240
 
     * @param {Int} x The X values for new position (coordinates are page-based)
7241
 
     */
7242
 
    setX: function(node, x) {
7243
 
        return Y_DOM.setXY(node, [x, null]);
7244
 
    },
7245
 
 
7246
 
    /**
7247
 
     * Set the Y position of an html element in page coordinates, regardless of how the element is positioned.
7248
 
     * The element(s) must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7249
 
     * @method setY
7250
 
     * @param element The target element
7251
 
     * @param {Int} y The Y values for new position (coordinates are page-based)
7252
 
     */
7253
 
    setY: function(node, y) {
7254
 
        return Y_DOM.setXY(node, [null, y]);
7255
 
    },
7256
 
 
7257
 
    /**
7258
 
     * @method swapXY
7259
 
     * @description Swap the xy position with another node
7260
 
     * @param {Node} node The node to swap with
7261
 
     * @param {Node} otherNode The other node to swap with
7262
 
     * @return {Node}
7263
 
     */
7264
 
    swapXY: function(node, otherNode) {
7265
 
        var xy = Y_DOM.getXY(node);
7266
 
        Y_DOM.setXY(node, Y_DOM.getXY(otherNode));
7267
 
        Y_DOM.setXY(otherNode, xy);
7268
 
    },
7269
 
 
7270
 
    _calcBorders: function(node, xy2) {
7271
 
        var t = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_TOP_WIDTH), 10) || 0,
7272
 
            l = parseInt(Y_DOM[GET_COMPUTED_STYLE](node, BORDER_LEFT_WIDTH), 10) || 0;
7273
 
        if (Y.UA.gecko) {
7274
 
            if (RE_TABLE.test(node.tagName)) {
7275
 
                t = 0;
7276
 
                l = 0;
7277
 
            }
7278
 
        }
7279
 
        xy2[0] += l;
7280
 
        xy2[1] += t;
7281
 
        return xy2;
7282
 
    },
7283
 
 
7284
 
    _getWinSize: function(node, doc) {
7285
 
        doc  = doc || (node) ? Y_DOM._getDoc(node) : Y.config.doc;
7286
 
        var win = doc.defaultView || doc.parentWindow,
7287
 
            mode = doc[COMPAT_MODE],
7288
 
            h = win.innerHeight,
7289
 
            w = win.innerWidth,
7290
 
            root = doc[DOCUMENT_ELEMENT];
7291
 
 
7292
 
        if ( mode && !Y.UA.opera ) { // IE, Gecko
7293
 
            if (mode != 'CSS1Compat') { // Quirks
7294
 
                root = doc.body; 
7295
 
            }
7296
 
            h = root.clientHeight;
7297
 
            w = root.clientWidth;
7298
 
        }
7299
 
        return { height: h, width: w };
7300
 
    },
7301
 
 
7302
 
    _getDocSize: function(node) {
7303
 
        var doc = (node) ? Y_DOM._getDoc(node) : Y.config.doc,
7304
 
            root = doc[DOCUMENT_ELEMENT];
7305
 
 
7306
 
        if (doc[COMPAT_MODE] != 'CSS1Compat') {
7307
 
            root = doc.body;
7308
 
        }
7309
 
 
7310
 
        return { height: root.scrollHeight, width: root.scrollWidth };
7311
 
    }
7312
 
});
7313
 
 
7314
 
})(Y);
7315
 
(function(Y) {
7316
 
var TOP = 'top',
7317
 
    RIGHT = 'right',
7318
 
    BOTTOM = 'bottom',
7319
 
    LEFT = 'left',
7320
 
 
7321
 
    getOffsets = function(r1, r2) {
7322
 
        var t = Math.max(r1[TOP], r2[TOP]),
7323
 
            r = Math.min(r1[RIGHT], r2[RIGHT]),
7324
 
            b = Math.min(r1[BOTTOM], r2[BOTTOM]),
7325
 
            l = Math.max(r1[LEFT], r2[LEFT]),
7326
 
            ret = {};
7327
 
        
7328
 
        ret[TOP] = t;
7329
 
        ret[RIGHT] = r;
7330
 
        ret[BOTTOM] = b;
7331
 
        ret[LEFT] = l;
7332
 
        return ret;
7333
 
    },
7334
 
 
7335
 
    DOM = Y.DOM;
7336
 
 
7337
 
Y.mix(DOM, {
7338
 
    /**
7339
 
     * Returns an Object literal containing the following about this element: (top, right, bottom, left)
7340
 
     * @for DOM
7341
 
     * @method region
7342
 
     * @param {HTMLElement} element The DOM element. 
7343
 
     * @return {Object} Object literal containing the following about this element: (top, right, bottom, left)
7344
 
     */
7345
 
    region: function(node) {
7346
 
        var xy = DOM.getXY(node),
7347
 
            ret = false;
7348
 
        
7349
 
        if (node && xy) {
7350
 
            ret = DOM._getRegion(
7351
 
                xy[1], // top
7352
 
                xy[0] + node.offsetWidth, // right
7353
 
                xy[1] + node.offsetHeight, // bottom
7354
 
                xy[0] // left
7355
 
            );
7356
 
        }
7357
 
 
7358
 
        return ret;
7359
 
    },
7360
 
 
7361
 
    /**
7362
 
     * Find the intersect information for the passes nodes.
7363
 
     * @method intersect
7364
 
     * @for DOM
7365
 
     * @param {HTMLElement} element The first element 
7366
 
     * @param {HTMLElement | Object} element2 The element or region to check the interect with
7367
 
     * @param {Object} altRegion An object literal containing the region for the first element if we already have the data (for performance i.e. DragDrop)
7368
 
     * @return {Object} Object literal containing the following intersection data: (top, right, bottom, left, area, yoff, xoff, inRegion)
7369
 
     */
7370
 
    intersect: function(node, node2, altRegion) {
7371
 
        var r = altRegion || DOM.region(node), region = {},
7372
 
            n = node2,
7373
 
            off;
7374
 
 
7375
 
        if (n.tagName) {
7376
 
            region = DOM.region(n);
7377
 
        } else if (Y.Lang.isObject(node2)) {
7378
 
            region = node2;
7379
 
        } else {
7380
 
            return false;
7381
 
        }
7382
 
        
7383
 
        off = getOffsets(region, r);
7384
 
        return {
7385
 
            top: off[TOP],
7386
 
            right: off[RIGHT],
7387
 
            bottom: off[BOTTOM],
7388
 
            left: off[LEFT],
7389
 
            area: ((off[BOTTOM] - off[TOP]) * (off[RIGHT] - off[LEFT])),
7390
 
            yoff: ((off[BOTTOM] - off[TOP])),
7391
 
            xoff: (off[RIGHT] - off[LEFT]),
7392
 
            inRegion: DOM.inRegion(node, node2, false, altRegion)
7393
 
        };
7394
 
        
7395
 
    },
7396
 
    /**
7397
 
     * Check if any part of this node is in the passed region
7398
 
     * @method inRegion
7399
 
     * @for DOM
7400
 
     * @param {Object} node2 The node to get the region from or an Object literal of the region
7401
 
     * $param {Boolean} all Should all of the node be inside the region
7402
 
     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
7403
 
     * @return {Boolean} True if in region, false if not.
7404
 
     */
7405
 
    inRegion: function(node, node2, all, altRegion) {
7406
 
        var region = {},
7407
 
            r = altRegion || DOM.region(node),
7408
 
            n = node2,
7409
 
            off;
7410
 
 
7411
 
        if (n.tagName) {
7412
 
            region = DOM.region(n);
7413
 
        } else if (Y.Lang.isObject(node2)) {
7414
 
            region = node2;
7415
 
        } else {
7416
 
            return false;
7417
 
        }
7418
 
            
7419
 
        if (all) {
7420
 
            return (
7421
 
                r[LEFT]   >= region[LEFT]   &&
7422
 
                r[RIGHT]  <= region[RIGHT]  && 
7423
 
                r[TOP]    >= region[TOP]    && 
7424
 
                r[BOTTOM] <= region[BOTTOM]  );
7425
 
        } else {
7426
 
            off = getOffsets(region, r);
7427
 
            if (off[BOTTOM] >= off[TOP] && off[RIGHT] >= off[LEFT]) {
7428
 
                return true;
7429
 
            } else {
7430
 
                return false;
7431
 
            }
7432
 
            
7433
 
        }
7434
 
    },
7435
 
 
7436
 
    /**
7437
 
     * Check if any part of this element is in the viewport
7438
 
     * @method inViewportRegion
7439
 
     * @for DOM
7440
 
     * @param {HTMLElement} element The DOM element. 
7441
 
     * @param {Boolean} all Should all of the node be inside the region
7442
 
     * @param {Object} altRegion An object literal containing the region for this node if we already have the data (for performance i.e. DragDrop)
7443
 
     * @return {Boolean} True if in region, false if not.
7444
 
     */
7445
 
    inViewportRegion: function(node, all, altRegion) {
7446
 
        return DOM.inRegion(node, DOM.viewportRegion(node), all, altRegion);
7447
 
            
7448
 
    },
7449
 
 
7450
 
    _getRegion: function(t, r, b, l) {
7451
 
        var region = {};
7452
 
 
7453
 
        region[TOP] = region[1] = t;
7454
 
        region[LEFT] = region[0] = l;
7455
 
        region[BOTTOM] = b;
7456
 
        region[RIGHT] = r;
7457
 
        region.width = region[RIGHT] - region[LEFT];
7458
 
        region.height = region[BOTTOM] - region[TOP];
7459
 
 
7460
 
        return region;
7461
 
    },
7462
 
 
7463
 
    /**
7464
 
     * Returns an Object literal containing the following about the visible region of viewport: (top, right, bottom, left)
7465
 
     * @method viewportRegion
7466
 
     * @for DOM
7467
 
     * @return {Object} Object literal containing the following about the visible region of the viewport: (top, right, bottom, left)
7468
 
     */
7469
 
    viewportRegion: function(node) {
7470
 
        node = node || Y.config.doc.documentElement;
7471
 
        var ret = false,
7472
 
            scrollX,
7473
 
            scrollY;
7474
 
 
7475
 
        if (node) {
7476
 
            scrollX = DOM.docScrollX(node);
7477
 
            scrollY = DOM.docScrollY(node);
7478
 
 
7479
 
            ret = DOM._getRegion(scrollY, // top
7480
 
                DOM.winWidth(node) + scrollX, // right
7481
 
                scrollY + DOM.winHeight(node), // bottom
7482
 
                scrollX); // left
7483
 
        }
7484
 
 
7485
 
        return ret;
7486
 
    }
7487
 
});
7488
 
})(Y);
7489
 
 
7490
 
 
7491
 
}, '3.4.1' ,{requires:['dom-base', 'dom-style']});
7492
 
YUI.add('selector-native', function(Y) {
7493
 
 
7494
 
(function(Y) {
7495
 
/**
7496
 
 * The selector-native module provides support for native querySelector
7497
 
 * @module dom
7498
 
 * @submodule selector-native
7499
 
 * @for Selector
7500
 
 */
7501
 
 
7502
 
/**
7503
 
 * Provides support for using CSS selectors to query the DOM 
7504
 
 * @class Selector 
7505
 
 * @static
7506
 
 * @for Selector
7507
 
 */
7508
 
 
7509
 
Y.namespace('Selector'); // allow native module to standalone
7510
 
 
7511
 
var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
7512
 
    OWNER_DOCUMENT = 'ownerDocument';
7513
 
 
7514
 
var Selector = {
7515
 
    _foundCache: [],
7516
 
 
7517
 
    useNative: true,
7518
 
 
7519
 
    _compare: ('sourceIndex' in Y.config.doc.documentElement) ?
7520
 
        function(nodeA, nodeB) {
7521
 
            var a = nodeA.sourceIndex,
7522
 
                b = nodeB.sourceIndex;
7523
 
 
7524
 
            if (a === b) {
7525
 
                return 0;
7526
 
            } else if (a > b) {
7527
 
                return 1;
7528
 
            }
7529
 
 
7530
 
            return -1;
7531
 
 
7532
 
        } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ?
7533
 
        function(nodeA, nodeB) {
7534
 
            if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
7535
 
                return -1;
7536
 
            } else {
7537
 
                return 1;
7538
 
            }
7539
 
        } :
7540
 
        function(nodeA, nodeB) {
7541
 
            var rangeA, rangeB, compare;
7542
 
            if (nodeA && nodeB) {
7543
 
                rangeA = nodeA[OWNER_DOCUMENT].createRange();
7544
 
                rangeA.setStart(nodeA, 0);
7545
 
                rangeB = nodeB[OWNER_DOCUMENT].createRange();
7546
 
                rangeB.setStart(nodeB, 0);
7547
 
                compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END
7548
 
            }
7549
 
 
7550
 
            return compare;
7551
 
        
7552
 
    }),
7553
 
 
7554
 
    _sort: function(nodes) {
7555
 
        if (nodes) {
7556
 
            nodes = Y.Array(nodes, 0, true);
7557
 
            if (nodes.sort) {
7558
 
                nodes.sort(Selector._compare);
7559
 
            }
7560
 
        }
7561
 
 
7562
 
        return nodes;
7563
 
    },
7564
 
 
7565
 
    _deDupe: function(nodes) {
7566
 
        var ret = [],
7567
 
            i, node;
7568
 
 
7569
 
        for (i = 0; (node = nodes[i++]);) {
7570
 
            if (!node._found) {
7571
 
                ret[ret.length] = node;
7572
 
                node._found = true;
7573
 
            }
7574
 
        }
7575
 
 
7576
 
        for (i = 0; (node = ret[i++]);) {
7577
 
            node._found = null;
7578
 
            node.removeAttribute('_found');
7579
 
        }
7580
 
 
7581
 
        return ret;
7582
 
    },
7583
 
 
7584
 
    /**
7585
 
     * Retrieves a set of nodes based on a given CSS selector. 
7586
 
     * @method query
7587
 
     *
7588
 
     * @param {string} selector The CSS Selector to test the node against.
7589
 
     * @param {HTMLElement} root optional An HTMLElement to start the query from. Defaults to Y.config.doc
7590
 
     * @param {Boolean} firstOnly optional Whether or not to return only the first match.
7591
 
     * @return {Array} An array of nodes that match the given selector.
7592
 
     * @static
7593
 
     */
7594
 
    query: function(selector, root, firstOnly, skipNative) {
7595
 
        root = root || Y.config.doc;
7596
 
        var ret = [],
7597
 
            useNative = (Y.Selector.useNative && Y.config.doc.querySelector && !skipNative),
7598
 
            queries = [[selector, root]],
7599
 
            query,
7600
 
            result,
7601
 
            i,
7602
 
            fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery;
7603
 
 
7604
 
        if (selector && fn) {
7605
 
            // split group into seperate queries
7606
 
            if (!skipNative && // already done if skipping
7607
 
                    (!useNative || root.tagName)) { // split native when element scoping is needed
7608
 
                queries = Selector._splitQueries(selector, root);
7609
 
            }
7610
 
 
7611
 
            for (i = 0; (query = queries[i++]);) {
7612
 
                result = fn(query[0], query[1], firstOnly);
7613
 
                if (!firstOnly) { // coerce DOM Collection to Array
7614
 
                    result = Y.Array(result, 0, true);
7615
 
                }
7616
 
                if (result) {
7617
 
                    ret = ret.concat(result);
7618
 
                }
7619
 
            }
7620
 
 
7621
 
            if (queries.length > 1) { // remove dupes and sort by doc order 
7622
 
                ret = Selector._sort(Selector._deDupe(ret));
7623
 
            }
7624
 
        }
7625
 
 
7626
 
        Y.log('query: ' + selector + ' returning: ' + ret.length, 'info', 'Selector');
7627
 
        return (firstOnly) ? (ret[0] || null) : ret;
7628
 
 
7629
 
    },
7630
 
 
7631
 
    // allows element scoped queries to begin with combinator
7632
 
    // e.g. query('> p', document.body) === query('body > p')
7633
 
    _splitQueries: function(selector, node) {
7634
 
        var groups = selector.split(','),
7635
 
            queries = [],
7636
 
            prefix = '',
7637
 
            i, len;
7638
 
 
7639
 
        if (node) {
7640
 
            // enforce for element scoping
7641
 
            if (node.tagName) {
7642
 
                node.id = node.id || Y.guid();
7643
 
                prefix = '[id="' + node.id + '"] ';
7644
 
            }
7645
 
 
7646
 
            for (i = 0, len = groups.length; i < len; ++i) {
7647
 
                selector =  prefix + groups[i];
7648
 
                queries.push([selector, node]);
7649
 
            }
7650
 
        }
7651
 
 
7652
 
        return queries;
7653
 
    },
7654
 
 
7655
 
    _nativeQuery: function(selector, root, one) {
7656
 
        if (Y.UA.webkit && selector.indexOf(':checked') > -1 &&
7657
 
                (Y.Selector.pseudos && Y.Selector.pseudos.checked)) { // webkit (chrome, safari) fails to pick up "selected"  with "checked"
7658
 
            return Y.Selector.query(selector, root, one, true); // redo with skipNative true to try brute query
7659
 
        }
7660
 
        try {
7661
 
            //Y.log('trying native query with: ' + selector, 'info', 'selector-native');
7662
 
            return root['querySelector' + (one ? '' : 'All')](selector);
7663
 
        } catch(e) { // fallback to brute if available
7664
 
            //Y.log('native query error; reverting to brute query with: ' + selector, 'info', 'selector-native');
7665
 
            return Y.Selector.query(selector, root, one, true); // redo with skipNative true
7666
 
        }
7667
 
    },
7668
 
 
7669
 
    filter: function(nodes, selector) {
7670
 
        var ret = [],
7671
 
            i, node;
7672
 
 
7673
 
        if (nodes && selector) {
7674
 
            for (i = 0; (node = nodes[i++]);) {
7675
 
                if (Y.Selector.test(node, selector)) {
7676
 
                    ret[ret.length] = node;
7677
 
                }
7678
 
            }
7679
 
        } else {
7680
 
            Y.log('invalid filter input (nodes: ' + nodes +
7681
 
                    ', selector: ' + selector + ')', 'warn', 'Selector');
7682
 
        }
7683
 
 
7684
 
        return ret;
7685
 
    },
7686
 
 
7687
 
    test: function(node, selector, root) {
7688
 
        var ret = false,
7689
 
            useFrag = false,
7690
 
            groups,
7691
 
            parent,
7692
 
            item,
7693
 
            items,
7694
 
            frag,
7695
 
            i, j, group;
7696
 
 
7697
 
        if (node && node.tagName) { // only test HTMLElements
7698
 
 
7699
 
            if (typeof selector == 'function') { // test with function
7700
 
                ret = selector.call(node, node);
7701
 
            } else { // test with query
7702
 
                // we need a root if off-doc
7703
 
                groups = selector.split(',');
7704
 
                if (!root && !Y.DOM.inDoc(node)) {
7705
 
                    parent = node.parentNode;
7706
 
                    if (parent) { 
7707
 
                        root = parent;
7708
 
                    } else { // only use frag when no parent to query
7709
 
                        frag = node[OWNER_DOCUMENT].createDocumentFragment();
7710
 
                        frag.appendChild(node);
7711
 
                        root = frag;
7712
 
                        useFrag = true;
7713
 
                    }
7714
 
                }
7715
 
                root = root || node[OWNER_DOCUMENT];
7716
 
 
7717
 
                if (!node.id) {
7718
 
                    node.id = Y.guid();
7719
 
                }
7720
 
                for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
7721
 
                    group += '[id="' + node.id + '"]';
7722
 
                    items = Y.Selector.query(group, root);
7723
 
 
7724
 
                    for (j = 0; item = items[j++];) {
7725
 
                        if (item === node) {
7726
 
                            ret = true;
7727
 
                            break;
7728
 
                        }
7729
 
                    }
7730
 
                    if (ret) {
7731
 
                        break;
7732
 
                    }
7733
 
                }
7734
 
 
7735
 
                if (useFrag) { // cleanup
7736
 
                    frag.removeChild(node);
7737
 
                }
7738
 
            };
7739
 
        }
7740
 
 
7741
 
        return ret;
7742
 
    },
7743
 
 
7744
 
    /**
7745
 
     * A convenience function to emulate Y.Node's aNode.ancestor(selector).
7746
 
     * @param {HTMLElement} element An HTMLElement to start the query from.
7747
 
     * @param {String} selector The CSS selector to test the node against.
7748
 
     * @return {HTMLElement} The ancestor node matching the selector, or null.
7749
 
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan 
7750
 
     * @static
7751
 
     * @method ancestor
7752
 
     */
7753
 
    ancestor: function (element, selector, testSelf) {
7754
 
        return Y.DOM.ancestor(element, function(n) {
7755
 
            return Y.Selector.test(n, selector);
7756
 
        }, testSelf);
7757
 
    }
7758
 
};
7759
 
 
7760
 
Y.mix(Y.Selector, Selector, true);
7761
 
 
7762
 
})(Y);
7763
 
 
7764
 
 
7765
 
}, '3.4.1' ,{requires:['dom-base']});
7766
 
YUI.add('selector', function(Y) {
7767
 
 
7768
 
 
7769
 
 
7770
 
 
7771
 
}, '3.4.1' ,{requires:['selector-native']});
7772
 
YUI.add('event-custom-base', function(Y) {
7773
 
 
7774
 
/**
7775
 
 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
7776
 
 * events.
7777
 
 * @module event-custom
7778
 
 */
7779
 
 
7780
 
Y.Env.evt = {
7781
 
    handles: {},
7782
 
    plugins: {}
7783
 
};
7784
 
 
7785
 
 
7786
 
/**
7787
 
 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
7788
 
 * events.
7789
 
 * @module event-custom
7790
 
 * @submodule event-custom-base
7791
 
 */
7792
 
 
7793
 
/**
7794
 
 * Allows for the insertion of methods that are executed before or after
7795
 
 * a specified method
7796
 
 * @class Do
7797
 
 * @static
7798
 
 */
7799
 
 
7800
 
var DO_BEFORE = 0,
7801
 
    DO_AFTER = 1,
7802
 
 
7803
 
DO = {
7804
 
 
7805
 
    /**
7806
 
     * Cache of objects touched by the utility
7807
 
     * @property objs
7808
 
     * @static
7809
 
     */
7810
 
    objs: {},
7811
 
 
7812
 
    /**
7813
 
     * <p>Execute the supplied method before the specified function.  Wrapping
7814
 
     * function may optionally return an instance of the following classes to
7815
 
     * further alter runtime behavior:</p>
7816
 
     * <dl>
7817
 
     *     <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
7818
 
     *         <dd>Immediatly stop execution and return
7819
 
     *         <code>returnValue</code>.  No other wrapping functions will be
7820
 
     *         executed.</dd>
7821
 
     *     <dt></code>Y.Do.AlterArgs(message, newArgArray)</code></dt>
7822
 
     *         <dd>Replace the arguments that the original function will be
7823
 
     *         called with.</dd>
7824
 
     *     <dt></code>Y.Do.Prevent(message)</code></dt>
7825
 
     *         <dd>Don't execute the wrapped function.  Other before phase
7826
 
     *         wrappers will be executed.</dd>
7827
 
     * </dl>
7828
 
     *
7829
 
     * @method before
7830
 
     * @param fn {Function} the function to execute
7831
 
     * @param obj the object hosting the method to displace
7832
 
     * @param sFn {string} the name of the method to displace
7833
 
     * @param c The execution context for fn
7834
 
     * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
7835
 
     * when the event fires.
7836
 
     * @return {string} handle for the subscription
7837
 
     * @static
7838
 
     */
7839
 
    before: function(fn, obj, sFn, c) {
7840
 
        // Y.log('Do before: ' + sFn, 'info', 'event');
7841
 
        var f = fn, a;
7842
 
        if (c) {
7843
 
            a = [fn, c].concat(Y.Array(arguments, 4, true));
7844
 
            f = Y.rbind.apply(Y, a);
7845
 
        }
7846
 
 
7847
 
        return this._inject(DO_BEFORE, f, obj, sFn);
7848
 
    },
7849
 
 
7850
 
    /**
7851
 
     * <p>Execute the supplied method after the specified function.  Wrapping
7852
 
     * function may optionally return an instance of the following classes to
7853
 
     * further alter runtime behavior:</p>
7854
 
     * <dl>
7855
 
     *     <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
7856
 
     *         <dd>Immediatly stop execution and return
7857
 
     *         <code>returnValue</code>.  No other wrapping functions will be
7858
 
     *         executed.</dd>
7859
 
     *     <dt></code>Y.Do.AlterReturn(message, returnValue)</code></dt>
7860
 
     *         <dd>Return <code>returnValue</code> instead of the wrapped
7861
 
     *         method's original return value.  This can be further altered by
7862
 
     *         other after phase wrappers.</dd>
7863
 
     * </dl>
7864
 
     *
7865
 
     * <p>The static properties <code>Y.Do.originalRetVal</code> and
7866
 
     * <code>Y.Do.currentRetVal</code> will be populated for reference.</p>
7867
 
     *
7868
 
     * @method after
7869
 
     * @param fn {Function} the function to execute
7870
 
     * @param obj the object hosting the method to displace
7871
 
     * @param sFn {string} the name of the method to displace
7872
 
     * @param c The execution context for fn
7873
 
     * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
7874
 
     * @return {string} handle for the subscription
7875
 
     * @static
7876
 
     */
7877
 
    after: function(fn, obj, sFn, c) {
7878
 
        var f = fn, a;
7879
 
        if (c) {
7880
 
            a = [fn, c].concat(Y.Array(arguments, 4, true));
7881
 
            f = Y.rbind.apply(Y, a);
7882
 
        }
7883
 
 
7884
 
        return this._inject(DO_AFTER, f, obj, sFn);
7885
 
    },
7886
 
 
7887
 
    /**
7888
 
     * Execute the supplied method before or after the specified function.
7889
 
     * Used by <code>before</code> and <code>after</code>.
7890
 
     *
7891
 
     * @method _inject
7892
 
     * @param when {string} before or after
7893
 
     * @param fn {Function} the function to execute
7894
 
     * @param obj the object hosting the method to displace
7895
 
     * @param sFn {string} the name of the method to displace
7896
 
     * @param c The execution context for fn
7897
 
     * @return {string} handle for the subscription
7898
 
     * @private
7899
 
     * @static
7900
 
     */
7901
 
    _inject: function(when, fn, obj, sFn) {
7902
 
 
7903
 
        // object id
7904
 
        var id = Y.stamp(obj), o, sid;
7905
 
 
7906
 
        if (! this.objs[id]) {
7907
 
            // create a map entry for the obj if it doesn't exist
7908
 
            this.objs[id] = {};
7909
 
        }
7910
 
 
7911
 
        o = this.objs[id];
7912
 
 
7913
 
        if (! o[sFn]) {
7914
 
            // create a map entry for the method if it doesn't exist
7915
 
            o[sFn] = new Y.Do.Method(obj, sFn);
7916
 
 
7917
 
            // re-route the method to our wrapper
7918
 
            obj[sFn] =
7919
 
                function() {
7920
 
                    return o[sFn].exec.apply(o[sFn], arguments);
7921
 
                };
7922
 
        }
7923
 
 
7924
 
        // subscriber id
7925
 
        sid = id + Y.stamp(fn) + sFn;
7926
 
 
7927
 
        // register the callback
7928
 
        o[sFn].register(sid, fn, when);
7929
 
 
7930
 
        return new Y.EventHandle(o[sFn], sid);
7931
 
 
7932
 
    },
7933
 
 
7934
 
    /**
7935
 
     * Detach a before or after subscription.
7936
 
     *
7937
 
     * @method detach
7938
 
     * @param handle {string} the subscription handle
7939
 
     * @static
7940
 
     */
7941
 
    detach: function(handle) {
7942
 
 
7943
 
        if (handle.detach) {
7944
 
            handle.detach();
7945
 
        }
7946
 
 
7947
 
    },
7948
 
 
7949
 
    _unload: function(e, me) {
7950
 
 
7951
 
    }
7952
 
};
7953
 
 
7954
 
Y.Do = DO;
7955
 
 
7956
 
//////////////////////////////////////////////////////////////////////////
7957
 
 
7958
 
/**
7959
 
 * Contains the return value from the wrapped method, accessible
7960
 
 * by 'after' event listeners.
7961
 
 *
7962
 
 * @property Do.originalRetVal
7963
 
 * @static
7964
 
 * @since 3.2.0
7965
 
 */
7966
 
 
7967
 
/**
7968
 
 * Contains the current state of the return value, consumable by
7969
 
 * 'after' event listeners, and updated if an after subscriber
7970
 
 * changes the return value generated by the wrapped function.
7971
 
 *
7972
 
 * @property Do.currentRetVal
7973
 
 * @static
7974
 
 * @since 3.2.0
7975
 
 */
7976
 
 
7977
 
//////////////////////////////////////////////////////////////////////////
7978
 
 
7979
 
/**
7980
 
 * Wrapper for a displaced method with aop enabled
7981
 
 * @class Do.Method
7982
 
 * @constructor
7983
 
 * @param obj The object to operate on
7984
 
 * @param sFn The name of the method to displace
7985
 
 */
7986
 
DO.Method = function(obj, sFn) {
7987
 
    this.obj = obj;
7988
 
    this.methodName = sFn;
7989
 
    this.method = obj[sFn];
7990
 
    this.before = {};
7991
 
    this.after = {};
7992
 
};
7993
 
 
7994
 
/**
7995
 
 * Register a aop subscriber
7996
 
 * @method register
7997
 
 * @param sid {string} the subscriber id
7998
 
 * @param fn {Function} the function to execute
7999
 
 * @param when {string} when to execute the function
8000
 
 */
8001
 
DO.Method.prototype.register = function (sid, fn, when) {
8002
 
    if (when) {
8003
 
        this.after[sid] = fn;
8004
 
    } else {
8005
 
        this.before[sid] = fn;
8006
 
    }
8007
 
};
8008
 
 
8009
 
/**
8010
 
 * Unregister a aop subscriber
8011
 
 * @method delete
8012
 
 * @param sid {string} the subscriber id
8013
 
 * @param fn {Function} the function to execute
8014
 
 * @param when {string} when to execute the function
8015
 
 */
8016
 
DO.Method.prototype._delete = function (sid) {
8017
 
    // Y.log('Y.Do._delete: ' + sid, 'info', 'Event');
8018
 
    delete this.before[sid];
8019
 
    delete this.after[sid];
8020
 
};
8021
 
 
8022
 
/**
8023
 
 * <p>Execute the wrapped method.  All arguments are passed into the wrapping
8024
 
 * functions.  If any of the before wrappers return an instance of
8025
 
 * <code>Y.Do.Halt</code> or <code>Y.Do.Prevent</code>, neither the wrapped
8026
 
 * function nor any after phase subscribers will be executed.</p>
8027
 
 *
8028
 
 * <p>The return value will be the return value of the wrapped function or one
8029
 
 * provided by a wrapper function via an instance of <code>Y.Do.Halt</code> or
8030
 
 * <code>Y.Do.AlterReturn</code>.
8031
 
 *
8032
 
 * @method exec
8033
 
 * @param arg* {any} Arguments are passed to the wrapping and wrapped functions
8034
 
 * @return {any} Return value of wrapped function unless overwritten (see above)
8035
 
 */
8036
 
DO.Method.prototype.exec = function () {
8037
 
 
8038
 
    var args = Y.Array(arguments, 0, true),
8039
 
        i, ret, newRet,
8040
 
        bf = this.before,
8041
 
        af = this.after,
8042
 
        prevented = false;
8043
 
 
8044
 
    // execute before
8045
 
    for (i in bf) {
8046
 
        if (bf.hasOwnProperty(i)) {
8047
 
            ret = bf[i].apply(this.obj, args);
8048
 
            if (ret) {
8049
 
                switch (ret.constructor) {
8050
 
                    case DO.Halt:
8051
 
                        return ret.retVal;
8052
 
                    case DO.AlterArgs:
8053
 
                        args = ret.newArgs;
8054
 
                        break;
8055
 
                    case DO.Prevent:
8056
 
                        prevented = true;
8057
 
                        break;
8058
 
                    default:
8059
 
                }
8060
 
            }
8061
 
        }
8062
 
    }
8063
 
 
8064
 
    // execute method
8065
 
    if (!prevented) {
8066
 
        ret = this.method.apply(this.obj, args);
8067
 
    }
8068
 
 
8069
 
    DO.originalRetVal = ret;
8070
 
    DO.currentRetVal = ret;
8071
 
 
8072
 
    // execute after methods.
8073
 
    for (i in af) {
8074
 
        if (af.hasOwnProperty(i)) {
8075
 
            newRet = af[i].apply(this.obj, args);
8076
 
            // Stop processing if a Halt object is returned
8077
 
            if (newRet && newRet.constructor == DO.Halt) {
8078
 
                return newRet.retVal;
8079
 
            // Check for a new return value
8080
 
            } else if (newRet && newRet.constructor == DO.AlterReturn) {
8081
 
                ret = newRet.newRetVal;
8082
 
                // Update the static retval state
8083
 
                DO.currentRetVal = ret;
8084
 
            }
8085
 
        }
8086
 
    }
8087
 
 
8088
 
    return ret;
8089
 
};
8090
 
 
8091
 
//////////////////////////////////////////////////////////////////////////
8092
 
 
8093
 
/**
8094
 
 * Return an AlterArgs object when you want to change the arguments that
8095
 
 * were passed into the function.  Useful for Do.before subscribers.  An
8096
 
 * example would be a service that scrubs out illegal characters prior to
8097
 
 * executing the core business logic.
8098
 
 * @class Do.AlterArgs
8099
 
 * @constructor
8100
 
 * @param msg {String} (optional) Explanation of the altered return value
8101
 
 * @param newArgs {Array} Call parameters to be used for the original method
8102
 
 *                        instead of the arguments originally passed in.
8103
 
 */
8104
 
DO.AlterArgs = function(msg, newArgs) {
8105
 
    this.msg = msg;
8106
 
    this.newArgs = newArgs;
8107
 
};
8108
 
 
8109
 
/**
8110
 
 * Return an AlterReturn object when you want to change the result returned
8111
 
 * from the core method to the caller.  Useful for Do.after subscribers.
8112
 
 * @class Do.AlterReturn
8113
 
 * @constructor
8114
 
 * @param msg {String} (optional) Explanation of the altered return value
8115
 
 * @param newRetVal {any} Return value passed to code that invoked the wrapped
8116
 
 *                      function.
8117
 
 */
8118
 
DO.AlterReturn = function(msg, newRetVal) {
8119
 
    this.msg = msg;
8120
 
    this.newRetVal = newRetVal;
8121
 
};
8122
 
 
8123
 
/**
8124
 
 * Return a Halt object when you want to terminate the execution
8125
 
 * of all subsequent subscribers as well as the wrapped method
8126
 
 * if it has not exectued yet.  Useful for Do.before subscribers.
8127
 
 * @class Do.Halt
8128
 
 * @constructor
8129
 
 * @param msg {String} (optional) Explanation of why the termination was done
8130
 
 * @param retVal {any} Return value passed to code that invoked the wrapped
8131
 
 *                      function.
8132
 
 */
8133
 
DO.Halt = function(msg, retVal) {
8134
 
    this.msg = msg;
8135
 
    this.retVal = retVal;
8136
 
};
8137
 
 
8138
 
/**
8139
 
 * Return a Prevent object when you want to prevent the wrapped function
8140
 
 * from executing, but want the remaining listeners to execute.  Useful
8141
 
 * for Do.before subscribers.
8142
 
 * @class Do.Prevent
8143
 
 * @constructor
8144
 
 * @param msg {String} (optional) Explanation of why the termination was done
8145
 
 */
8146
 
DO.Prevent = function(msg) {
8147
 
    this.msg = msg;
8148
 
};
8149
 
 
8150
 
/**
8151
 
 * Return an Error object when you want to terminate the execution
8152
 
 * of all subsequent method calls.
8153
 
 * @class Do.Error
8154
 
 * @constructor
8155
 
 * @param msg {String} (optional) Explanation of the altered return value
8156
 
 * @param retVal {any} Return value passed to code that invoked the wrapped
8157
 
 *                      function.
8158
 
 * @deprecated use Y.Do.Halt or Y.Do.Prevent
8159
 
 */
8160
 
DO.Error = DO.Halt;
8161
 
 
8162
 
 
8163
 
//////////////////////////////////////////////////////////////////////////
8164
 
 
8165
 
// Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
8166
 
 
8167
 
 
8168
 
/**
8169
 
 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
8170
 
 * events.
8171
 
 * @module event-custom
8172
 
 * @submodule event-custom-base
8173
 
 */
8174
 
 
8175
 
 
8176
 
// var onsubscribeType = "_event:onsub",
8177
 
var AFTER = 'after',
8178
 
    CONFIGS = [
8179
 
        'broadcast',
8180
 
        'monitored',
8181
 
        'bubbles',
8182
 
        'context',
8183
 
        'contextFn',
8184
 
        'currentTarget',
8185
 
        'defaultFn',
8186
 
        'defaultTargetOnly',
8187
 
        'details',
8188
 
        'emitFacade',
8189
 
        'fireOnce',
8190
 
        'async',
8191
 
        'host',
8192
 
        'preventable',
8193
 
        'preventedFn',
8194
 
        'queuable',
8195
 
        'silent',
8196
 
        'stoppedFn',
8197
 
        'target',
8198
 
        'type'
8199
 
    ],
8200
 
 
8201
 
    YUI3_SIGNATURE = 9,
8202
 
    YUI_LOG = 'yui:log';
8203
 
 
8204
 
/**
8205
 
 * The CustomEvent class lets you define events for your application
8206
 
 * that can be subscribed to by one or more independent component.
8207
 
 *
8208
 
 * @param {String} type The type of event, which is passed to the callback
8209
 
 * when the event fires.
8210
 
 * @param {object} o configuration object.
8211
 
 * @class CustomEvent
8212
 
 * @constructor
8213
 
 */
8214
 
Y.CustomEvent = function(type, o) {
8215
 
 
8216
 
    // if (arguments.length > 2) {
8217
 
// this.log('CustomEvent context and silent are now in the config', 'warn', 'Event');
8218
 
    // }
8219
 
 
8220
 
    o = o || {};
8221
 
 
8222
 
    this.id = Y.stamp(this);
8223
 
 
8224
 
    /**
8225
 
     * The type of event, returned to subscribers when the event fires
8226
 
     * @property type
8227
 
     * @type string
8228
 
     */
8229
 
    this.type = type;
8230
 
 
8231
 
    /**
8232
 
     * The context the the event will fire from by default.  Defaults to the YUI
8233
 
     * instance.
8234
 
     * @property context
8235
 
     * @type object
8236
 
     */
8237
 
    this.context = Y;
8238
 
 
8239
 
    /**
8240
 
     * Monitor when an event is attached or detached.
8241
 
     *
8242
 
     * @property monitored
8243
 
     * @type boolean
8244
 
     */
8245
 
    // this.monitored = false;
8246
 
 
8247
 
    this.logSystem = (type == YUI_LOG);
8248
 
 
8249
 
    /**
8250
 
     * If 0, this event does not broadcast.  If 1, the YUI instance is notified
8251
 
     * every time this event fires.  If 2, the YUI instance and the YUI global
8252
 
     * (if event is enabled on the global) are notified every time this event
8253
 
     * fires.
8254
 
     * @property broadcast
8255
 
     * @type int
8256
 
     */
8257
 
    // this.broadcast = 0;
8258
 
 
8259
 
    /**
8260
 
     * By default all custom events are logged in the debug build, set silent
8261
 
     * to true to disable debug outpu for this event.
8262
 
     * @property silent
8263
 
     * @type boolean
8264
 
     */
8265
 
    this.silent = this.logSystem;
8266
 
 
8267
 
    /**
8268
 
     * Specifies whether this event should be queued when the host is actively
8269
 
     * processing an event.  This will effect exectution order of the callbacks
8270
 
     * for the various events.
8271
 
     * @property queuable
8272
 
     * @type boolean
8273
 
     * @default false
8274
 
     */
8275
 
    // this.queuable = false;
8276
 
 
8277
 
    /**
8278
 
     * The subscribers to this event
8279
 
     * @property subscribers
8280
 
     * @type Subscriber {}
8281
 
     */
8282
 
    this.subscribers = {};
8283
 
 
8284
 
    /**
8285
 
     * 'After' subscribers
8286
 
     * @property afters
8287
 
     * @type Subscriber {}
8288
 
     */
8289
 
    this.afters = {};
8290
 
 
8291
 
    /**
8292
 
     * This event has fired if true
8293
 
     *
8294
 
     * @property fired
8295
 
     * @type boolean
8296
 
     * @default false;
8297
 
     */
8298
 
    // this.fired = false;
8299
 
 
8300
 
    /**
8301
 
     * An array containing the arguments the custom event
8302
 
     * was last fired with.
8303
 
     * @property firedWith
8304
 
     * @type Array
8305
 
     */
8306
 
    // this.firedWith;
8307
 
 
8308
 
    /**
8309
 
     * This event should only fire one time if true, and if
8310
 
     * it has fired, any new subscribers should be notified
8311
 
     * immediately.
8312
 
     *
8313
 
     * @property fireOnce
8314
 
     * @type boolean
8315
 
     * @default false;
8316
 
     */
8317
 
    // this.fireOnce = false;
8318
 
 
8319
 
    /**
8320
 
     * fireOnce listeners will fire syncronously unless async
8321
 
     * is set to true
8322
 
     * @property async
8323
 
     * @type boolean
8324
 
     * @default false
8325
 
     */
8326
 
    //this.async = false;
8327
 
 
8328
 
    /**
8329
 
     * Flag for stopPropagation that is modified during fire()
8330
 
     * 1 means to stop propagation to bubble targets.  2 means
8331
 
     * to also stop additional subscribers on this target.
8332
 
     * @property stopped
8333
 
     * @type int
8334
 
     */
8335
 
    // this.stopped = 0;
8336
 
 
8337
 
    /**
8338
 
     * Flag for preventDefault that is modified during fire().
8339
 
     * if it is not 0, the default behavior for this event
8340
 
     * @property prevented
8341
 
     * @type int
8342
 
     */
8343
 
    // this.prevented = 0;
8344
 
 
8345
 
    /**
8346
 
     * Specifies the host for this custom event.  This is used
8347
 
     * to enable event bubbling
8348
 
     * @property host
8349
 
     * @type EventTarget
8350
 
     */
8351
 
    // this.host = null;
8352
 
 
8353
 
    /**
8354
 
     * The default function to execute after event listeners
8355
 
     * have fire, but only if the default action was not
8356
 
     * prevented.
8357
 
     * @property defaultFn
8358
 
     * @type Function
8359
 
     */
8360
 
    // this.defaultFn = null;
8361
 
 
8362
 
    /**
8363
 
     * The function to execute if a subscriber calls
8364
 
     * stopPropagation or stopImmediatePropagation
8365
 
     * @property stoppedFn
8366
 
     * @type Function
8367
 
     */
8368
 
    // this.stoppedFn = null;
8369
 
 
8370
 
    /**
8371
 
     * The function to execute if a subscriber calls
8372
 
     * preventDefault
8373
 
     * @property preventedFn
8374
 
     * @type Function
8375
 
     */
8376
 
    // this.preventedFn = null;
8377
 
 
8378
 
    /**
8379
 
     * Specifies whether or not this event's default function
8380
 
     * can be cancelled by a subscriber by executing preventDefault()
8381
 
     * on the event facade
8382
 
     * @property preventable
8383
 
     * @type boolean
8384
 
     * @default true
8385
 
     */
8386
 
    this.preventable = true;
8387
 
 
8388
 
    /**
8389
 
     * Specifies whether or not a subscriber can stop the event propagation
8390
 
     * via stopPropagation(), stopImmediatePropagation(), or halt()
8391
 
     *
8392
 
     * Events can only bubble if emitFacade is true.
8393
 
     *
8394
 
     * @property bubbles
8395
 
     * @type boolean
8396
 
     * @default true
8397
 
     */
8398
 
    this.bubbles = true;
8399
 
 
8400
 
    /**
8401
 
     * Supports multiple options for listener signatures in order to
8402
 
     * port YUI 2 apps.
8403
 
     * @property signature
8404
 
     * @type int
8405
 
     * @default 9
8406
 
     */
8407
 
    this.signature = YUI3_SIGNATURE;
8408
 
 
8409
 
    this.subCount = 0;
8410
 
    this.afterCount = 0;
8411
 
 
8412
 
    // this.hasSubscribers = false;
8413
 
 
8414
 
    // this.hasAfters = false;
8415
 
 
8416
 
    /**
8417
 
     * If set to true, the custom event will deliver an EventFacade object
8418
 
     * that is similar to a DOM event object.
8419
 
     * @property emitFacade
8420
 
     * @type boolean
8421
 
     * @default false
8422
 
     */
8423
 
    // this.emitFacade = false;
8424
 
 
8425
 
    this.applyConfig(o, true);
8426
 
 
8427
 
    // this.log("Creating " + this.type);
8428
 
 
8429
 
};
8430
 
 
8431
 
Y.CustomEvent.prototype = {
8432
 
    constructor: Y.CustomEvent,
8433
 
 
8434
 
    /**
8435
 
     * Returns the number of subscribers for this event as the sum of the on()
8436
 
     * subscribers and after() subscribers.
8437
 
     *
8438
 
     * @method hasSubs
8439
 
     * @return Number
8440
 
     */
8441
 
    hasSubs: function(when) {
8442
 
        var s = this.subCount, a = this.afterCount, sib = this.sibling;
8443
 
 
8444
 
        if (sib) {
8445
 
            s += sib.subCount;
8446
 
            a += sib.afterCount;
8447
 
        }
8448
 
 
8449
 
        if (when) {
8450
 
            return (when == 'after') ? a : s;
8451
 
        }
8452
 
 
8453
 
        return (s + a);
8454
 
    },
8455
 
 
8456
 
    /**
8457
 
     * Monitor the event state for the subscribed event.  The first parameter
8458
 
     * is what should be monitored, the rest are the normal parameters when
8459
 
     * subscribing to an event.
8460
 
     * @method monitor
8461
 
     * @param what {string} what to monitor ('detach', 'attach', 'publish').
8462
 
     * @return {EventHandle} return value from the monitor event subscription.
8463
 
     */
8464
 
    monitor: function(what) {
8465
 
        this.monitored = true;
8466
 
        var type = this.id + '|' + this.type + '_' + what,
8467
 
            args = Y.Array(arguments, 0, true);
8468
 
        args[0] = type;
8469
 
        return this.host.on.apply(this.host, args);
8470
 
    },
8471
 
 
8472
 
    /**
8473
 
     * Get all of the subscribers to this event and any sibling event
8474
 
     * @method getSubs
8475
 
     * @return {Array} first item is the on subscribers, second the after.
8476
 
     */
8477
 
    getSubs: function() {
8478
 
        var s = Y.merge(this.subscribers), a = Y.merge(this.afters), sib = this.sibling;
8479
 
 
8480
 
        if (sib) {
8481
 
            Y.mix(s, sib.subscribers);
8482
 
            Y.mix(a, sib.afters);
8483
 
        }
8484
 
 
8485
 
        return [s, a];
8486
 
    },
8487
 
 
8488
 
    /**
8489
 
     * Apply configuration properties.  Only applies the CONFIG whitelist
8490
 
     * @method applyConfig
8491
 
     * @param o hash of properties to apply.
8492
 
     * @param force {boolean} if true, properties that exist on the event
8493
 
     * will be overwritten.
8494
 
     */
8495
 
    applyConfig: function(o, force) {
8496
 
        if (o) {
8497
 
            Y.mix(this, o, force, CONFIGS);
8498
 
        }
8499
 
    },
8500
 
 
8501
 
    /**
8502
 
     * Create the Subscription for subscribing function, context, and bound
8503
 
     * arguments.  If this is a fireOnce event, the subscriber is immediately 
8504
 
     * notified.
8505
 
     *
8506
 
     * @method _on
8507
 
     * @param fn {Function} Subscription callback
8508
 
     * @param [context] {Object} Override `this` in the callback
8509
 
     * @param [args] {Array} bound arguments that will be passed to the callback after the arguments generated by fire()
8510
 
     * @param [when] {String} "after" to slot into after subscribers
8511
 
     * @return {EventHandle}
8512
 
     * @protected
8513
 
     */
8514
 
    _on: function(fn, context, args, when) {
8515
 
 
8516
 
        if (!fn) {
8517
 
            this.log('Invalid callback for CE: ' + this.type);
8518
 
        }
8519
 
 
8520
 
        var s = new Y.Subscriber(fn, context, args, when);
8521
 
 
8522
 
        if (this.fireOnce && this.fired) {
8523
 
            if (this.async) {
8524
 
                setTimeout(Y.bind(this._notify, this, s, this.firedWith), 0);
8525
 
            } else {
8526
 
                this._notify(s, this.firedWith);
8527
 
            }
8528
 
        }
8529
 
 
8530
 
        if (when == AFTER) {
8531
 
            this.afters[s.id] = s;
8532
 
            this.afterCount++;
8533
 
        } else {
8534
 
            this.subscribers[s.id] = s;
8535
 
            this.subCount++;
8536
 
        }
8537
 
 
8538
 
        return new Y.EventHandle(this, s);
8539
 
 
8540
 
    },
8541
 
 
8542
 
    /**
8543
 
     * Listen for this event
8544
 
     * @method subscribe
8545
 
     * @param {Function} fn The function to execute.
8546
 
     * @return {EventHandle} Unsubscribe handle.
8547
 
     * @deprecated use on.
8548
 
     */
8549
 
    subscribe: function(fn, context) {
8550
 
        Y.log('ce.subscribe deprecated, use "on"', 'warn', 'deprecated');
8551
 
        var a = (arguments.length > 2) ? Y.Array(arguments, 2, true) : null;
8552
 
        return this._on(fn, context, a, true);
8553
 
    },
8554
 
 
8555
 
    /**
8556
 
     * Listen for this event
8557
 
     * @method on
8558
 
     * @param {Function} fn The function to execute.
8559
 
     * @param {object} context optional execution context.
8560
 
     * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
8561
 
     * when the event fires.
8562
 
     * @return {EventHandle} An object with a detach method to detch the handler(s).
8563
 
     */
8564
 
    on: function(fn, context) {
8565
 
        var a = (arguments.length > 2) ? Y.Array(arguments, 2, true) : null;
8566
 
        if (this.host) {
8567
 
            this.host._monitor('attach', this.type, {
8568
 
                args: arguments
8569
 
            });
8570
 
        }
8571
 
        return this._on(fn, context, a, true);
8572
 
    },
8573
 
 
8574
 
    /**
8575
 
     * Listen for this event after the normal subscribers have been notified and
8576
 
     * the default behavior has been applied.  If a normal subscriber prevents the
8577
 
     * default behavior, it also prevents after listeners from firing.
8578
 
     * @method after
8579
 
     * @param {Function} fn The function to execute.
8580
 
     * @param {object} context optional execution context.
8581
 
     * @param {mixed} arg* 0..n additional arguments to supply to the subscriber
8582
 
     * when the event fires.
8583
 
     * @return {EventHandle} handle Unsubscribe handle.
8584
 
     */
8585
 
    after: function(fn, context) {
8586
 
        var a = (arguments.length > 2) ? Y.Array(arguments, 2, true) : null;
8587
 
        return this._on(fn, context, a, AFTER);
8588
 
    },
8589
 
 
8590
 
    /**
8591
 
     * Detach listeners.
8592
 
     * @method detach
8593
 
     * @param {Function} fn  The subscribed function to remove, if not supplied
8594
 
     *                       all will be removed.
8595
 
     * @param {Object}   context The context object passed to subscribe.
8596
 
     * @return {int} returns the number of subscribers unsubscribed.
8597
 
     */
8598
 
    detach: function(fn, context) {
8599
 
        // unsubscribe handle
8600
 
        if (fn && fn.detach) {
8601
 
            return fn.detach();
8602
 
        }
8603
 
 
8604
 
        var i, s,
8605
 
            found = 0,
8606
 
            subs = Y.merge(this.subscribers, this.afters);
8607
 
 
8608
 
        for (i in subs) {
8609
 
            if (subs.hasOwnProperty(i)) {
8610
 
                s = subs[i];
8611
 
                if (s && (!fn || fn === s.fn)) {
8612
 
                    this._delete(s);
8613
 
                    found++;
8614
 
                }
8615
 
            }
8616
 
        }
8617
 
 
8618
 
        return found;
8619
 
    },
8620
 
 
8621
 
    /**
8622
 
     * Detach listeners.
8623
 
     * @method unsubscribe
8624
 
     * @param {Function} fn  The subscribed function to remove, if not supplied
8625
 
     *                       all will be removed.
8626
 
     * @param {Object}   context The context object passed to subscribe.
8627
 
     * @return {int|undefined} returns the number of subscribers unsubscribed.
8628
 
     * @deprecated use detach.
8629
 
     */
8630
 
    unsubscribe: function() {
8631
 
        return this.detach.apply(this, arguments);
8632
 
    },
8633
 
 
8634
 
    /**
8635
 
     * Notify a single subscriber
8636
 
     * @method _notify
8637
 
     * @param {Subscriber} s the subscriber.
8638
 
     * @param {Array} args the arguments array to apply to the listener.
8639
 
     * @protected
8640
 
     */
8641
 
    _notify: function(s, args, ef) {
8642
 
 
8643
 
        this.log(this.type + '->' + 'sub: ' + s.id);
8644
 
 
8645
 
        var ret;
8646
 
 
8647
 
        ret = s.notify(args, this);
8648
 
 
8649
 
        if (false === ret || this.stopped > 1) {
8650
 
            this.log(this.type + ' cancelled by subscriber');
8651
 
            return false;
8652
 
        }
8653
 
 
8654
 
        return true;
8655
 
    },
8656
 
 
8657
 
    /**
8658
 
     * Logger abstraction to centralize the application of the silent flag
8659
 
     * @method log
8660
 
     * @param {string} msg message to log.
8661
 
     * @param {string} cat log category.
8662
 
     */
8663
 
    log: function(msg, cat) {
8664
 
        if (!this.silent) {
8665
 
            Y.log(this.id + ': ' + msg, cat || 'info', 'event');
8666
 
        }
8667
 
    },
8668
 
 
8669
 
    /**
8670
 
     * Notifies the subscribers.  The callback functions will be executed
8671
 
     * from the context specified when the event was created, and with the
8672
 
     * following parameters:
8673
 
     *   <ul>
8674
 
     *   <li>The type of event</li>
8675
 
     *   <li>All of the arguments fire() was executed with as an array</li>
8676
 
     *   <li>The custom object (if any) that was passed into the subscribe()
8677
 
     *       method</li>
8678
 
     *   </ul>
8679
 
     * @method fire
8680
 
     * @param {Object*} arguments an arbitrary set of parameters to pass to
8681
 
     *                            the handler.
8682
 
     * @return {boolean} false if one of the subscribers returned false,
8683
 
     *                   true otherwise.
8684
 
     *
8685
 
     */
8686
 
    fire: function() {
8687
 
        if (this.fireOnce && this.fired) {
8688
 
            this.log('fireOnce event: ' + this.type + ' already fired');
8689
 
            return true;
8690
 
        } else {
8691
 
 
8692
 
            var args = Y.Array(arguments, 0, true);
8693
 
 
8694
 
            // this doesn't happen if the event isn't published
8695
 
            // this.host._monitor('fire', this.type, args);
8696
 
 
8697
 
            this.fired = true;
8698
 
            this.firedWith = args;
8699
 
 
8700
 
            if (this.emitFacade) {
8701
 
                return this.fireComplex(args);
8702
 
            } else {
8703
 
                return this.fireSimple(args);
8704
 
            }
8705
 
        }
8706
 
    },
8707
 
 
8708
 
    /**
8709
 
     * Set up for notifying subscribers of non-emitFacade events.
8710
 
     *
8711
 
     * @method fireSimple
8712
 
     * @param args {Array} Arguments passed to fire()
8713
 
     * @return Boolean false if a subscriber returned false
8714
 
     * @protected
8715
 
     */
8716
 
    fireSimple: function(args) {
8717
 
        this.stopped = 0;
8718
 
        this.prevented = 0;
8719
 
        if (this.hasSubs()) {
8720
 
            // this._procSubs(Y.merge(this.subscribers, this.afters), args);
8721
 
            var subs = this.getSubs();
8722
 
            this._procSubs(subs[0], args);
8723
 
            this._procSubs(subs[1], args);
8724
 
        }
8725
 
        this._broadcast(args);
8726
 
        return this.stopped ? false : true;
8727
 
    },
8728
 
 
8729
 
    // Requires the event-custom-complex module for full funcitonality.
8730
 
    fireComplex: function(args) {
8731
 
        Y.log('Missing event-custom-complex needed to emit a facade for: ' + this.type);
8732
 
        args[0] = args[0] || {};
8733
 
        return this.fireSimple(args);
8734
 
    },
8735
 
 
8736
 
    /**
8737
 
     * Notifies a list of subscribers.
8738
 
     *
8739
 
     * @method _procSubs
8740
 
     * @param subs {Array} List of subscribers
8741
 
     * @param args {Array} Arguments passed to fire()
8742
 
     * @param ef {}
8743
 
     * @return Boolean false if a subscriber returns false or stops the event
8744
 
     *              propagation via e.stopPropagation(),
8745
 
     *              e.stopImmediatePropagation(), or e.halt()
8746
 
     * @private
8747
 
     */
8748
 
    _procSubs: function(subs, args, ef) {
8749
 
        var s, i;
8750
 
        for (i in subs) {
8751
 
            if (subs.hasOwnProperty(i)) {
8752
 
                s = subs[i];
8753
 
                if (s && s.fn) {
8754
 
                    if (false === this._notify(s, args, ef)) {
8755
 
                        this.stopped = 2;
8756
 
                    }
8757
 
                    if (this.stopped == 2) {
8758
 
                        return false;
8759
 
                    }
8760
 
                }
8761
 
            }
8762
 
        }
8763
 
 
8764
 
        return true;
8765
 
    },
8766
 
 
8767
 
    /**
8768
 
     * Notifies the YUI instance if the event is configured with broadcast = 1,
8769
 
     * and both the YUI instance and Y.Global if configured with broadcast = 2.
8770
 
     *
8771
 
     * @method _broadcast
8772
 
     * @param args {Array} Arguments sent to fire()
8773
 
     * @private
8774
 
     */
8775
 
    _broadcast: function(args) {
8776
 
        if (!this.stopped && this.broadcast) {
8777
 
 
8778
 
            var a = Y.Array(args);
8779
 
            a.unshift(this.type);
8780
 
 
8781
 
            if (this.host !== Y) {
8782
 
                Y.fire.apply(Y, a);
8783
 
            }
8784
 
 
8785
 
            if (this.broadcast == 2) {
8786
 
                Y.Global.fire.apply(Y.Global, a);
8787
 
            }
8788
 
        }
8789
 
    },
8790
 
 
8791
 
    /**
8792
 
     * Removes all listeners
8793
 
     * @method unsubscribeAll
8794
 
     * @return {int} The number of listeners unsubscribed.
8795
 
     * @deprecated use detachAll.
8796
 
     */
8797
 
    unsubscribeAll: function() {
8798
 
        return this.detachAll.apply(this, arguments);
8799
 
    },
8800
 
 
8801
 
    /**
8802
 
     * Removes all listeners
8803
 
     * @method detachAll
8804
 
     * @return {int} The number of listeners unsubscribed.
8805
 
     */
8806
 
    detachAll: function() {
8807
 
        return this.detach();
8808
 
    },
8809
 
 
8810
 
    /**
8811
 
     * Deletes the subscriber from the internal store of on() and after()
8812
 
     * subscribers.
8813
 
     *
8814
 
     * @method _delete
8815
 
     * @param subscriber object.
8816
 
     * @private
8817
 
     */
8818
 
    _delete: function(s) {
8819
 
        if (s) {
8820
 
            if (this.subscribers[s.id]) {
8821
 
                delete this.subscribers[s.id];
8822
 
                this.subCount--;
8823
 
            }
8824
 
            if (this.afters[s.id]) {
8825
 
                delete this.afters[s.id];
8826
 
                this.afterCount--;
8827
 
            }
8828
 
        }
8829
 
 
8830
 
        if (this.host) {
8831
 
            this.host._monitor('detach', this.type, {
8832
 
                ce: this,
8833
 
                sub: s
8834
 
            });
8835
 
        }
8836
 
 
8837
 
        if (s) {
8838
 
            // delete s.fn;
8839
 
            // delete s.context;
8840
 
            s.deleted = true;
8841
 
        }
8842
 
    }
8843
 
};
8844
 
/**
8845
 
 * Stores the subscriber information to be used when the event fires.
8846
 
 * @param {Function} fn       The wrapped function to execute.
8847
 
 * @param {Object}   context  The value of the keyword 'this' in the listener.
8848
 
 * @param {Array} args*       0..n additional arguments to supply the listener.
8849
 
 *
8850
 
 * @class Subscriber
8851
 
 * @constructor
8852
 
 */
8853
 
Y.Subscriber = function(fn, context, args) {
8854
 
 
8855
 
    /**
8856
 
     * The callback that will be execute when the event fires
8857
 
     * This is wrapped by Y.rbind if obj was supplied.
8858
 
     * @property fn
8859
 
     * @type Function
8860
 
     */
8861
 
    this.fn = fn;
8862
 
 
8863
 
    /**
8864
 
     * Optional 'this' keyword for the listener
8865
 
     * @property context
8866
 
     * @type Object
8867
 
     */
8868
 
    this.context = context;
8869
 
 
8870
 
    /**
8871
 
     * Unique subscriber id
8872
 
     * @property id
8873
 
     * @type String
8874
 
     */
8875
 
    this.id = Y.stamp(this);
8876
 
 
8877
 
    /**
8878
 
     * Additional arguments to propagate to the subscriber
8879
 
     * @property args
8880
 
     * @type Array
8881
 
     */
8882
 
    this.args = args;
8883
 
 
8884
 
    /**
8885
 
     * Custom events for a given fire transaction.
8886
 
     * @property events
8887
 
     * @type {EventTarget}
8888
 
     */
8889
 
    // this.events = null;
8890
 
 
8891
 
    /**
8892
 
     * This listener only reacts to the event once
8893
 
     * @property once
8894
 
     */
8895
 
    // this.once = false;
8896
 
 
8897
 
};
8898
 
 
8899
 
Y.Subscriber.prototype = {
8900
 
    constructor: Y.Subscriber,
8901
 
 
8902
 
    _notify: function(c, args, ce) {
8903
 
        if (this.deleted && !this.postponed) {
8904
 
            if (this.postponed) {
8905
 
                delete this.fn;
8906
 
                delete this.context;
8907
 
            } else {
8908
 
                delete this.postponed;
8909
 
                return null;
8910
 
            }
8911
 
        }
8912
 
        var a = this.args, ret;
8913
 
        switch (ce.signature) {
8914
 
            case 0:
8915
 
                ret = this.fn.call(c, ce.type, args, c);
8916
 
                break;
8917
 
            case 1:
8918
 
                ret = this.fn.call(c, args[0] || null, c);
8919
 
                break;
8920
 
            default:
8921
 
                if (a || args) {
8922
 
                    args = args || [];
8923
 
                    a = (a) ? args.concat(a) : args;
8924
 
                    ret = this.fn.apply(c, a);
8925
 
                } else {
8926
 
                    ret = this.fn.call(c);
8927
 
                }
8928
 
        }
8929
 
 
8930
 
        if (this.once) {
8931
 
            ce._delete(this);
8932
 
        }
8933
 
 
8934
 
        return ret;
8935
 
    },
8936
 
 
8937
 
    /**
8938
 
     * Executes the subscriber.
8939
 
     * @method notify
8940
 
     * @param args {Array} Arguments array for the subscriber.
8941
 
     * @param ce {CustomEvent} The custom event that sent the notification.
8942
 
     */
8943
 
    notify: function(args, ce) {
8944
 
        var c = this.context,
8945
 
            ret = true;
8946
 
 
8947
 
        if (!c) {
8948
 
            c = (ce.contextFn) ? ce.contextFn() : ce.context;
8949
 
        }
8950
 
 
8951
 
        // only catch errors if we will not re-throw them.
8952
 
        if (Y.config.throwFail) {
8953
 
            ret = this._notify(c, args, ce);
8954
 
        } else {
8955
 
            try {
8956
 
                ret = this._notify(c, args, ce);
8957
 
            } catch (e) {
8958
 
                Y.error(this + ' failed: ' + e.message, e);
8959
 
            }
8960
 
        }
8961
 
 
8962
 
        return ret;
8963
 
    },
8964
 
 
8965
 
    /**
8966
 
     * Returns true if the fn and obj match this objects properties.
8967
 
     * Used by the unsubscribe method to match the right subscriber.
8968
 
     *
8969
 
     * @method contains
8970
 
     * @param {Function} fn the function to execute.
8971
 
     * @param {Object} context optional 'this' keyword for the listener.
8972
 
     * @return {boolean} true if the supplied arguments match this
8973
 
     *                   subscriber's signature.
8974
 
     */
8975
 
    contains: function(fn, context) {
8976
 
        if (context) {
8977
 
            return ((this.fn == fn) && this.context == context);
8978
 
        } else {
8979
 
            return (this.fn == fn);
8980
 
        }
8981
 
    }
8982
 
 
8983
 
};
8984
 
/**
8985
 
 * Return value from all subscribe operations
8986
 
 * @class EventHandle
8987
 
 * @constructor
8988
 
 * @param {CustomEvent} evt the custom event.
8989
 
 * @param {Subscriber} sub the subscriber.
8990
 
 */
8991
 
Y.EventHandle = function(evt, sub) {
8992
 
 
8993
 
    /**
8994
 
     * The custom event
8995
 
     * @type CustomEvent
8996
 
     */
8997
 
    this.evt = evt;
8998
 
 
8999
 
    /**
9000
 
     * The subscriber object
9001
 
     * @type Subscriber
9002
 
     */
9003
 
    this.sub = sub;
9004
 
};
9005
 
 
9006
 
Y.EventHandle.prototype = {
9007
 
    batch: function(f, c) {
9008
 
        f.call(c || this, this);
9009
 
        if (Y.Lang.isArray(this.evt)) {
9010
 
            Y.Array.each(this.evt, function(h) {
9011
 
                h.batch.call(c || h, f);
9012
 
            });
9013
 
        }
9014
 
    },
9015
 
 
9016
 
    /**
9017
 
     * Detaches this subscriber
9018
 
     * @method detach
9019
 
     * @return {int} the number of detached listeners
9020
 
     */
9021
 
    detach: function() {
9022
 
        var evt = this.evt, detached = 0, i;
9023
 
        if (evt) {
9024
 
            // Y.log('EventHandle.detach: ' + this.sub, 'info', 'Event');
9025
 
            if (Y.Lang.isArray(evt)) {
9026
 
                for (i = 0; i < evt.length; i++) {
9027
 
                    detached += evt[i].detach();
9028
 
                }
9029
 
            } else {
9030
 
                evt._delete(this.sub);
9031
 
                detached = 1;
9032
 
            }
9033
 
 
9034
 
        }
9035
 
 
9036
 
        return detached;
9037
 
    },
9038
 
 
9039
 
    /**
9040
 
     * Monitor the event state for the subscribed event.  The first parameter
9041
 
     * is what should be monitored, the rest are the normal parameters when
9042
 
     * subscribing to an event.
9043
 
     * @method monitor
9044
 
     * @param what {string} what to monitor ('attach', 'detach', 'publish').
9045
 
     * @return {EventHandle} return value from the monitor event subscription.
9046
 
     */
9047
 
    monitor: function(what) {
9048
 
        return this.evt.monitor.apply(this.evt, arguments);
9049
 
    }
9050
 
};
9051
 
 
9052
 
/**
9053
 
 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
9054
 
 * events.
9055
 
 * @module event-custom
9056
 
 * @submodule event-custom-base
9057
 
 */
9058
 
 
9059
 
/**
9060
 
 * EventTarget provides the implementation for any object to
9061
 
 * publish, subscribe and fire to custom events, and also
9062
 
 * alows other EventTargets to target the object with events
9063
 
 * sourced from the other object.
9064
 
 * EventTarget is designed to be used with Y.augment to wrap
9065
 
 * EventCustom in an interface that allows events to be listened to
9066
 
 * and fired by name.  This makes it possible for implementing code to
9067
 
 * subscribe to an event that either has not been created yet, or will
9068
 
 * not be created at all.
9069
 
 * @class EventTarget
9070
 
 * @param opts a configuration object
9071
 
 * @config emitFacade {boolean} if true, all events will emit event
9072
 
 * facade payloads by default (default false)
9073
 
 * @config prefix {string} the prefix to apply to non-prefixed event names
9074
 
 * @config chain {boolean} if true, on/after/detach return the host to allow
9075
 
 * chaining, otherwise they return an EventHandle (default false)
9076
 
 */
9077
 
 
9078
 
var L = Y.Lang,
9079
 
    PREFIX_DELIMITER = ':',
9080
 
    CATEGORY_DELIMITER = '|',
9081
 
    AFTER_PREFIX = '~AFTER~',
9082
 
    YArray = Y.Array,
9083
 
 
9084
 
    _wildType = Y.cached(function(type) {
9085
 
        return type.replace(/(.*)(:)(.*)/, "*$2$3");
9086
 
    }),
9087
 
 
9088
 
    /**
9089
 
     * If the instance has a prefix attribute and the
9090
 
     * event type is not prefixed, the instance prefix is
9091
 
     * applied to the supplied type.
9092
 
     * @method _getType
9093
 
     * @private
9094
 
     */
9095
 
    _getType = Y.cached(function(type, pre) {
9096
 
 
9097
 
        if (!pre || !L.isString(type) || type.indexOf(PREFIX_DELIMITER) > -1) {
9098
 
            return type;
9099
 
        }
9100
 
 
9101
 
        return pre + PREFIX_DELIMITER + type;
9102
 
    }),
9103
 
 
9104
 
    /**
9105
 
     * Returns an array with the detach key (if provided),
9106
 
     * and the prefixed event name from _getType
9107
 
     * Y.on('detachcategory| menu:click', fn)
9108
 
     * @method _parseType
9109
 
     * @private
9110
 
     */
9111
 
    _parseType = Y.cached(function(type, pre) {
9112
 
 
9113
 
        var t = type, detachcategory, after, i;
9114
 
 
9115
 
        if (!L.isString(t)) {
9116
 
            return t;
9117
 
        }
9118
 
 
9119
 
        i = t.indexOf(AFTER_PREFIX);
9120
 
 
9121
 
        if (i > -1) {
9122
 
            after = true;
9123
 
            t = t.substr(AFTER_PREFIX.length);
9124
 
            // Y.log(t);
9125
 
        }
9126
 
 
9127
 
        i = t.indexOf(CATEGORY_DELIMITER);
9128
 
 
9129
 
        if (i > -1) {
9130
 
            detachcategory = t.substr(0, (i));
9131
 
            t = t.substr(i+1);
9132
 
            if (t == '*') {
9133
 
                t = null;
9134
 
            }
9135
 
        }
9136
 
 
9137
 
        // detach category, full type with instance prefix, is this an after listener, short type
9138
 
        return [detachcategory, (pre) ? _getType(t, pre) : t, after, t];
9139
 
    }),
9140
 
 
9141
 
    ET = function(opts) {
9142
 
 
9143
 
        // Y.log('EventTarget constructor executed: ' + this._yuid);
9144
 
 
9145
 
        var o = (L.isObject(opts)) ? opts : {};
9146
 
 
9147
 
        this._yuievt = this._yuievt || {
9148
 
 
9149
 
            id: Y.guid(),
9150
 
 
9151
 
            events: {},
9152
 
 
9153
 
            targets: {},
9154
 
 
9155
 
            config: o,
9156
 
 
9157
 
            chain: ('chain' in o) ? o.chain : Y.config.chain,
9158
 
 
9159
 
            bubbling: false,
9160
 
 
9161
 
            defaults: {
9162
 
                context: o.context || this,
9163
 
                host: this,
9164
 
                emitFacade: o.emitFacade,
9165
 
                fireOnce: o.fireOnce,
9166
 
                queuable: o.queuable,
9167
 
                monitored: o.monitored,
9168
 
                broadcast: o.broadcast,
9169
 
                defaultTargetOnly: o.defaultTargetOnly,
9170
 
                bubbles: ('bubbles' in o) ? o.bubbles : true
9171
 
            }
9172
 
        };
9173
 
 
9174
 
    };
9175
 
 
9176
 
 
9177
 
ET.prototype = {
9178
 
    constructor: ET,
9179
 
 
9180
 
    /**
9181
 
     * Listen to a custom event hosted by this object one time.
9182
 
     * This is the equivalent to <code>on</code> except the
9183
 
     * listener is immediatelly detached when it is executed.
9184
 
     * @method once
9185
 
     * @param type    {string}   The type of the event
9186
 
     * @param fn {Function} The callback
9187
 
     * @param context {object} optional execution context.
9188
 
     * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
9189
 
     * @return the event target or a detach handle per 'chain' config
9190
 
     */
9191
 
    once: function() {
9192
 
        var handle = this.on.apply(this, arguments);
9193
 
        handle.batch(function(hand) {
9194
 
            if (hand.sub) {
9195
 
                hand.sub.once = true;
9196
 
            }
9197
 
        });
9198
 
        return handle;
9199
 
    },
9200
 
 
9201
 
    /**
9202
 
     * Listen to a custom event hosted by this object one time.
9203
 
     * This is the equivalent to <code>after</code> except the
9204
 
     * listener is immediatelly detached when it is executed.
9205
 
     * @method onceAfter
9206
 
     * @param type    {string}   The type of the event
9207
 
     * @param fn {Function} The callback
9208
 
     * @param context {object} optional execution context.
9209
 
     * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
9210
 
     * @return the event target or a detach handle per 'chain' config
9211
 
     */
9212
 
    onceAfter: function() {
9213
 
        var args = YArray(arguments, 0, true);
9214
 
        args[0] = AFTER_PREFIX + args[0];
9215
 
 
9216
 
        return this.once.apply(this, args);
9217
 
    },
9218
 
 
9219
 
    /**
9220
 
     * Takes the type parameter passed to 'on' and parses out the
9221
 
     * various pieces that could be included in the type.  If the
9222
 
     * event type is passed without a prefix, it will be expanded
9223
 
     * to include the prefix one is supplied or the event target
9224
 
     * is configured with a default prefix.
9225
 
     * @method parseType
9226
 
     * @param {string} type the type
9227
 
     * @param {string} [pre=this._yuievt.config.prefix] the prefix
9228
 
     * @since 3.3.0
9229
 
     * @return {Array} an array containing:
9230
 
     *  * the detach category, if supplied,
9231
 
     *  * the prefixed event type,
9232
 
     *  * whether or not this is an after listener,
9233
 
     *  * the supplied event type
9234
 
     */
9235
 
    parseType: function(type, pre) {
9236
 
        return _parseType(type, pre || this._yuievt.config.prefix);
9237
 
    },
9238
 
 
9239
 
    /**
9240
 
     * Subscribe to a custom event hosted by this object
9241
 
     * @method on
9242
 
     * @param type    {string}   The type of the event
9243
 
     * @param fn {Function} The callback
9244
 
     * @param context {object} optional execution context.
9245
 
     * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
9246
 
     * @return the event target or a detach handle per 'chain' config
9247
 
     */
9248
 
    on: function(type, fn, context) {
9249
 
 
9250
 
        var parts = _parseType(type, this._yuievt.config.prefix), f, c, args, ret, ce,
9251
 
            detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype,
9252
 
            Node = Y.Node, n, domevent, isArr;
9253
 
 
9254
 
        // full name, args, detachcategory, after
9255
 
        this._monitor('attach', parts[1], {
9256
 
            args: arguments,
9257
 
            category: parts[0],
9258
 
            after: parts[2]
9259
 
        });
9260
 
 
9261
 
        if (L.isObject(type)) {
9262
 
 
9263
 
            if (L.isFunction(type)) {
9264
 
                return Y.Do.before.apply(Y.Do, arguments);
9265
 
            }
9266
 
 
9267
 
            f = fn;
9268
 
            c = context;
9269
 
            args = YArray(arguments, 0, true);
9270
 
            ret = [];
9271
 
 
9272
 
            if (L.isArray(type)) {
9273
 
                isArr = true;
9274
 
            }
9275
 
 
9276
 
            after = type._after;
9277
 
            delete type._after;
9278
 
 
9279
 
            Y.each(type, function(v, k) {
9280
 
 
9281
 
                if (L.isObject(v)) {
9282
 
                    f = v.fn || ((L.isFunction(v)) ? v : f);
9283
 
                    c = v.context || c;
9284
 
                }
9285
 
 
9286
 
                var nv = (after) ? AFTER_PREFIX : '';
9287
 
 
9288
 
                args[0] = nv + ((isArr) ? v : k);
9289
 
                args[1] = f;
9290
 
                args[2] = c;
9291
 
 
9292
 
                ret.push(this.on.apply(this, args));
9293
 
 
9294
 
            }, this);
9295
 
 
9296
 
            return (this._yuievt.chain) ? this : new Y.EventHandle(ret);
9297
 
 
9298
 
        }
9299
 
 
9300
 
        detachcategory = parts[0];
9301
 
        after = parts[2];
9302
 
        shorttype = parts[3];
9303
 
 
9304
 
        // extra redirection so we catch adaptor events too.  take a look at this.
9305
 
        if (Node && Y.instanceOf(this, Node) && (shorttype in Node.DOM_EVENTS)) {
9306
 
            args = YArray(arguments, 0, true);
9307
 
            args.splice(2, 0, Node.getDOMNode(this));
9308
 
            // Y.log("Node detected, redirecting with these args: " + args);
9309
 
            return Y.on.apply(Y, args);
9310
 
        }
9311
 
 
9312
 
        type = parts[1];
9313
 
 
9314
 
        if (Y.instanceOf(this, YUI)) {
9315
 
 
9316
 
            adapt = Y.Env.evt.plugins[type];
9317
 
            args  = YArray(arguments, 0, true);
9318
 
            args[0] = shorttype;
9319
 
 
9320
 
            if (Node) {
9321
 
                n = args[2];
9322
 
 
9323
 
                if (Y.instanceOf(n, Y.NodeList)) {
9324
 
                    n = Y.NodeList.getDOMNodes(n);
9325
 
                } else if (Y.instanceOf(n, Node)) {
9326
 
                    n = Node.getDOMNode(n);
9327
 
                }
9328
 
 
9329
 
                domevent = (shorttype in Node.DOM_EVENTS);
9330
 
 
9331
 
                // Captures both DOM events and event plugins.
9332
 
                if (domevent) {
9333
 
                    args[2] = n;
9334
 
                }
9335
 
            }
9336
 
 
9337
 
            // check for the existance of an event adaptor
9338
 
            if (adapt) {
9339
 
                Y.log('Using adaptor for ' + shorttype + ', ' + n, 'info', 'event');
9340
 
                handle = adapt.on.apply(Y, args);
9341
 
            } else if ((!type) || domevent) {
9342
 
                handle = Y.Event._attach(args);
9343
 
            }
9344
 
 
9345
 
        }
9346
 
 
9347
 
        if (!handle) {
9348
 
            ce = this._yuievt.events[type] || this.publish(type);
9349
 
            handle = ce._on(fn, context, (arguments.length > 3) ? YArray(arguments, 3, true) : null, (after) ? 'after' : true);
9350
 
        }
9351
 
 
9352
 
        if (detachcategory) {
9353
 
            store[detachcategory] = store[detachcategory] || {};
9354
 
            store[detachcategory][type] = store[detachcategory][type] || [];
9355
 
            store[detachcategory][type].push(handle);
9356
 
        }
9357
 
 
9358
 
        return (this._yuievt.chain) ? this : handle;
9359
 
 
9360
 
    },
9361
 
 
9362
 
    /**
9363
 
     * subscribe to an event
9364
 
     * @method subscribe
9365
 
     * @deprecated use on
9366
 
     */
9367
 
    subscribe: function() {
9368
 
        Y.log('EventTarget subscribe() is deprecated, use on()', 'warn', 'deprecated');
9369
 
        return this.on.apply(this, arguments);
9370
 
    },
9371
 
 
9372
 
    /**
9373
 
     * Detach one or more listeners the from the specified event
9374
 
     * @method detach
9375
 
     * @param type {string|Object}   Either the handle to the subscriber or the
9376
 
     *                        type of event.  If the type
9377
 
     *                        is not specified, it will attempt to remove
9378
 
     *                        the listener from all hosted events.
9379
 
     * @param fn   {Function} The subscribed function to unsubscribe, if not
9380
 
     *                          supplied, all subscribers will be removed.
9381
 
     * @param context  {Object}   The custom object passed to subscribe.  This is
9382
 
     *                        optional, but if supplied will be used to
9383
 
     *                        disambiguate multiple listeners that are the same
9384
 
     *                        (e.g., you subscribe many object using a function
9385
 
     *                        that lives on the prototype)
9386
 
     * @return {EventTarget} the host
9387
 
     */
9388
 
    detach: function(type, fn, context) {
9389
 
        var evts = this._yuievt.events, i,
9390
 
            Node = Y.Node, isNode = Node && (Y.instanceOf(this, Node));
9391
 
 
9392
 
        // detachAll disabled on the Y instance.
9393
 
        if (!type && (this !== Y)) {
9394
 
            for (i in evts) {
9395
 
                if (evts.hasOwnProperty(i)) {
9396
 
                    evts[i].detach(fn, context);
9397
 
                }
9398
 
            }
9399
 
            if (isNode) {
9400
 
                Y.Event.purgeElement(Node.getDOMNode(this));
9401
 
            }
9402
 
 
9403
 
            return this;
9404
 
        }
9405
 
 
9406
 
        var parts = _parseType(type, this._yuievt.config.prefix),
9407
 
        detachcategory = L.isArray(parts) ? parts[0] : null,
9408
 
        shorttype = (parts) ? parts[3] : null,
9409
 
        adapt, store = Y.Env.evt.handles, detachhost, cat, args,
9410
 
        ce,
9411
 
 
9412
 
        keyDetacher = function(lcat, ltype, host) {
9413
 
            var handles = lcat[ltype], ce, i;
9414
 
            if (handles) {
9415
 
                for (i = handles.length - 1; i >= 0; --i) {
9416
 
                    ce = handles[i].evt;
9417
 
                    if (ce.host === host || ce.el === host) {
9418
 
                        handles[i].detach();
9419
 
                    }
9420
 
                }
9421
 
            }
9422
 
        };
9423
 
 
9424
 
        if (detachcategory) {
9425
 
 
9426
 
            cat = store[detachcategory];
9427
 
            type = parts[1];
9428
 
            detachhost = (isNode) ? Y.Node.getDOMNode(this) : this;
9429
 
 
9430
 
            if (cat) {
9431
 
                if (type) {
9432
 
                    keyDetacher(cat, type, detachhost);
9433
 
                } else {
9434
 
                    for (i in cat) {
9435
 
                        if (cat.hasOwnProperty(i)) {
9436
 
                            keyDetacher(cat, i, detachhost);
9437
 
                        }
9438
 
                    }
9439
 
                }
9440
 
 
9441
 
                return this;
9442
 
            }
9443
 
 
9444
 
        // If this is an event handle, use it to detach
9445
 
        } else if (L.isObject(type) && type.detach) {
9446
 
            type.detach();
9447
 
            return this;
9448
 
        // extra redirection so we catch adaptor events too.  take a look at this.
9449
 
        } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) {
9450
 
            args = YArray(arguments, 0, true);
9451
 
            args[2] = Node.getDOMNode(this);
9452
 
            Y.detach.apply(Y, args);
9453
 
            return this;
9454
 
        }
9455
 
 
9456
 
        adapt = Y.Env.evt.plugins[shorttype];
9457
 
 
9458
 
        // The YUI instance handles DOM events and adaptors
9459
 
        if (Y.instanceOf(this, YUI)) {
9460
 
            args = YArray(arguments, 0, true);
9461
 
            // use the adaptor specific detach code if
9462
 
            if (adapt && adapt.detach) {
9463
 
                adapt.detach.apply(Y, args);
9464
 
                return this;
9465
 
            // DOM event fork
9466
 
            } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) {
9467
 
                args[0] = type;
9468
 
                Y.Event.detach.apply(Y.Event, args);
9469
 
                return this;
9470
 
            }
9471
 
        }
9472
 
 
9473
 
        // ce = evts[type];
9474
 
        ce = evts[parts[1]];
9475
 
        if (ce) {
9476
 
            ce.detach(fn, context);
9477
 
        }
9478
 
 
9479
 
        return this;
9480
 
    },
9481
 
 
9482
 
    /**
9483
 
     * detach a listener
9484
 
     * @method unsubscribe
9485
 
     * @deprecated use detach
9486
 
     */
9487
 
    unsubscribe: function() {
9488
 
Y.log('EventTarget unsubscribe() is deprecated, use detach()', 'warn', 'deprecated');
9489
 
        return this.detach.apply(this, arguments);
9490
 
    },
9491
 
 
9492
 
    /**
9493
 
     * Removes all listeners from the specified event.  If the event type
9494
 
     * is not specified, all listeners from all hosted custom events will
9495
 
     * be removed.
9496
 
     * @method detachAll
9497
 
     * @param type {string}   The type, or name of the event
9498
 
     */
9499
 
    detachAll: function(type) {
9500
 
        return this.detach(type);
9501
 
    },
9502
 
 
9503
 
    /**
9504
 
     * Removes all listeners from the specified event.  If the event type
9505
 
     * is not specified, all listeners from all hosted custom events will
9506
 
     * be removed.
9507
 
     * @method unsubscribeAll
9508
 
     * @param type {string}   The type, or name of the event
9509
 
     * @deprecated use detachAll
9510
 
     */
9511
 
    unsubscribeAll: function() {
9512
 
Y.log('EventTarget unsubscribeAll() is deprecated, use detachAll()', 'warn', 'deprecated');
9513
 
        return this.detachAll.apply(this, arguments);
9514
 
    },
9515
 
 
9516
 
    /**
9517
 
     * Creates a new custom event of the specified type.  If a custom event
9518
 
     * by that name already exists, it will not be re-created.  In either
9519
 
     * case the custom event is returned.
9520
 
     *
9521
 
     * @method publish
9522
 
     *
9523
 
     * @param type {string} the type, or name of the event
9524
 
     * @param opts {object} optional config params.  Valid properties are:
9525
 
     *
9526
 
     *  <ul>
9527
 
     *    <li>
9528
 
     *   'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
9529
 
     *    </li>
9530
 
     *    <li>
9531
 
     *   'bubbles': whether or not this event bubbles (true)
9532
 
     *              Events can only bubble if emitFacade is true.
9533
 
     *    </li>
9534
 
     *    <li>
9535
 
     *   'context': the default execution context for the listeners (this)
9536
 
     *    </li>
9537
 
     *    <li>
9538
 
     *   'defaultFn': the default function to execute when this event fires if preventDefault was not called
9539
 
     *    </li>
9540
 
     *    <li>
9541
 
     *   'emitFacade': whether or not this event emits a facade (false)
9542
 
     *    </li>
9543
 
     *    <li>
9544
 
     *   'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click'
9545
 
     *    </li>
9546
 
     *    <li>
9547
 
     *   'fireOnce': if an event is configured to fire once, new subscribers after
9548
 
     *   the fire will be notified immediately.
9549
 
     *    </li>
9550
 
     *    <li>
9551
 
     *   'async': fireOnce event listeners will fire synchronously if the event has already
9552
 
     *    fired unless async is true.
9553
 
     *    </li>
9554
 
     *    <li>
9555
 
     *   'preventable': whether or not preventDefault() has an effect (true)
9556
 
     *    </li>
9557
 
     *    <li>
9558
 
     *   'preventedFn': a function that is executed when preventDefault is called
9559
 
     *    </li>
9560
 
     *    <li>
9561
 
     *   'queuable': whether or not this event can be queued during bubbling (false)
9562
 
     *    </li>
9563
 
     *    <li>
9564
 
     *   'silent': if silent is true, debug messages are not provided for this event.
9565
 
     *    </li>
9566
 
     *    <li>
9567
 
     *   'stoppedFn': a function that is executed when stopPropagation is called
9568
 
     *    </li>
9569
 
     *
9570
 
     *    <li>
9571
 
     *   'monitored': specifies whether or not this event should send notifications about
9572
 
     *   when the event has been attached, detached, or published.
9573
 
     *    </li>
9574
 
     *    <li>
9575
 
     *   'type': the event type (valid option if not provided as the first parameter to publish)
9576
 
     *    </li>
9577
 
     *  </ul>
9578
 
     *
9579
 
     *  @return {CustomEvent} the custom event
9580
 
     *
9581
 
     */
9582
 
    publish: function(type, opts) {
9583
 
        var events, ce, ret, defaults,
9584
 
            edata    = this._yuievt,
9585
 
            pre      = edata.config.prefix;
9586
 
 
9587
 
        type = (pre) ? _getType(type, pre) : type;
9588
 
 
9589
 
        this._monitor('publish', type, {
9590
 
            args: arguments
9591
 
        });
9592
 
 
9593
 
        if (L.isObject(type)) {
9594
 
            ret = {};
9595
 
            Y.each(type, function(v, k) {
9596
 
                ret[k] = this.publish(k, v || opts);
9597
 
            }, this);
9598
 
 
9599
 
            return ret;
9600
 
        }
9601
 
 
9602
 
        events = edata.events;
9603
 
        ce = events[type];
9604
 
 
9605
 
        if (ce) {
9606
 
// ce.log("publish applying new config to published event: '"+type+"' exists", 'info', 'event');
9607
 
            if (opts) {
9608
 
                ce.applyConfig(opts, true);
9609
 
            }
9610
 
        } else {
9611
 
 
9612
 
            defaults = edata.defaults;
9613
 
 
9614
 
            // apply defaults
9615
 
            ce = new Y.CustomEvent(type,
9616
 
                                  (opts) ? Y.merge(defaults, opts) : defaults);
9617
 
            events[type] = ce;
9618
 
        }
9619
 
 
9620
 
        // make sure we turn the broadcast flag off if this
9621
 
        // event was published as a result of bubbling
9622
 
        // if (opts instanceof Y.CustomEvent) {
9623
 
          //   events[type].broadcast = false;
9624
 
        // }
9625
 
 
9626
 
        return events[type];
9627
 
    },
9628
 
 
9629
 
    /**
9630
 
     * This is the entry point for the event monitoring system.
9631
 
     * You can monitor 'attach', 'detach', 'fire', and 'publish'.
9632
 
     * When configured, these events generate an event.  click ->
9633
 
     * click_attach, click_detach, click_publish -- these can
9634
 
     * be subscribed to like other events to monitor the event
9635
 
     * system.  Inividual published events can have monitoring
9636
 
     * turned on or off (publish can't be turned off before it
9637
 
     * it published) by setting the events 'monitor' config.
9638
 
     *
9639
 
     * @method _monitor
9640
 
     * @param what {String} 'attach', 'detach', 'fire', or 'publish'
9641
 
     * @param type {String} Name of the event being monitored
9642
 
     * @param o {Object} Information about the event interaction, such as
9643
 
     *                  fire() args, subscription category, publish config
9644
 
     * @private
9645
 
     */
9646
 
    _monitor: function(what, type, o) {
9647
 
        var monitorevt, ce = this.getEvent(type);
9648
 
        if ((this._yuievt.config.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) {
9649
 
            monitorevt = type + '_' + what;
9650
 
            // Y.log('monitoring: ' + monitorevt);
9651
 
            o.monitored = what;
9652
 
            this.fire.call(this, monitorevt, o);
9653
 
        }
9654
 
    },
9655
 
 
9656
 
   /**
9657
 
     * Fire a custom event by name.  The callback functions will be executed
9658
 
     * from the context specified when the event was created, and with the
9659
 
     * following parameters.
9660
 
     *
9661
 
     * If the custom event object hasn't been created, then the event hasn't
9662
 
     * been published and it has no subscribers.  For performance sake, we
9663
 
     * immediate exit in this case.  This means the event won't bubble, so
9664
 
     * if the intention is that a bubble target be notified, the event must
9665
 
     * be published on this object first.
9666
 
     *
9667
 
     * The first argument is the event type, and any additional arguments are
9668
 
     * passed to the listeners as parameters.  If the first of these is an
9669
 
     * object literal, and the event is configured to emit an event facade,
9670
 
     * that object is mixed into the event facade and the facade is provided
9671
 
     * in place of the original object.
9672
 
     *
9673
 
     * @method fire
9674
 
     * @param type {String|Object} The type of the event, or an object that contains
9675
 
     * a 'type' property.
9676
 
     * @param arguments {Object*} an arbitrary set of parameters to pass to
9677
 
     * the handler.  If the first of these is an object literal and the event is
9678
 
     * configured to emit an event facade, the event facade will replace that
9679
 
     * parameter after the properties the object literal contains are copied to
9680
 
     * the event facade.
9681
 
     * @return {EventTarget} the event host
9682
 
     *
9683
 
     */
9684
 
    fire: function(type) {
9685
 
 
9686
 
        var typeIncluded = L.isString(type),
9687
 
            t = (typeIncluded) ? type : (type && type.type),
9688
 
            ce, ret, pre = this._yuievt.config.prefix, ce2,
9689
 
            args = (typeIncluded) ? YArray(arguments, 1, true) : arguments;
9690
 
 
9691
 
        t = (pre) ? _getType(t, pre) : t;
9692
 
 
9693
 
        this._monitor('fire', t, {
9694
 
            args: args
9695
 
        });
9696
 
 
9697
 
        ce = this.getEvent(t, true);
9698
 
        ce2 = this.getSibling(t, ce);
9699
 
 
9700
 
        if (ce2 && !ce) {
9701
 
            ce = this.publish(t);
9702
 
        }
9703
 
 
9704
 
        // this event has not been published or subscribed to
9705
 
        if (!ce) {
9706
 
            if (this._yuievt.hasTargets) {
9707
 
                return this.bubble({ type: t }, args, this);
9708
 
            }
9709
 
 
9710
 
            // otherwise there is nothing to be done
9711
 
            ret = true;
9712
 
        } else {
9713
 
            ce.sibling = ce2;
9714
 
            ret = ce.fire.apply(ce, args);
9715
 
        }
9716
 
 
9717
 
        return (this._yuievt.chain) ? this : ret;
9718
 
    },
9719
 
 
9720
 
    getSibling: function(type, ce) {
9721
 
        var ce2;
9722
 
        // delegate to *:type events if there are subscribers
9723
 
        if (type.indexOf(PREFIX_DELIMITER) > -1) {
9724
 
            type = _wildType(type);
9725
 
            // console.log(type);
9726
 
            ce2 = this.getEvent(type, true);
9727
 
            if (ce2) {
9728
 
                // console.log("GOT ONE: " + type);
9729
 
                ce2.applyConfig(ce);
9730
 
                ce2.bubbles = false;
9731
 
                ce2.broadcast = 0;
9732
 
                // ret = ce2.fire.apply(ce2, a);
9733
 
            }
9734
 
        }
9735
 
 
9736
 
        return ce2;
9737
 
    },
9738
 
 
9739
 
    /**
9740
 
     * Returns the custom event of the provided type has been created, a
9741
 
     * falsy value otherwise
9742
 
     * @method getEvent
9743
 
     * @param type {string} the type, or name of the event
9744
 
     * @param prefixed {string} if true, the type is prefixed already
9745
 
     * @return {CustomEvent} the custom event or null
9746
 
     */
9747
 
    getEvent: function(type, prefixed) {
9748
 
        var pre, e;
9749
 
        if (!prefixed) {
9750
 
            pre = this._yuievt.config.prefix;
9751
 
            type = (pre) ? _getType(type, pre) : type;
9752
 
        }
9753
 
        e = this._yuievt.events;
9754
 
        return e[type] || null;
9755
 
    },
9756
 
 
9757
 
    /**
9758
 
     * Subscribe to a custom event hosted by this object.  The
9759
 
     * supplied callback will execute after any listeners add
9760
 
     * via the subscribe method, and after the default function,
9761
 
     * if configured for the event, has executed.
9762
 
     * @method after
9763
 
     * @param type    {string}   The type of the event
9764
 
     * @param fn {Function} The callback
9765
 
     * @param context {object} optional execution context.
9766
 
     * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
9767
 
     * @return the event target or a detach handle per 'chain' config
9768
 
     */
9769
 
    after: function(type, fn) {
9770
 
 
9771
 
        var a = YArray(arguments, 0, true);
9772
 
 
9773
 
        switch (L.type(type)) {
9774
 
            case 'function':
9775
 
                return Y.Do.after.apply(Y.Do, arguments);
9776
 
            case 'array':
9777
 
            //     YArray.each(a[0], function(v) {
9778
 
            //         v = AFTER_PREFIX + v;
9779
 
            //     });
9780
 
            //     break;
9781
 
            case 'object':
9782
 
                a[0]._after = true;
9783
 
                break;
9784
 
            default:
9785
 
                a[0] = AFTER_PREFIX + type;
9786
 
        }
9787
 
 
9788
 
        return this.on.apply(this, a);
9789
 
 
9790
 
    },
9791
 
 
9792
 
    /**
9793
 
     * Executes the callback before a DOM event, custom event
9794
 
     * or method.  If the first argument is a function, it
9795
 
     * is assumed the target is a method.  For DOM and custom
9796
 
     * events, this is an alias for Y.on.
9797
 
     *
9798
 
     * For DOM and custom events:
9799
 
     * type, callback, context, 0-n arguments
9800
 
     *
9801
 
     * For methods:
9802
 
     * callback, object (method host), methodName, context, 0-n arguments
9803
 
     *
9804
 
     * @method before
9805
 
     * @return detach handle
9806
 
     */
9807
 
    before: function() {
9808
 
        return this.on.apply(this, arguments);
9809
 
    }
9810
 
 
9811
 
};
9812
 
 
9813
 
Y.EventTarget = ET;
9814
 
 
9815
 
// make Y an event target
9816
 
Y.mix(Y, ET.prototype);
9817
 
ET.call(Y, { bubbles: false });
9818
 
 
9819
 
YUI.Env.globalEvents = YUI.Env.globalEvents || new ET();
9820
 
 
9821
 
/**
9822
 
 * Hosts YUI page level events.  This is where events bubble to
9823
 
 * when the broadcast config is set to 2.  This property is
9824
 
 * only available if the custom event module is loaded.
9825
 
 * @property Global
9826
 
 * @type EventTarget
9827
 
 * @for YUI
9828
 
 */
9829
 
Y.Global = YUI.Env.globalEvents;
9830
 
 
9831
 
// @TODO implement a global namespace function on Y.Global?
9832
 
 
9833
 
/**
9834
 
 * <code>YUI</code>'s <code>on</code> method is a unified interface for subscribing to
9835
 
 * most events exposed by YUI.  This includes custom events, DOM events, and
9836
 
 * function events.  <code>detach</code> is also provided to remove listeners
9837
 
 * serviced by this function.
9838
 
 *
9839
 
 * The signature that <code>on</code> accepts varies depending on the type
9840
 
 * of event being consumed.  Refer to the specific methods that will
9841
 
 * service a specific request for additional information about subscribing
9842
 
 * to that type of event.
9843
 
 *
9844
 
 * <ul>
9845
 
 * <li>Custom events.  These events are defined by various
9846
 
 * modules in the library.  This type of event is delegated to
9847
 
 * <code>EventTarget</code>'s <code>on</code> method.
9848
 
 *   <ul>
9849
 
 *     <li>The type of the event</li>
9850
 
 *     <li>The callback to execute</li>
9851
 
 *     <li>An optional context object</li>
9852
 
 *     <li>0..n additional arguments to supply the callback.</li>
9853
 
 *   </ul>
9854
 
 *   Example:
9855
 
 *   <code>Y.on('drag:drophit', function() { // start work });</code>
9856
 
 * </li>
9857
 
 * <li>DOM events.  These are moments reported by the browser related
9858
 
 * to browser functionality and user interaction.
9859
 
 * This type of event is delegated to <code>Event</code>'s
9860
 
 * <code>attach</code> method.
9861
 
 *   <ul>
9862
 
 *     <li>The type of the event</li>
9863
 
 *     <li>The callback to execute</li>
9864
 
 *     <li>The specification for the Node(s) to attach the listener
9865
 
 *     to.  This can be a selector, collections, or Node/Element
9866
 
 *     refereces.</li>
9867
 
 *     <li>An optional context object</li>
9868
 
 *     <li>0..n additional arguments to supply the callback.</li>
9869
 
 *   </ul>
9870
 
 *   Example:
9871
 
 *   <code>Y.on('click', function(e) { // something was clicked }, '#someelement');</code>
9872
 
 * </li>
9873
 
 * <li>Function events.  These events can be used to react before or after a
9874
 
 * function is executed.  This type of event is delegated to <code>Event.Do</code>'s
9875
 
 * <code>before</code> method.
9876
 
 *   <ul>
9877
 
 *     <li>The callback to execute</li>
9878
 
 *     <li>The object that has the function that will be listened for.</li>
9879
 
 *     <li>The name of the function to listen for.</li>
9880
 
 *     <li>An optional context object</li>
9881
 
 *     <li>0..n additional arguments to supply the callback.</li>
9882
 
 *   </ul>
9883
 
 *   Example <code>Y.on(function(arg1, arg2, etc) { // obj.methodname was executed }, obj 'methodname');</code>
9884
 
 * </li>
9885
 
 * </ul>
9886
 
 *
9887
 
 * <code>on</code> corresponds to the moment before any default behavior of
9888
 
 * the event.  <code>after</code> works the same way, but these listeners
9889
 
 * execute after the event's default behavior.  <code>before</code> is an
9890
 
 * alias for <code>on</code>.
9891
 
 *
9892
 
 * @method on
9893
 
 * @param type event type (this parameter does not apply for function events)
9894
 
 * @param fn the callback
9895
 
 * @param context optionally change the value of 'this' in the callback
9896
 
 * @param args* 0..n additional arguments to pass to the callback.
9897
 
 * @return the event target or a detach handle per 'chain' config
9898
 
 * @for YUI
9899
 
 */
9900
 
 
9901
 
 /**
9902
 
  * Listen for an event one time.  Equivalent to <code>on</code>, except that
9903
 
  * the listener is immediately detached when executed.
9904
 
  * @see on
9905
 
  * @method once
9906
 
  * @param type event type (this parameter does not apply for function events)
9907
 
  * @param fn the callback
9908
 
  * @param context optionally change the value of 'this' in the callback
9909
 
  * @param args* 0..n additional arguments to pass to the callback.
9910
 
  * @return the event target or a detach handle per 'chain' config
9911
 
  * @for YUI
9912
 
  */
9913
 
 
9914
 
/**
9915
 
 * after() is a unified interface for subscribing to
9916
 
 * most events exposed by YUI.  This includes custom events,
9917
 
 * DOM events, and AOP events.  This works the same way as
9918
 
 * the on() function, only it operates after any default
9919
 
 * behavior for the event has executed. @see <code>on</code> for more
9920
 
 * information.
9921
 
 * @method after
9922
 
 * @param type event type (this parameter does not apply for function events)
9923
 
 * @param fn the callback
9924
 
 * @param context optionally change the value of 'this' in the callback
9925
 
 * @param args* 0..n additional arguments to pass to the callback.
9926
 
 * @return the event target or a detach handle per 'chain' config
9927
 
 * @for YUI
9928
 
 */
9929
 
 
9930
 
 
9931
 
}, '3.4.1' ,{requires:['oop']});
9932
 
YUI.add('event-custom-complex', function(Y) {
9933
 
 
9934
 
 
9935
 
/**
9936
 
 * Adds event facades, preventable default behavior, and bubbling.
9937
 
 * events.
9938
 
 * @module event-custom
9939
 
 * @submodule event-custom-complex
9940
 
 */
9941
 
 
9942
 
var FACADE,
9943
 
    FACADE_KEYS,
9944
 
    EMPTY = {},
9945
 
    CEProto = Y.CustomEvent.prototype,
9946
 
    ETProto = Y.EventTarget.prototype;
9947
 
 
9948
 
/**
9949
 
 * Wraps and protects a custom event for use when emitFacade is set to true.
9950
 
 * Requires the event-custom-complex module
9951
 
 * @class EventFacade
9952
 
 * @param e {Event} the custom event
9953
 
 * @param currentTarget {HTMLElement} the element the listener was attached to
9954
 
 */
9955
 
 
9956
 
Y.EventFacade = function(e, currentTarget) {
9957
 
 
9958
 
    e = e || EMPTY;
9959
 
 
9960
 
    this._event = e;
9961
 
 
9962
 
    /**
9963
 
     * The arguments passed to fire
9964
 
     * @property details
9965
 
     * @type Array
9966
 
     */
9967
 
    this.details = e.details;
9968
 
 
9969
 
    /**
9970
 
     * The event type, this can be overridden by the fire() payload
9971
 
     * @property type
9972
 
     * @type string
9973
 
     */
9974
 
    this.type = e.type;
9975
 
 
9976
 
    /**
9977
 
     * The real event type
9978
 
     * @property type
9979
 
     * @type string
9980
 
     */
9981
 
    this._type = e.type;
9982
 
 
9983
 
    //////////////////////////////////////////////////////
9984
 
 
9985
 
    /**
9986
 
     * Node reference for the targeted eventtarget
9987
 
     * @property target
9988
 
     * @type Node
9989
 
     */
9990
 
    this.target = e.target;
9991
 
 
9992
 
    /**
9993
 
     * Node reference for the element that the listener was attached to.
9994
 
     * @property currentTarget
9995
 
     * @type Node
9996
 
     */
9997
 
    this.currentTarget = currentTarget;
9998
 
 
9999
 
    /**
10000
 
     * Node reference to the relatedTarget
10001
 
     * @property relatedTarget
10002
 
     * @type Node
10003
 
     */
10004
 
    this.relatedTarget = e.relatedTarget;
10005
 
 
10006
 
};
10007
 
 
10008
 
Y.extend(Y.EventFacade, Object, {
10009
 
 
10010
 
    /**
10011
 
     * Stops the propagation to the next bubble target
10012
 
     * @method stopPropagation
10013
 
     */
10014
 
    stopPropagation: function() {
10015
 
        this._event.stopPropagation();
10016
 
        this.stopped = 1;
10017
 
    },
10018
 
 
10019
 
    /**
10020
 
     * Stops the propagation to the next bubble target and
10021
 
     * prevents any additional listeners from being exectued
10022
 
     * on the current target.
10023
 
     * @method stopImmediatePropagation
10024
 
     */
10025
 
    stopImmediatePropagation: function() {
10026
 
        this._event.stopImmediatePropagation();
10027
 
        this.stopped = 2;
10028
 
    },
10029
 
 
10030
 
    /**
10031
 
     * Prevents the event's default behavior
10032
 
     * @method preventDefault
10033
 
     */
10034
 
    preventDefault: function() {
10035
 
        this._event.preventDefault();
10036
 
        this.prevented = 1;
10037
 
    },
10038
 
 
10039
 
    /**
10040
 
     * Stops the event propagation and prevents the default
10041
 
     * event behavior.
10042
 
     * @method halt
10043
 
     * @param immediate {boolean} if true additional listeners
10044
 
     * on the current target will not be executed
10045
 
     */
10046
 
    halt: function(immediate) {
10047
 
        this._event.halt(immediate);
10048
 
        this.prevented = 1;
10049
 
        this.stopped = (immediate) ? 2 : 1;
10050
 
    }
10051
 
 
10052
 
});
10053
 
 
10054
 
CEProto.fireComplex = function(args) {
10055
 
 
10056
 
    var es, ef, q, queue, ce, ret, events, subs, postponed,
10057
 
        self = this, host = self.host || self, next, oldbubble;
10058
 
 
10059
 
    if (self.stack) {
10060
 
        // queue this event if the current item in the queue bubbles
10061
 
        if (self.queuable && self.type != self.stack.next.type) {
10062
 
            self.log('queue ' + self.type);
10063
 
            self.stack.queue.push([self, args]);
10064
 
            return true;
10065
 
        }
10066
 
    }
10067
 
 
10068
 
    es = self.stack || {
10069
 
       // id of the first event in the stack
10070
 
       id: self.id,
10071
 
       next: self,
10072
 
       silent: self.silent,
10073
 
       stopped: 0,
10074
 
       prevented: 0,
10075
 
       bubbling: null,
10076
 
       type: self.type,
10077
 
       // defaultFnQueue: new Y.Queue(),
10078
 
       afterQueue: new Y.Queue(),
10079
 
       defaultTargetOnly: self.defaultTargetOnly,
10080
 
       queue: []
10081
 
    };
10082
 
 
10083
 
    subs = self.getSubs();
10084
 
 
10085
 
    self.stopped = (self.type !== es.type) ? 0 : es.stopped;
10086
 
    self.prevented = (self.type !== es.type) ? 0 : es.prevented;
10087
 
 
10088
 
    self.target = self.target || host;
10089
 
 
10090
 
    events = new Y.EventTarget({
10091
 
        fireOnce: true,
10092
 
        context: host
10093
 
    });
10094
 
 
10095
 
    self.events = events;
10096
 
 
10097
 
    if (self.stoppedFn) {
10098
 
        events.on('stopped', self.stoppedFn);
10099
 
    }
10100
 
 
10101
 
    self.currentTarget = host;
10102
 
 
10103
 
    self.details = args.slice(); // original arguments in the details
10104
 
 
10105
 
    // self.log("Firing " + self  + ", " + "args: " + args);
10106
 
    self.log("Firing " + self.type);
10107
 
 
10108
 
    self._facade = null; // kill facade to eliminate stale properties
10109
 
 
10110
 
    ef = self._getFacade(args);
10111
 
 
10112
 
    if (Y.Lang.isObject(args[0])) {
10113
 
        args[0] = ef;
10114
 
    } else {
10115
 
        args.unshift(ef);
10116
 
    }
10117
 
 
10118
 
    // if (subCount) {
10119
 
    if (subs[0]) {
10120
 
        // self._procSubs(Y.merge(self.subscribers), args, ef);
10121
 
        self._procSubs(subs[0], args, ef);
10122
 
    }
10123
 
 
10124
 
    // bubble if this is hosted in an event target and propagation has not been stopped
10125
 
    if (self.bubbles && host.bubble && !self.stopped) {
10126
 
 
10127
 
        oldbubble = es.bubbling;
10128
 
 
10129
 
        // self.bubbling = true;
10130
 
        es.bubbling = self.type;
10131
 
 
10132
 
        // if (host !== ef.target || es.type != self.type) {
10133
 
        if (es.type != self.type) {
10134
 
            es.stopped = 0;
10135
 
            es.prevented = 0;
10136
 
        }
10137
 
 
10138
 
        ret = host.bubble(self, args, null, es);
10139
 
 
10140
 
        self.stopped = Math.max(self.stopped, es.stopped);
10141
 
        self.prevented = Math.max(self.prevented, es.prevented);
10142
 
 
10143
 
        // self.bubbling = false;
10144
 
        es.bubbling = oldbubble;
10145
 
 
10146
 
    }
10147
 
 
10148
 
    if (self.prevented) {
10149
 
        if (self.preventedFn) {
10150
 
            self.preventedFn.apply(host, args);
10151
 
        }
10152
 
    } else if (self.defaultFn &&
10153
 
              ((!self.defaultTargetOnly && !es.defaultTargetOnly) ||
10154
 
                host === ef.target)) {
10155
 
        self.defaultFn.apply(host, args);
10156
 
    }
10157
 
 
10158
 
    // broadcast listeners are fired as discreet events on the
10159
 
    // YUI instance and potentially the YUI global.
10160
 
    self._broadcast(args);
10161
 
 
10162
 
    // Queue the after
10163
 
    if (subs[1] && !self.prevented && self.stopped < 2) {
10164
 
        if (es.id === self.id || self.type != host._yuievt.bubbling) {
10165
 
            self._procSubs(subs[1], args, ef);
10166
 
            while ((next = es.afterQueue.last())) {
10167
 
                next();
10168
 
            }
10169
 
        } else {
10170
 
            postponed = subs[1];
10171
 
            if (es.execDefaultCnt) {
10172
 
                postponed = Y.merge(postponed);
10173
 
                Y.each(postponed, function(s) {
10174
 
                    s.postponed = true;
10175
 
                });
10176
 
            }
10177
 
 
10178
 
            es.afterQueue.add(function() {
10179
 
                self._procSubs(postponed, args, ef);
10180
 
            });
10181
 
        }
10182
 
    }
10183
 
 
10184
 
    self.target = null;
10185
 
 
10186
 
    if (es.id === self.id) {
10187
 
        queue = es.queue;
10188
 
 
10189
 
        while (queue.length) {
10190
 
            q = queue.pop();
10191
 
            ce = q[0];
10192
 
            // set up stack to allow the next item to be processed
10193
 
            es.next = ce;
10194
 
            ce.fire.apply(ce, q[1]);
10195
 
        }
10196
 
 
10197
 
        self.stack = null;
10198
 
    }
10199
 
 
10200
 
    ret = !(self.stopped);
10201
 
 
10202
 
    if (self.type != host._yuievt.bubbling) {
10203
 
        es.stopped = 0;
10204
 
        es.prevented = 0;
10205
 
        self.stopped = 0;
10206
 
        self.prevented = 0;
10207
 
    }
10208
 
 
10209
 
    return ret;
10210
 
};
10211
 
 
10212
 
CEProto._getFacade = function() {
10213
 
 
10214
 
    var ef = this._facade, o, o2,
10215
 
    args = this.details;
10216
 
 
10217
 
    if (!ef) {
10218
 
        ef = new Y.EventFacade(this, this.currentTarget);
10219
 
    }
10220
 
 
10221
 
    // if the first argument is an object literal, apply the
10222
 
    // properties to the event facade
10223
 
    o = args && args[0];
10224
 
 
10225
 
    if (Y.Lang.isObject(o, true)) {
10226
 
 
10227
 
        o2 = {};
10228
 
 
10229
 
        // protect the event facade properties
10230
 
        Y.mix(o2, ef, true, FACADE_KEYS);
10231
 
 
10232
 
        // mix the data
10233
 
        Y.mix(ef, o, true);
10234
 
 
10235
 
        // restore ef
10236
 
        Y.mix(ef, o2, true, FACADE_KEYS);
10237
 
 
10238
 
        // Allow the event type to be faked
10239
 
        // http://yuilibrary.com/projects/yui3/ticket/2528376
10240
 
        ef.type = o.type || ef.type;
10241
 
    }
10242
 
 
10243
 
    // update the details field with the arguments
10244
 
    // ef.type = this.type;
10245
 
    ef.details = this.details;
10246
 
 
10247
 
    // use the original target when the event bubbled to this target
10248
 
    ef.target = this.originalTarget || this.target;
10249
 
 
10250
 
    ef.currentTarget = this.currentTarget;
10251
 
    ef.stopped = 0;
10252
 
    ef.prevented = 0;
10253
 
 
10254
 
    this._facade = ef;
10255
 
 
10256
 
    return this._facade;
10257
 
};
10258
 
 
10259
 
/**
10260
 
 * Stop propagation to bubble targets
10261
 
 * @for CustomEvent
10262
 
 * @method stopPropagation
10263
 
 */
10264
 
CEProto.stopPropagation = function() {
10265
 
    this.stopped = 1;
10266
 
    if (this.stack) {
10267
 
        this.stack.stopped = 1;
10268
 
    }
10269
 
    this.events.fire('stopped', this);
10270
 
};
10271
 
 
10272
 
/**
10273
 
 * Stops propagation to bubble targets, and prevents any remaining
10274
 
 * subscribers on the current target from executing.
10275
 
 * @method stopImmediatePropagation
10276
 
 */
10277
 
CEProto.stopImmediatePropagation = function() {
10278
 
    this.stopped = 2;
10279
 
    if (this.stack) {
10280
 
        this.stack.stopped = 2;
10281
 
    }
10282
 
    this.events.fire('stopped', this);
10283
 
};
10284
 
 
10285
 
/**
10286
 
 * Prevents the execution of this event's defaultFn
10287
 
 * @method preventDefault
10288
 
 */
10289
 
CEProto.preventDefault = function() {
10290
 
    if (this.preventable) {
10291
 
        this.prevented = 1;
10292
 
        if (this.stack) {
10293
 
            this.stack.prevented = 1;
10294
 
        }
10295
 
    }
10296
 
};
10297
 
 
10298
 
/**
10299
 
 * Stops the event propagation and prevents the default
10300
 
 * event behavior.
10301
 
 * @method halt
10302
 
 * @param immediate {boolean} if true additional listeners
10303
 
 * on the current target will not be executed
10304
 
 */
10305
 
CEProto.halt = function(immediate) {
10306
 
    if (immediate) {
10307
 
        this.stopImmediatePropagation();
10308
 
    } else {
10309
 
        this.stopPropagation();
10310
 
    }
10311
 
    this.preventDefault();
10312
 
};
10313
 
 
10314
 
/**
10315
 
 * Registers another EventTarget as a bubble target.  Bubble order
10316
 
 * is determined by the order registered.  Multiple targets can
10317
 
 * be specified.
10318
 
 *
10319
 
 * Events can only bubble if emitFacade is true.
10320
 
 *
10321
 
 * Included in the event-custom-complex submodule.
10322
 
 *
10323
 
 * @method addTarget
10324
 
 * @param o {EventTarget} the target to add
10325
 
 * @for EventTarget
10326
 
 */
10327
 
ETProto.addTarget = function(o) {
10328
 
    this._yuievt.targets[Y.stamp(o)] = o;
10329
 
    this._yuievt.hasTargets = true;
10330
 
};
10331
 
 
10332
 
/**
10333
 
 * Returns an array of bubble targets for this object.
10334
 
 * @method getTargets
10335
 
 * @return EventTarget[]
10336
 
 */
10337
 
ETProto.getTargets = function() {
10338
 
    return Y.Object.values(this._yuievt.targets);
10339
 
};
10340
 
 
10341
 
/**
10342
 
 * Removes a bubble target
10343
 
 * @method removeTarget
10344
 
 * @param o {EventTarget} the target to remove
10345
 
 * @for EventTarget
10346
 
 */
10347
 
ETProto.removeTarget = function(o) {
10348
 
    delete this._yuievt.targets[Y.stamp(o)];
10349
 
};
10350
 
 
10351
 
/**
10352
 
 * Propagate an event.  Requires the event-custom-complex module.
10353
 
 * @method bubble
10354
 
 * @param evt {CustomEvent} the custom event to propagate
10355
 
 * @return {boolean} the aggregated return value from Event.Custom.fire
10356
 
 * @for EventTarget
10357
 
 */
10358
 
ETProto.bubble = function(evt, args, target, es) {
10359
 
 
10360
 
    var targs = this._yuievt.targets, ret = true,
10361
 
        t, type = evt && evt.type, ce, i, bc, ce2,
10362
 
        originalTarget = target || (evt && evt.target) || this,
10363
 
        oldbubble;
10364
 
 
10365
 
    if (!evt || ((!evt.stopped) && targs)) {
10366
 
 
10367
 
        // Y.log('Bubbling ' + evt.type);
10368
 
        for (i in targs) {
10369
 
            if (targs.hasOwnProperty(i)) {
10370
 
                t = targs[i];
10371
 
                ce = t.getEvent(type, true);
10372
 
                ce2 = t.getSibling(type, ce);
10373
 
 
10374
 
                if (ce2 && !ce) {
10375
 
                    ce = t.publish(type);
10376
 
                }
10377
 
 
10378
 
                oldbubble = t._yuievt.bubbling;
10379
 
                t._yuievt.bubbling = type;
10380
 
 
10381
 
                // if this event was not published on the bubble target,
10382
 
                // continue propagating the event.
10383
 
                if (!ce) {
10384
 
                    if (t._yuievt.hasTargets) {
10385
 
                        t.bubble(evt, args, originalTarget, es);
10386
 
                    }
10387
 
                } else {
10388
 
 
10389
 
                    ce.sibling = ce2;
10390
 
 
10391
 
                    // set the original target to that the target payload on the
10392
 
                    // facade is correct.
10393
 
                    ce.target = originalTarget;
10394
 
                    ce.originalTarget = originalTarget;
10395
 
                    ce.currentTarget = t;
10396
 
                    bc = ce.broadcast;
10397
 
                    ce.broadcast = false;
10398
 
 
10399
 
                    // default publish may not have emitFacade true -- that
10400
 
                    // shouldn't be what the implementer meant to do
10401
 
                    ce.emitFacade = true;
10402
 
 
10403
 
                    ce.stack = es;
10404
 
 
10405
 
                    ret = ret && ce.fire.apply(ce, args || evt.details || []);
10406
 
                    ce.broadcast = bc;
10407
 
                    ce.originalTarget = null;
10408
 
 
10409
 
 
10410
 
                    // stopPropagation() was called
10411
 
                    if (ce.stopped) {
10412
 
                        break;
10413
 
                    }
10414
 
                }
10415
 
 
10416
 
                t._yuievt.bubbling = oldbubble;
10417
 
            }
10418
 
        }
10419
 
    }
10420
 
 
10421
 
    return ret;
10422
 
};
10423
 
 
10424
 
FACADE = new Y.EventFacade();
10425
 
FACADE_KEYS = Y.Object.keys(FACADE);
10426
 
 
10427
 
 
10428
 
 
10429
 
}, '3.4.1' ,{requires:['event-custom-base']});
10430
 
YUI.add('node-core', function(Y) {
10431
 
 
10432
 
/**
10433
 
 * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
10434
 
 * @module node
10435
 
 * @submodule node-core
10436
 
 */
10437
 
 
10438
 
/**
10439
 
 * The Node class provides a wrapper for manipulating DOM Nodes.
10440
 
 * Node properties can be accessed via the set/get methods.
10441
 
 * Use `Y.one()` to retrieve Node instances.
10442
 
 *
10443
 
 * <strong>NOTE:</strong> Node properties are accessed using
10444
 
 * the <code>set</code> and <code>get</code> methods.
10445
 
 *
10446
 
 * @class Node
10447
 
 * @constructor
10448
 
 * @param {DOMNode} node the DOM node to be mapped to the Node instance.
10449
 
 * @uses EventTarget
10450
 
 */
10451
 
 
10452
 
// "globals"
10453
 
var DOT = '.',
10454
 
    NODE_NAME = 'nodeName',
10455
 
    NODE_TYPE = 'nodeType',
10456
 
    OWNER_DOCUMENT = 'ownerDocument',
10457
 
    TAG_NAME = 'tagName',
10458
 
    UID = '_yuid',
10459
 
    EMPTY_OBJ = {},
10460
 
 
10461
 
    _slice = Array.prototype.slice,
10462
 
 
10463
 
    Y_DOM = Y.DOM,
10464
 
 
10465
 
    Y_Node = function(node) {
10466
 
        if (!this.getDOMNode) { // support optional "new"
10467
 
            return new Y_Node(node);
10468
 
        }
10469
 
 
10470
 
        if (typeof node == 'string') {
10471
 
            node = Y_Node._fromString(node);
10472
 
            if (!node) {
10473
 
                return null; // NOTE: return
10474
 
            }
10475
 
        }
10476
 
 
10477
 
        var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID];
10478
 
 
10479
 
        if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) {
10480
 
            node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
10481
 
        }
10482
 
 
10483
 
        uid = uid || Y.stamp(node);
10484
 
        if (!uid) { // stamp failed; likely IE non-HTMLElement
10485
 
            uid = Y.guid();
10486
 
        }
10487
 
 
10488
 
        this[UID] = uid;
10489
 
 
10490
 
        /**
10491
 
         * The underlying DOM node bound to the Y.Node instance
10492
 
         * @property _node
10493
 
         * @private
10494
 
         */
10495
 
        this._node = node;
10496
 
 
10497
 
        this._stateProxy = node; // when augmented with Attribute
10498
 
 
10499
 
        if (this._initPlugins) { // when augmented with Plugin.Host
10500
 
            this._initPlugins();
10501
 
        }
10502
 
    },
10503
 
 
10504
 
    // used with previous/next/ancestor tests
10505
 
    _wrapFn = function(fn) {
10506
 
        var ret = null;
10507
 
        if (fn) {
10508
 
            ret = (typeof fn == 'string') ?
10509
 
            function(n) {
10510
 
                return Y.Selector.test(n, fn);
10511
 
            } :
10512
 
            function(n) {
10513
 
                return fn(Y.one(n));
10514
 
            };
10515
 
        }
10516
 
 
10517
 
        return ret;
10518
 
    };
10519
 
// end "globals"
10520
 
 
10521
 
Y_Node.ATTRS = {};
10522
 
Y_Node.DOM_EVENTS = {};
10523
 
 
10524
 
Y_Node._fromString = function(node) {
10525
 
    if (node) {
10526
 
        if (node.indexOf('doc') === 0) { // doc OR document
10527
 
            node = Y.config.doc;
10528
 
        } else if (node.indexOf('win') === 0) { // win OR window
10529
 
            node = Y.config.win;
10530
 
        } else {
10531
 
            node = Y.Selector.query(node, null, true);
10532
 
        }
10533
 
    }
10534
 
 
10535
 
    return node || null;
10536
 
};
10537
 
 
10538
 
/**
10539
 
 * The name of the component
10540
 
 * @static
10541
 
 * @property NAME
10542
 
 */
10543
 
Y_Node.NAME = 'node';
10544
 
 
10545
 
/*
10546
 
 * The pattern used to identify ARIA attributes
10547
 
 */
10548
 
Y_Node.re_aria = /^(?:role$|aria-)/;
10549
 
 
10550
 
Y_Node.SHOW_TRANSITION = 'fadeIn';
10551
 
Y_Node.HIDE_TRANSITION = 'fadeOut';
10552
 
 
10553
 
/**
10554
 
 * A list of Node instances that have been created
10555
 
 * @private
10556
 
 * @property _instances
10557
 
 * @static
10558
 
 *
10559
 
 */
10560
 
Y_Node._instances = {};
10561
 
 
10562
 
/**
10563
 
 * Retrieves the DOM node bound to a Node instance
10564
 
 * @method getDOMNode
10565
 
 * @static
10566
 
 *
10567
 
 * @param {Y.Node || HTMLNode} node The Node instance or an HTMLNode
10568
 
 * @return {HTMLNode} The DOM node bound to the Node instance.  If a DOM node is passed
10569
 
 * as the node argument, it is simply returned.
10570
 
 */
10571
 
Y_Node.getDOMNode = function(node) {
10572
 
    if (node) {
10573
 
        return (node.nodeType) ? node : node._node || null;
10574
 
    }
10575
 
    return null;
10576
 
};
10577
 
 
10578
 
/**
10579
 
 * Checks Node return values and wraps DOM Nodes as Y.Node instances
10580
 
 * and DOM Collections / Arrays as Y.NodeList instances.
10581
 
 * Other return values just pass thru.  If undefined is returned (e.g. no return)
10582
 
 * then the Node instance is returned for chainability.
10583
 
 * @method scrubVal
10584
 
 * @static
10585
 
 *
10586
 
 * @param {any} node The Node instance or an HTMLNode
10587
 
 * @return {Y.Node | Y.NodeList | any} Depends on what is returned from the DOM node.
10588
 
 */
10589
 
Y_Node.scrubVal = function(val, node) {
10590
 
    if (val) { // only truthy values are risky
10591
 
         if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function
10592
 
            if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window
10593
 
                val = Y.one(val);
10594
 
            } else if ((val.item && !val._nodes) || // dom collection or Node instance
10595
 
                    (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
10596
 
                val = Y.all(val);
10597
 
            }
10598
 
        }
10599
 
    } else if (typeof val === 'undefined') {
10600
 
        val = node; // for chaining
10601
 
    } else if (val === null) {
10602
 
        val = null; // IE: DOM null not the same as null
10603
 
    }
10604
 
 
10605
 
    return val;
10606
 
};
10607
 
 
10608
 
/**
10609
 
 * Adds methods to the Y.Node prototype, routing through scrubVal.
10610
 
 * @method addMethod
10611
 
 * @static
10612
 
 *
10613
 
 * @param {String} name The name of the method to add
10614
 
 * @param {Function} fn The function that becomes the method
10615
 
 * @param {Object} context An optional context to call the method with
10616
 
 * (defaults to the Node instance)
10617
 
 * @return {any} Depends on what is returned from the DOM node.
10618
 
 */
10619
 
Y_Node.addMethod = function(name, fn, context) {
10620
 
    if (name && fn && typeof fn == 'function') {
10621
 
        Y_Node.prototype[name] = function() {
10622
 
            var args = _slice.call(arguments),
10623
 
                node = this,
10624
 
                ret;
10625
 
 
10626
 
            if (args[0] && Y.instanceOf(args[0], Y_Node)) {
10627
 
                args[0] = args[0]._node;
10628
 
            }
10629
 
 
10630
 
            if (args[1] && Y.instanceOf(args[1], Y_Node)) {
10631
 
                args[1] = args[1]._node;
10632
 
            }
10633
 
            args.unshift(node._node);
10634
 
 
10635
 
            ret = fn.apply(node, args);
10636
 
 
10637
 
            if (ret) { // scrub truthy
10638
 
                ret = Y_Node.scrubVal(ret, node);
10639
 
            }
10640
 
 
10641
 
            (typeof ret != 'undefined') || (ret = node);
10642
 
            return ret;
10643
 
        };
10644
 
    } else {
10645
 
        Y.log('unable to add method: ' + name, 'warn', 'Node');
10646
 
    }
10647
 
};
10648
 
 
10649
 
/**
10650
 
 * Imports utility methods to be added as Y.Node methods.
10651
 
 * @method importMethod
10652
 
 * @static
10653
 
 *
10654
 
 * @param {Object} host The object that contains the method to import.
10655
 
 * @param {String} name The name of the method to import
10656
 
 * @param {String} altName An optional name to use in place of the host name
10657
 
 * @param {Object} context An optional context to call the method with
10658
 
 */
10659
 
Y_Node.importMethod = function(host, name, altName) {
10660
 
    if (typeof name == 'string') {
10661
 
        altName = altName || name;
10662
 
        Y_Node.addMethod(altName, host[name], host);
10663
 
    } else {
10664
 
        Y.Array.each(name, function(n) {
10665
 
            Y_Node.importMethod(host, n);
10666
 
        });
10667
 
    }
10668
 
};
10669
 
 
10670
 
/**
10671
 
 * Retrieves a NodeList based on the given CSS selector.
10672
 
 * @method all
10673
 
 *
10674
 
 * @param {string} selector The CSS selector to test against.
10675
 
 * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
10676
 
 * @for YUI
10677
 
 */
10678
 
 
10679
 
/**
10680
 
 * Returns a single Node instance bound to the node or the
10681
 
 * first element matching the given selector. Returns null if no match found.
10682
 
 * <strong>Note:</strong> For chaining purposes you may want to
10683
 
 * use <code>Y.all</code>, which returns a NodeList when no match is found.
10684
 
 * @method one
10685
 
 * @param {String | HTMLElement} node a node or Selector
10686
 
 * @return {Y.Node | null} a Node instance or null if no match found.
10687
 
 * @for YUI
10688
 
 */
10689
 
 
10690
 
/**
10691
 
 * Returns a single Node instance bound to the node or the
10692
 
 * first element matching the given selector. Returns null if no match found.
10693
 
 * <strong>Note:</strong> For chaining purposes you may want to
10694
 
 * use <code>Y.all</code>, which returns a NodeList when no match is found.
10695
 
 * @method one
10696
 
 * @static
10697
 
 * @param {String | HTMLElement} node a node or Selector
10698
 
 * @return {Y.Node | null} a Node instance or null if no match found.
10699
 
 * @for Node
10700
 
 */
10701
 
Y_Node.one = function(node) {
10702
 
    var instance = null,
10703
 
        cachedNode,
10704
 
        uid;
10705
 
 
10706
 
    if (node) {
10707
 
        if (typeof node == 'string') {
10708
 
            node = Y_Node._fromString(node);
10709
 
            if (!node) {
10710
 
                return null; // NOTE: return
10711
 
            }
10712
 
        } else if (node.getDOMNode) {
10713
 
            return node; // NOTE: return
10714
 
        }
10715
 
 
10716
 
        if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc)
10717
 
            uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid;
10718
 
            instance = Y_Node._instances[uid]; // reuse exising instances
10719
 
            cachedNode = instance ? instance._node : null;
10720
 
            if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
10721
 
                instance = new Y_Node(node);
10722
 
                if (node.nodeType != 11) { // dont cache document fragment
10723
 
                    Y_Node._instances[instance[UID]] = instance; // cache node
10724
 
                }
10725
 
            }
10726
 
        }
10727
 
    }
10728
 
 
10729
 
    return instance;
10730
 
};
10731
 
 
10732
 
/**
10733
 
 * The default setter for DOM properties
10734
 
 * Called with instance context (this === the Node instance)
10735
 
 * @method DEFAULT_SETTER
10736
 
 * @static
10737
 
 * @param {String} name The attribute/property being set
10738
 
 * @param {any} val The value to be set
10739
 
 * @return {any} The value
10740
 
 */
10741
 
Y_Node.DEFAULT_SETTER = function(name, val) {
10742
 
    var node = this._stateProxy,
10743
 
        strPath;
10744
 
 
10745
 
    if (name.indexOf(DOT) > -1) {
10746
 
        strPath = name;
10747
 
        name = name.split(DOT);
10748
 
        // only allow when defined on node
10749
 
        Y.Object.setValue(node, name, val);
10750
 
    } else if (typeof node[name] != 'undefined') { // pass thru DOM properties
10751
 
        node[name] = val;
10752
 
    }
10753
 
 
10754
 
    return val;
10755
 
};
10756
 
 
10757
 
/**
10758
 
 * The default getter for DOM properties
10759
 
 * Called with instance context (this === the Node instance)
10760
 
 * @method DEFAULT_GETTER
10761
 
 * @static
10762
 
 * @param {String} name The attribute/property to look up
10763
 
 * @return {any} The current value
10764
 
 */
10765
 
Y_Node.DEFAULT_GETTER = function(name) {
10766
 
    var node = this._stateProxy,
10767
 
        val;
10768
 
 
10769
 
    if (name.indexOf && name.indexOf(DOT) > -1) {
10770
 
        val = Y.Object.getValue(node, name.split(DOT));
10771
 
    } else if (typeof node[name] != 'undefined') { // pass thru from DOM
10772
 
        val = node[name];
10773
 
    }
10774
 
 
10775
 
    return val;
10776
 
};
10777
 
 
10778
 
Y.mix(Y_Node.prototype, {
10779
 
    /**
10780
 
     * The method called when outputting Node instances as strings
10781
 
     * @method toString
10782
 
     * @return {String} A string representation of the Node instance
10783
 
     */
10784
 
    toString: function() {
10785
 
        var str = this[UID] + ': not bound to a node',
10786
 
            node = this._node,
10787
 
            attrs, id, className;
10788
 
 
10789
 
        if (node) {
10790
 
            attrs = node.attributes;
10791
 
            id = (attrs && attrs.id) ? node.getAttribute('id') : null;
10792
 
            className = (attrs && attrs.className) ? node.getAttribute('className') : null;
10793
 
            str = node[NODE_NAME];
10794
 
 
10795
 
            if (id) {
10796
 
                str += '#' + id;
10797
 
            }
10798
 
 
10799
 
            if (className) {
10800
 
                str += '.' + className.replace(' ', '.');
10801
 
            }
10802
 
 
10803
 
            // TODO: add yuid?
10804
 
            str += ' ' + this[UID];
10805
 
        }
10806
 
        return str;
10807
 
    },
10808
 
 
10809
 
    /**
10810
 
     * Returns an attribute value on the Node instance.
10811
 
     * Unless pre-configured (via `Node.ATTRS`), get hands
10812
 
     * off to the underlying DOM node.  Only valid
10813
 
     * attributes/properties for the node will be queried.
10814
 
     * @method get
10815
 
     * @param {String} attr The attribute
10816
 
     * @return {any} The current value of the attribute
10817
 
     */
10818
 
    get: function(attr) {
10819
 
        var val;
10820
 
 
10821
 
        if (this._getAttr) { // use Attribute imple
10822
 
            val = this._getAttr(attr);
10823
 
        } else {
10824
 
            val = this._get(attr);
10825
 
        }
10826
 
 
10827
 
        if (val) {
10828
 
            val = Y_Node.scrubVal(val, this);
10829
 
        } else if (val === null) {
10830
 
            val = null; // IE: DOM null is not true null (even though they ===)
10831
 
        }
10832
 
        return val;
10833
 
    },
10834
 
 
10835
 
    /**
10836
 
     * Helper method for get.
10837
 
     * @method _get
10838
 
     * @private
10839
 
     * @param {String} attr The attribute
10840
 
     * @return {any} The current value of the attribute
10841
 
     */
10842
 
    _get: function(attr) {
10843
 
        var attrConfig = Y_Node.ATTRS[attr],
10844
 
            val;
10845
 
 
10846
 
        if (attrConfig && attrConfig.getter) {
10847
 
            val = attrConfig.getter.call(this);
10848
 
        } else if (Y_Node.re_aria.test(attr)) {
10849
 
            val = this._node.getAttribute(attr, 2);
10850
 
        } else {
10851
 
            val = Y_Node.DEFAULT_GETTER.apply(this, arguments);
10852
 
        }
10853
 
 
10854
 
        return val;
10855
 
    },
10856
 
 
10857
 
    /**
10858
 
     * Sets an attribute on the Node instance.
10859
 
     * Unless pre-configured (via Node.ATTRS), set hands
10860
 
     * off to the underlying DOM node.  Only valid
10861
 
     * attributes/properties for the node will be set.
10862
 
     * To set custom attributes use setAttribute.
10863
 
     * @method set
10864
 
     * @param {String} attr The attribute to be set.
10865
 
     * @param {any} val The value to set the attribute to.
10866
 
     * @chainable
10867
 
     */
10868
 
    set: function(attr, val) {
10869
 
        var attrConfig = Y_Node.ATTRS[attr];
10870
 
 
10871
 
        if (this._setAttr) { // use Attribute imple
10872
 
            this._setAttr.apply(this, arguments);
10873
 
        } else { // use setters inline
10874
 
            if (attrConfig && attrConfig.setter) {
10875
 
                attrConfig.setter.call(this, val, attr);
10876
 
            } else if (Y_Node.re_aria.test(attr)) { // special case Aria
10877
 
                this._node.setAttribute(attr, val);
10878
 
            } else {
10879
 
                Y_Node.DEFAULT_SETTER.apply(this, arguments);
10880
 
            }
10881
 
        }
10882
 
 
10883
 
        return this;
10884
 
    },
10885
 
 
10886
 
    /**
10887
 
     * Sets multiple attributes.
10888
 
     * @method setAttrs
10889
 
     * @param {Object} attrMap an object of name/value pairs to set
10890
 
     * @chainable
10891
 
     */
10892
 
    setAttrs: function(attrMap) {
10893
 
        if (this._setAttrs) { // use Attribute imple
10894
 
            this._setAttrs(attrMap);
10895
 
        } else { // use setters inline
10896
 
            Y.Object.each(attrMap, function(v, n) {
10897
 
                this.set(n, v);
10898
 
            }, this);
10899
 
        }
10900
 
 
10901
 
        return this;
10902
 
    },
10903
 
 
10904
 
    /**
10905
 
     * Returns an object containing the values for the requested attributes.
10906
 
     * @method getAttrs
10907
 
     * @param {Array} attrs an array of attributes to get values
10908
 
     * @return {Object} An object with attribute name/value pairs.
10909
 
     */
10910
 
    getAttrs: function(attrs) {
10911
 
        var ret = {};
10912
 
        if (this._getAttrs) { // use Attribute imple
10913
 
            this._getAttrs(attrs);
10914
 
        } else { // use setters inline
10915
 
            Y.Array.each(attrs, function(v, n) {
10916
 
                ret[v] = this.get(v);
10917
 
            }, this);
10918
 
        }
10919
 
 
10920
 
        return ret;
10921
 
    },
10922
 
 
10923
 
    /**
10924
 
     * Compares nodes to determine if they match.
10925
 
     * Node instances can be compared to each other and/or HTMLElements.
10926
 
     * @method compareTo
10927
 
     * @param {HTMLElement | Node} refNode The reference node to compare to the node.
10928
 
     * @return {Boolean} True if the nodes match, false if they do not.
10929
 
     */
10930
 
    compareTo: function(refNode) {
10931
 
        var node = this._node;
10932
 
 
10933
 
        if (Y.instanceOf(refNode, Y_Node)) {
10934
 
            refNode = refNode._node;
10935
 
        }
10936
 
        return node === refNode;
10937
 
    },
10938
 
 
10939
 
    /**
10940
 
     * Determines whether the node is appended to the document.
10941
 
     * @method inDoc
10942
 
     * @param {Node|HTMLElement} doc optional An optional document to check against.
10943
 
     * Defaults to current document.
10944
 
     * @return {Boolean} Whether or not this node is appended to the document.
10945
 
     */
10946
 
    inDoc: function(doc) {
10947
 
        var node = this._node;
10948
 
        doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
10949
 
        if (doc.documentElement) {
10950
 
            return Y_DOM.contains(doc.documentElement, node);
10951
 
        }
10952
 
    },
10953
 
 
10954
 
    getById: function(id) {
10955
 
        var node = this._node,
10956
 
            ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]);
10957
 
        if (ret && Y_DOM.contains(node, ret)) {
10958
 
            ret = Y.one(ret);
10959
 
        } else {
10960
 
            ret = null;
10961
 
        }
10962
 
        return ret;
10963
 
    },
10964
 
 
10965
 
   /**
10966
 
     * Returns the nearest ancestor that passes the test applied by supplied boolean method.
10967
 
     * @method ancestor
10968
 
     * @param {String | Function} fn A selector string or boolean method for testing elements.
10969
 
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan
10970
 
     * If a function is used, it receives the current node being tested as the only argument.
10971
 
     * @return {Node} The matching Node instance or null if not found
10972
 
     */
10973
 
    ancestor: function(fn, testSelf) {
10974
 
        return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf));
10975
 
    },
10976
 
 
10977
 
   /**
10978
 
     * Returns the ancestors that pass the test applied by supplied boolean method.
10979
 
     * @method ancestors
10980
 
     * @param {String | Function} fn A selector string or boolean method for testing elements.
10981
 
     * @param {Boolean} testSelf optional Whether or not to include the element in the scan
10982
 
     * If a function is used, it receives the current node being tested as the only argument.
10983
 
     * @return {NodeList} A NodeList instance containing the matching elements
10984
 
     */
10985
 
    ancestors: function(fn, testSelf) {
10986
 
        return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf));
10987
 
    },
10988
 
 
10989
 
    /**
10990
 
     * Returns the previous matching sibling.
10991
 
     * Returns the nearest element node sibling if no method provided.
10992
 
     * @method previous
10993
 
     * @param {String | Function} fn A selector or boolean method for testing elements.
10994
 
     * If a function is used, it receives the current node being tested as the only argument.
10995
 
     * @return {Node} Node instance or null if not found
10996
 
     */
10997
 
    previous: function(fn, all) {
10998
 
        return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
10999
 
    },
11000
 
 
11001
 
    /**
11002
 
     * Returns the next matching sibling.
11003
 
     * Returns the nearest element node sibling if no method provided.
11004
 
     * @method next
11005
 
     * @param {String | Function} fn A selector or boolean method for testing elements.
11006
 
     * If a function is used, it receives the current node being tested as the only argument.
11007
 
     * @return {Node} Node instance or null if not found
11008
 
     */
11009
 
    next: function(fn, all) {
11010
 
        return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
11011
 
    },
11012
 
 
11013
 
    /**
11014
 
     * Returns all matching siblings.
11015
 
     * Returns all siblings if no method provided.
11016
 
     * @method siblings
11017
 
     * @param {String | Function} fn A selector or boolean method for testing elements.
11018
 
     * If a function is used, it receives the current node being tested as the only argument.
11019
 
     * @return {NodeList} NodeList instance bound to found siblings
11020
 
     */
11021
 
    siblings: function(fn) {
11022
 
        return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn)));
11023
 
    },
11024
 
 
11025
 
    /**
11026
 
     * Retrieves a Node instance of nodes based on the given CSS selector.
11027
 
     * @method one
11028
 
     *
11029
 
     * @param {string} selector The CSS selector to test against.
11030
 
     * @return {Node} A Node instance for the matching HTMLElement.
11031
 
     */
11032
 
    one: function(selector) {
11033
 
        return Y.one(Y.Selector.query(selector, this._node, true));
11034
 
    },
11035
 
 
11036
 
    /**
11037
 
     * Retrieves a NodeList based on the given CSS selector.
11038
 
     * @method all
11039
 
     *
11040
 
     * @param {string} selector The CSS selector to test against.
11041
 
     * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
11042
 
     */
11043
 
    all: function(selector) {
11044
 
        var nodelist = Y.all(Y.Selector.query(selector, this._node));
11045
 
        nodelist._query = selector;
11046
 
        nodelist._queryRoot = this._node;
11047
 
        return nodelist;
11048
 
    },
11049
 
 
11050
 
    // TODO: allow fn test
11051
 
    /**
11052
 
     * Test if the supplied node matches the supplied selector.
11053
 
     * @method test
11054
 
     *
11055
 
     * @param {string} selector The CSS selector to test against.
11056
 
     * @return {boolean} Whether or not the node matches the selector.
11057
 
     */
11058
 
    test: function(selector) {
11059
 
        return Y.Selector.test(this._node, selector);
11060
 
    },
11061
 
 
11062
 
    /**
11063
 
     * Removes the node from its parent.
11064
 
     * Shortcut for myNode.get('parentNode').removeChild(myNode);
11065
 
     * @method remove
11066
 
     * @param {Boolean} destroy whether or not to call destroy() on the node
11067
 
     * after removal.
11068
 
     * @chainable
11069
 
     *
11070
 
     */
11071
 
    remove: function(destroy) {
11072
 
        var node = this._node;
11073
 
 
11074
 
        if (node && node.parentNode) {
11075
 
            node.parentNode.removeChild(node);
11076
 
        }
11077
 
 
11078
 
        if (destroy) {
11079
 
            this.destroy();
11080
 
        }
11081
 
 
11082
 
        return this;
11083
 
    },
11084
 
 
11085
 
    /**
11086
 
     * Replace the node with the other node. This is a DOM update only
11087
 
     * and does not change the node bound to the Node instance.
11088
 
     * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
11089
 
     * @method replace
11090
 
     * @param {Y.Node || HTMLNode} newNode Node to be inserted
11091
 
     * @chainable
11092
 
     *
11093
 
     */
11094
 
    replace: function(newNode) {
11095
 
        var node = this._node;
11096
 
        if (typeof newNode == 'string') {
11097
 
            newNode = Y_Node.create(newNode);
11098
 
        }
11099
 
        node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node);
11100
 
        return this;
11101
 
    },
11102
 
 
11103
 
    /**
11104
 
     * @method replaceChild
11105
 
     * @for Node
11106
 
     * @param {String | HTMLElement | Node} node Node to be inserted
11107
 
     * @param {HTMLElement | Node} refNode Node to be replaced
11108
 
     * @return {Node} The replaced node
11109
 
     */
11110
 
    replaceChild: function(node, refNode) {
11111
 
        if (typeof node == 'string') {
11112
 
            node = Y_DOM.create(node);
11113
 
        }
11114
 
 
11115
 
        return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode)));
11116
 
    },
11117
 
 
11118
 
    /**
11119
 
     * Nulls internal node references, removes any plugins and event listeners
11120
 
     * @method destroy
11121
 
     * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the
11122
 
     * node's subtree (default is false)
11123
 
     *
11124
 
     */
11125
 
    destroy: function(recursive) {
11126
 
        var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid',
11127
 
            instance;
11128
 
 
11129
 
        this.purge(); // TODO: only remove events add via this Node
11130
 
 
11131
 
        if (this.unplug) { // may not be a PluginHost
11132
 
            this.unplug();
11133
 
        }
11134
 
 
11135
 
        this.clearData();
11136
 
 
11137
 
        if (recursive) {
11138
 
            Y.NodeList.each(this.all('*'), function(node) {
11139
 
                instance = Y_Node._instances[node[UID]];
11140
 
                if (instance) {
11141
 
                   instance.destroy();
11142
 
                }
11143
 
            });
11144
 
        }
11145
 
 
11146
 
        this._node = null;
11147
 
        this._stateProxy = null;
11148
 
 
11149
 
        delete Y_Node._instances[this._yuid];
11150
 
    },
11151
 
 
11152
 
    /**
11153
 
     * Invokes a method on the Node instance
11154
 
     * @method invoke
11155
 
     * @param {String} method The name of the method to invoke
11156
 
     * @param {Any}  a, b, c, etc. Arguments to invoke the method with.
11157
 
     * @return Whatever the underly method returns.
11158
 
     * DOM Nodes and Collections return values
11159
 
     * are converted to Node/NodeList instances.
11160
 
     *
11161
 
     */
11162
 
    invoke: function(method, a, b, c, d, e) {
11163
 
        var node = this._node,
11164
 
            ret;
11165
 
 
11166
 
        if (a && Y.instanceOf(a, Y_Node)) {
11167
 
            a = a._node;
11168
 
        }
11169
 
 
11170
 
        if (b && Y.instanceOf(b, Y_Node)) {
11171
 
            b = b._node;
11172
 
        }
11173
 
 
11174
 
        ret = node[method](a, b, c, d, e);
11175
 
        return Y_Node.scrubVal(ret, this);
11176
 
    },
11177
 
 
11178
 
    /**
11179
 
    * @method swap
11180
 
    * @description Swap DOM locations with the given node.
11181
 
    * This does not change which DOM node each Node instance refers to.
11182
 
    * @param {Node} otherNode The node to swap with
11183
 
     * @chainable
11184
 
    */
11185
 
    swap: Y.config.doc.documentElement.swapNode ?
11186
 
        function(otherNode) {
11187
 
            this._node.swapNode(Y_Node.getDOMNode(otherNode));
11188
 
        } :
11189
 
        function(otherNode) {
11190
 
            otherNode = Y_Node.getDOMNode(otherNode);
11191
 
            var node = this._node,
11192
 
                parent = otherNode.parentNode,
11193
 
                nextSibling = otherNode.nextSibling;
11194
 
 
11195
 
            if (nextSibling === node) {
11196
 
                parent.insertBefore(node, otherNode);
11197
 
            } else if (otherNode === node.nextSibling) {
11198
 
                parent.insertBefore(otherNode, node);
11199
 
            } else {
11200
 
                node.parentNode.replaceChild(otherNode, node);
11201
 
                Y_DOM.addHTML(parent, node, nextSibling);
11202
 
            }
11203
 
            return this;
11204
 
        },
11205
 
 
11206
 
 
11207
 
    /**
11208
 
    * @method getData
11209
 
    * @description Retrieves arbitrary data stored on a Node instance.
11210
 
    * This is not stored with the DOM node.
11211
 
    * @param {string} name Optional name of the data field to retrieve.
11212
 
    * If no name is given, all data is returned.
11213
 
    * @return {any | Object} Whatever is stored at the given field,
11214
 
    * or an object hash of all fields.
11215
 
    */
11216
 
    getData: function(name) {
11217
 
        var ret;
11218
 
        this._data = this._data || {};
11219
 
        if (arguments.length) {
11220
 
            ret = this._data[name];
11221
 
        } else {
11222
 
            ret = this._data;
11223
 
        }
11224
 
 
11225
 
        return ret;
11226
 
 
11227
 
    },
11228
 
 
11229
 
    /**
11230
 
    * @method setData
11231
 
    * @description Stores arbitrary data on a Node instance.
11232
 
    * This is not stored with the DOM node.
11233
 
    * @param {string} name The name of the field to set. If no name
11234
 
    * is given, name is treated as the data and overrides any existing data.
11235
 
    * @param {any} val The value to be assigned to the field.
11236
 
    * @chainable
11237
 
    */
11238
 
    setData: function(name, val) {
11239
 
        this._data = this._data || {};
11240
 
        if (arguments.length > 1) {
11241
 
            this._data[name] = val;
11242
 
        } else {
11243
 
            this._data = name;
11244
 
        }
11245
 
 
11246
 
       return this;
11247
 
    },
11248
 
 
11249
 
    /**
11250
 
    * @method clearData
11251
 
    * @description Clears stored data.
11252
 
    * @param {string} name The name of the field to clear. If no name
11253
 
    * is given, all data is cleared.
11254
 
    * @chainable
11255
 
    */
11256
 
    clearData: function(name) {
11257
 
        if ('_data' in this) {
11258
 
            if (name) {
11259
 
                delete this._data[name];
11260
 
            } else {
11261
 
                delete this._data;
11262
 
            }
11263
 
        }
11264
 
 
11265
 
        return this;
11266
 
    },
11267
 
 
11268
 
    hasMethod: function(method) {
11269
 
        var node = this._node;
11270
 
        return !!(node && method in node &&
11271
 
                typeof node[method] != 'unknown' &&
11272
 
            (typeof node[method] == 'function' ||
11273
 
                String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space
11274
 
    },
11275
 
 
11276
 
    isFragment: function() {
11277
 
        return (this.get('nodeType') === 11);
11278
 
    },
11279
 
 
11280
 
    /**
11281
 
     * Removes and destroys all of the nodes within the node.
11282
 
     * @method empty
11283
 
     * @chainable
11284
 
     */
11285
 
    empty: function() {
11286
 
        this.get('childNodes').remove().destroy(true);
11287
 
        return this;
11288
 
    },
11289
 
 
11290
 
    /**
11291
 
     * Returns the DOM node bound to the Node instance
11292
 
     * @method getDOMNode
11293
 
     * @return {DOMNode}
11294
 
     */
11295
 
    getDOMNode: function() {
11296
 
        return this._node;
11297
 
    }
11298
 
}, true);
11299
 
 
11300
 
Y.Node = Y_Node;
11301
 
Y.one = Y_Node.one;
11302
 
/**
11303
 
 * The NodeList module provides support for managing collections of Nodes.
11304
 
 * @module node
11305
 
 * @submodule node-core
11306
 
 */
11307
 
 
11308
 
/**
11309
 
 * The NodeList class provides a wrapper for manipulating DOM NodeLists.
11310
 
 * NodeList properties can be accessed via the set/get methods.
11311
 
 * Use Y.all() to retrieve NodeList instances.
11312
 
 *
11313
 
 * @class NodeList
11314
 
 * @constructor
11315
 
 */
11316
 
 
11317
 
var NodeList = function(nodes) {
11318
 
    var tmp = [];
11319
 
    if (typeof nodes === 'string') { // selector query
11320
 
        this._query = nodes;
11321
 
        nodes = Y.Selector.query(nodes);
11322
 
    } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window
11323
 
        nodes = [nodes];
11324
 
    } else if (Y.instanceOf(nodes, Y.Node)) {
11325
 
        nodes = [nodes._node];
11326
 
    } else if (Y.instanceOf(nodes[0], Y.Node)) { // allow array of Y.Nodes
11327
 
        Y.Array.each(nodes, function(node) {
11328
 
            if (node._node) {
11329
 
                tmp.push(node._node);
11330
 
            }
11331
 
        });
11332
 
        nodes = tmp;
11333
 
    } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes)
11334
 
        nodes = Y.Array(nodes, 0, true);
11335
 
    }
11336
 
 
11337
 
    /**
11338
 
     * The underlying array of DOM nodes bound to the Y.NodeList instance
11339
 
     * @property _nodes
11340
 
     * @private
11341
 
     */
11342
 
    this._nodes = nodes;
11343
 
};
11344
 
 
11345
 
NodeList.NAME = 'NodeList';
11346
 
 
11347
 
/**
11348
 
 * Retrieves the DOM nodes bound to a NodeList instance
11349
 
 * @method getDOMNodes
11350
 
 * @static
11351
 
 *
11352
 
 * @param {Y.NodeList} nodelist The NodeList instance
11353
 
 * @return {Array} The array of DOM nodes bound to the NodeList
11354
 
 */
11355
 
NodeList.getDOMNodes = function(nodelist) {
11356
 
    return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist;
11357
 
};
11358
 
 
11359
 
NodeList.each = function(instance, fn, context) {
11360
 
    var nodes = instance._nodes;
11361
 
    if (nodes && nodes.length) {
11362
 
        Y.Array.each(nodes, fn, context || instance);
11363
 
    } else {
11364
 
        Y.log('no nodes bound to ' + this, 'warn', 'NodeList');
11365
 
    }
11366
 
};
11367
 
 
11368
 
NodeList.addMethod = function(name, fn, context) {
11369
 
    if (name && fn) {
11370
 
        NodeList.prototype[name] = function() {
11371
 
            var ret = [],
11372
 
                args = arguments;
11373
 
 
11374
 
            Y.Array.each(this._nodes, function(node) {
11375
 
                var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid',
11376
 
                    instance = Y.Node._instances[node[UID]],
11377
 
                    ctx,
11378
 
                    result;
11379
 
 
11380
 
                if (!instance) {
11381
 
                    instance = NodeList._getTempNode(node);
11382
 
                }
11383
 
                ctx = context || instance;
11384
 
                result = fn.apply(ctx, args);
11385
 
                if (result !== undefined && result !== instance) {
11386
 
                    ret[ret.length] = result;
11387
 
                }
11388
 
            });
11389
 
 
11390
 
            // TODO: remove tmp pointer
11391
 
            return ret.length ? ret : this;
11392
 
        };
11393
 
    } else {
11394
 
        Y.log('unable to add method: ' + name + ' to NodeList', 'warn', 'node');
11395
 
    }
11396
 
};
11397
 
 
11398
 
NodeList.importMethod = function(host, name, altName) {
11399
 
    if (typeof name === 'string') {
11400
 
        altName = altName || name;
11401
 
        NodeList.addMethod(name, host[name]);
11402
 
    } else {
11403
 
        Y.Array.each(name, function(n) {
11404
 
            NodeList.importMethod(host, n);
11405
 
        });
11406
 
    }
11407
 
};
11408
 
 
11409
 
NodeList._getTempNode = function(node) {
11410
 
    var tmp = NodeList._tempNode;
11411
 
    if (!tmp) {
11412
 
        tmp = Y.Node.create('<div></div>');
11413
 
        NodeList._tempNode = tmp;
11414
 
    }
11415
 
 
11416
 
    tmp._node = node;
11417
 
    tmp._stateProxy = node;
11418
 
    return tmp;
11419
 
};
11420
 
 
11421
 
Y.mix(NodeList.prototype, {
11422
 
    /**
11423
 
     * Retrieves the Node instance at the given index.
11424
 
     * @method item
11425
 
     *
11426
 
     * @param {Number} index The index of the target Node.
11427
 
     * @return {Node} The Node instance at the given index.
11428
 
     */
11429
 
    item: function(index) {
11430
 
        return Y.one((this._nodes || [])[index]);
11431
 
    },
11432
 
 
11433
 
    /**
11434
 
     * Applies the given function to each Node in the NodeList.
11435
 
     * @method each
11436
 
     * @param {Function} fn The function to apply. It receives 3 arguments:
11437
 
     * the current node instance, the node's index, and the NodeList instance
11438
 
     * @param {Object} context optional An optional context to apply the function with
11439
 
     * Default context is the current Node instance
11440
 
     * @chainable
11441
 
     */
11442
 
    each: function(fn, context) {
11443
 
        var instance = this;
11444
 
        Y.Array.each(this._nodes, function(node, index) {
11445
 
            node = Y.one(node);
11446
 
            return fn.call(context || node, node, index, instance);
11447
 
        });
11448
 
        return instance;
11449
 
    },
11450
 
 
11451
 
    batch: function(fn, context) {
11452
 
        var nodelist = this;
11453
 
 
11454
 
        Y.Array.each(this._nodes, function(node, index) {
11455
 
            var instance = Y.Node._instances[node[UID]];
11456
 
            if (!instance) {
11457
 
                instance = NodeList._getTempNode(node);
11458
 
            }
11459
 
 
11460
 
            return fn.call(context || instance, instance, index, nodelist);
11461
 
        });
11462
 
        return nodelist;
11463
 
    },
11464
 
 
11465
 
    /**
11466
 
     * Executes the function once for each node until a true value is returned.
11467
 
     * @method some
11468
 
     * @param {Function} fn The function to apply. It receives 3 arguments:
11469
 
     * the current node instance, the node's index, and the NodeList instance
11470
 
     * @param {Object} context optional An optional context to execute the function from.
11471
 
     * Default context is the current Node instance
11472
 
     * @return {Boolean} Whether or not the function returned true for any node.
11473
 
     */
11474
 
    some: function(fn, context) {
11475
 
        var instance = this;
11476
 
        return Y.Array.some(this._nodes, function(node, index) {
11477
 
            node = Y.one(node);
11478
 
            context = context || node;
11479
 
            return fn.call(context, node, index, instance);
11480
 
        });
11481
 
    },
11482
 
 
11483
 
    /**
11484
 
     * Creates a documenFragment from the nodes bound to the NodeList instance
11485
 
     * @method toFrag
11486
 
     * @return Node a Node instance bound to the documentFragment
11487
 
     */
11488
 
    toFrag: function() {
11489
 
        return Y.one(Y.DOM._nl2frag(this._nodes));
11490
 
    },
11491
 
 
11492
 
    /**
11493
 
     * Returns the index of the node in the NodeList instance
11494
 
     * or -1 if the node isn't found.
11495
 
     * @method indexOf
11496
 
     * @param {Y.Node || DOMNode} node the node to search for
11497
 
     * @return {Int} the index of the node value or -1 if not found
11498
 
     */
11499
 
    indexOf: function(node) {
11500
 
        return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
11501
 
    },
11502
 
 
11503
 
    /**
11504
 
     * Filters the NodeList instance down to only nodes matching the given selector.
11505
 
     * @method filter
11506
 
     * @param {String} selector The selector to filter against
11507
 
     * @return {NodeList} NodeList containing the updated collection
11508
 
     * @see Selector
11509
 
     */
11510
 
    filter: function(selector) {
11511
 
        return Y.all(Y.Selector.filter(this._nodes, selector));
11512
 
    },
11513
 
 
11514
 
 
11515
 
    /**
11516
 
     * Creates a new NodeList containing all nodes at every n indices, where
11517
 
     * remainder n % index equals r.
11518
 
     * (zero-based index).
11519
 
     * @method modulus
11520
 
     * @param {Int} n The offset to use (return every nth node)
11521
 
     * @param {Int} r An optional remainder to use with the modulus operation (defaults to zero)
11522
 
     * @return {NodeList} NodeList containing the updated collection
11523
 
     */
11524
 
    modulus: function(n, r) {
11525
 
        r = r || 0;
11526
 
        var nodes = [];
11527
 
        NodeList.each(this, function(node, i) {
11528
 
            if (i % n === r) {
11529
 
                nodes.push(node);
11530
 
            }
11531
 
        });
11532
 
 
11533
 
        return Y.all(nodes);
11534
 
    },
11535
 
 
11536
 
    /**
11537
 
     * Creates a new NodeList containing all nodes at odd indices
11538
 
     * (zero-based index).
11539
 
     * @method odd
11540
 
     * @return {NodeList} NodeList containing the updated collection
11541
 
     */
11542
 
    odd: function() {
11543
 
        return this.modulus(2, 1);
11544
 
    },
11545
 
 
11546
 
    /**
11547
 
     * Creates a new NodeList containing all nodes at even indices
11548
 
     * (zero-based index), including zero.
11549
 
     * @method even
11550
 
     * @return {NodeList} NodeList containing the updated collection
11551
 
     */
11552
 
    even: function() {
11553
 
        return this.modulus(2);
11554
 
    },
11555
 
 
11556
 
    destructor: function() {
11557
 
    },
11558
 
 
11559
 
    /**
11560
 
     * Reruns the initial query, when created using a selector query
11561
 
     * @method refresh
11562
 
     * @chainable
11563
 
     */
11564
 
    refresh: function() {
11565
 
        var doc,
11566
 
            nodes = this._nodes,
11567
 
            query = this._query,
11568
 
            root = this._queryRoot;
11569
 
 
11570
 
        if (query) {
11571
 
            if (!root) {
11572
 
                if (nodes && nodes[0] && nodes[0].ownerDocument) {
11573
 
                    root = nodes[0].ownerDocument;
11574
 
                }
11575
 
            }
11576
 
 
11577
 
            this._nodes = Y.Selector.query(query, root);
11578
 
        }
11579
 
 
11580
 
        return this;
11581
 
    },
11582
 
 
11583
 
    _prepEvtArgs: function(type, fn, context) {
11584
 
        // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
11585
 
        var args = Y.Array(arguments, 0, true);
11586
 
 
11587
 
        if (args.length < 2) { // type only (event hash) just add nodes
11588
 
            args[2] = this._nodes;
11589
 
        } else {
11590
 
            args.splice(2, 0, this._nodes);
11591
 
        }
11592
 
 
11593
 
        args[3] = context || this; // default to NodeList instance as context
11594
 
 
11595
 
        return args;
11596
 
    },
11597
 
 
11598
 
    /**
11599
 
     * Applies an event listener to each Node bound to the NodeList.
11600
 
     * @method on
11601
 
     * @param {String} type The event being listened for
11602
 
     * @param {Function} fn The handler to call when the event fires
11603
 
     * @param {Object} context The context to call the handler with.
11604
 
     * Default is the NodeList instance.
11605
 
     * @param {Object} context The context to call the handler with.
11606
 
     * param {mixed} arg* 0..n additional arguments to supply to the subscriber
11607
 
     * when the event fires.
11608
 
     * @return {Object} Returns an event handle that can later be use to detach().
11609
 
     * @see Event.on
11610
 
     */
11611
 
    on: function(type, fn, context) {
11612
 
        return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
11613
 
    },
11614
 
 
11615
 
    /**
11616
 
     * Applies an one-time event listener to each Node bound to the NodeList.
11617
 
     * @method once
11618
 
     * @param {String} type The event being listened for
11619
 
     * @param {Function} fn The handler to call when the event fires
11620
 
     * @param {Object} context The context to call the handler with.
11621
 
     * Default is the NodeList instance.
11622
 
     * @return {Object} Returns an event handle that can later be use to detach().
11623
 
     * @see Event.on
11624
 
     */
11625
 
    once: function(type, fn, context) {
11626
 
        return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
11627
 
    },
11628
 
 
11629
 
    /**
11630
 
     * Applies an event listener to each Node bound to the NodeList.
11631
 
     * The handler is called only after all on() handlers are called
11632
 
     * and the event is not prevented.
11633
 
     * @method after
11634
 
     * @param {String} type The event being listened for
11635
 
     * @param {Function} fn The handler to call when the event fires
11636
 
     * @param {Object} context The context to call the handler with.
11637
 
     * Default is the NodeList instance.
11638
 
     * @return {Object} Returns an event handle that can later be use to detach().
11639
 
     * @see Event.on
11640
 
     */
11641
 
    after: function(type, fn, context) {
11642
 
        return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
11643
 
    },
11644
 
 
11645
 
    /**
11646
 
     * Returns the current number of items in the NodeList.
11647
 
     * @method size
11648
 
     * @return {Int} The number of items in the NodeList.
11649
 
     */
11650
 
    size: function() {
11651
 
        return this._nodes.length;
11652
 
    },
11653
 
 
11654
 
    /**
11655
 
     * Determines if the instance is bound to any nodes
11656
 
     * @method isEmpty
11657
 
     * @return {Boolean} Whether or not the NodeList is bound to any nodes
11658
 
     */
11659
 
    isEmpty: function() {
11660
 
        return this._nodes.length < 1;
11661
 
    },
11662
 
 
11663
 
    toString: function() {
11664
 
        var str = '',
11665
 
            errorMsg = this[UID] + ': not bound to any nodes',
11666
 
            nodes = this._nodes,
11667
 
            node;
11668
 
 
11669
 
        if (nodes && nodes[0]) {
11670
 
            node = nodes[0];
11671
 
            str += node[NODE_NAME];
11672
 
            if (node.id) {
11673
 
                str += '#' + node.id;
11674
 
            }
11675
 
 
11676
 
            if (node.className) {
11677
 
                str += '.' + node.className.replace(' ', '.');
11678
 
            }
11679
 
 
11680
 
            if (nodes.length > 1) {
11681
 
                str += '...[' + nodes.length + ' items]';
11682
 
            }
11683
 
        }
11684
 
        return str || errorMsg;
11685
 
    },
11686
 
 
11687
 
    /**
11688
 
     * Returns the DOM node bound to the Node instance
11689
 
     * @method getDOMNodes
11690
 
     * @return {Array}
11691
 
     */
11692
 
    getDOMNodes: function() {
11693
 
        return this._nodes;
11694
 
    }
11695
 
}, true);
11696
 
 
11697
 
NodeList.importMethod(Y.Node.prototype, [
11698
 
    /** Called on each Node instance
11699
 
      * @method destroy
11700
 
      * @see Node.destroy
11701
 
      */
11702
 
    'destroy',
11703
 
 
11704
 
    /** Called on each Node instance
11705
 
      * @method empty
11706
 
      * @see Node.empty
11707
 
      */
11708
 
    'empty',
11709
 
 
11710
 
    /** Called on each Node instance
11711
 
      * @method remove
11712
 
      * @see Node.remove
11713
 
      */
11714
 
    'remove',
11715
 
 
11716
 
    /** Called on each Node instance
11717
 
      * @method set
11718
 
      * @see Node.set
11719
 
      */
11720
 
    'set'
11721
 
]);
11722
 
 
11723
 
// one-off implementation to convert array of Nodes to NodeList
11724
 
// e.g. Y.all('input').get('parentNode');
11725
 
 
11726
 
/** Called on each Node instance
11727
 
  * @method get
11728
 
  * @see Node
11729
 
  */
11730
 
NodeList.prototype.get = function(attr) {
11731
 
    var ret = [],
11732
 
        nodes = this._nodes,
11733
 
        isNodeList = false,
11734
 
        getTemp = NodeList._getTempNode,
11735
 
        instance,
11736
 
        val;
11737
 
 
11738
 
    if (nodes[0]) {
11739
 
        instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
11740
 
        val = instance._get(attr);
11741
 
        if (val && val.nodeType) {
11742
 
            isNodeList = true;
11743
 
        }
11744
 
    }
11745
 
 
11746
 
    Y.Array.each(nodes, function(node) {
11747
 
        instance = Y.Node._instances[node._yuid];
11748
 
 
11749
 
        if (!instance) {
11750
 
            instance = getTemp(node);
11751
 
        }
11752
 
 
11753
 
        val = instance._get(attr);
11754
 
        if (!isNodeList) { // convert array of Nodes to NodeList
11755
 
            val = Y.Node.scrubVal(val, instance);
11756
 
        }
11757
 
 
11758
 
        ret.push(val);
11759
 
    });
11760
 
 
11761
 
    return (isNodeList) ? Y.all(ret) : ret;
11762
 
};
11763
 
 
11764
 
Y.NodeList = NodeList;
11765
 
 
11766
 
Y.all = function(nodes) {
11767
 
    return new NodeList(nodes);
11768
 
};
11769
 
 
11770
 
Y.Node.all = Y.all;
11771
 
/**
11772
 
 * @module node
11773
 
 * @submodule node-core
11774
 
 */
11775
 
 
11776
 
var Y_NodeList = Y.NodeList,
11777
 
    ArrayProto = Array.prototype,
11778
 
    ArrayMethods = {
11779
 
        /** Returns a new NodeList combining the given NodeList(s)
11780
 
          * @for NodeList
11781
 
          * @method concat
11782
 
          * @param {NodeList | Array} valueN Arrays/NodeLists and/or values to
11783
 
          * concatenate to the resulting NodeList
11784
 
          * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
11785
 
          */
11786
 
        'concat': 1,
11787
 
        /** Removes the first last from the NodeList and returns it.
11788
 
          * @for NodeList
11789
 
          * @method pop
11790
 
          * @return {Node} The last item in the NodeList.
11791
 
          */
11792
 
        'pop': 0,
11793
 
        /** Adds the given Node(s) to the end of the NodeList.
11794
 
          * @for NodeList
11795
 
          * @method push
11796
 
          * @param {Node | DOMNode} nodes One or more nodes to add to the end of the NodeList.
11797
 
          */
11798
 
        'push': 0,
11799
 
        /** Removes the first item from the NodeList and returns it.
11800
 
          * @for NodeList
11801
 
          * @method shift
11802
 
          * @return {Node} The first item in the NodeList.
11803
 
          */
11804
 
        'shift': 0,
11805
 
        /** Returns a new NodeList comprising the Nodes in the given range.
11806
 
          * @for NodeList
11807
 
          * @method slice
11808
 
          * @param {Number} begin Zero-based index at which to begin extraction.
11809
 
          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.
11810
 
          * @param {Number} end Zero-based index at which to end extraction. slice extracts up to but not including end.
11811
 
          slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
11812
 
          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.
11813
 
          If end is omitted, slice extracts to the end of the sequence.
11814
 
          * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
11815
 
          */
11816
 
        'slice': 1,
11817
 
        /** Changes the content of the NodeList, adding new elements while removing old elements.
11818
 
          * @for NodeList
11819
 
          * @method splice
11820
 
          * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
11821
 
          * @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.
11822
 
          * {Node | DOMNode| element1, ..., elementN
11823
 
          The elements to add to the array. If you don't specify any elements, splice simply removes elements from the array.
11824
 
          * @return {NodeList} The element(s) removed.
11825
 
          */
11826
 
        'splice': 1,
11827
 
        /** Adds the given Node(s) to the beginning of the NodeList.
11828
 
          * @for NodeList
11829
 
          * @method push
11830
 
          * @param {Node | DOMNode} nodes One or more nodes to add to the NodeList.
11831
 
          */
11832
 
        'unshift': 0
11833
 
    };
11834
 
 
11835
 
 
11836
 
Y.Object.each(ArrayMethods, function(returnNodeList, name) {
11837
 
    Y_NodeList.prototype[name] = function() {
11838
 
        var args = [],
11839
 
            i = 0,
11840
 
            arg,
11841
 
            ret;
11842
 
 
11843
 
        while (typeof (arg = arguments[i++]) != 'undefined') { // use DOM nodes/nodeLists
11844
 
            args.push(arg._node || arg._nodes || arg);
11845
 
        }
11846
 
 
11847
 
        ret = ArrayProto[name].apply(this._nodes, args);
11848
 
 
11849
 
        if (returnNodeList) {
11850
 
            ret = Y.all(ret);
11851
 
        } else {
11852
 
            ret = Y.Node.scrubVal(ret);
11853
 
        }
11854
 
 
11855
 
        return ret;
11856
 
    };
11857
 
});
11858
 
/**
11859
 
 * @module node
11860
 
 * @submodule node-core
11861
 
 */
11862
 
 
11863
 
Y.Array.each([
11864
 
    /**
11865
 
     * Passes through to DOM method.
11866
 
     * @for Node
11867
 
     * @method removeChild
11868
 
     * @param {HTMLElement | Node} node Node to be removed
11869
 
     * @return {Node} The removed node
11870
 
     */
11871
 
    'removeChild',
11872
 
 
11873
 
    /**
11874
 
     * Passes through to DOM method.
11875
 
     * @method hasChildNodes
11876
 
     * @return {Boolean} Whether or not the node has any childNodes
11877
 
     */
11878
 
    'hasChildNodes',
11879
 
 
11880
 
    /**
11881
 
     * Passes through to DOM method.
11882
 
     * @method cloneNode
11883
 
     * @param {Boolean} deep Whether or not to perform a deep clone, which includes
11884
 
     * subtree and attributes
11885
 
     * @return {Node} The clone
11886
 
     */
11887
 
    'cloneNode',
11888
 
 
11889
 
    /**
11890
 
     * Passes through to DOM method.
11891
 
     * @method hasAttribute
11892
 
     * @param {String} attribute The attribute to test for
11893
 
     * @return {Boolean} Whether or not the attribute is present
11894
 
     */
11895
 
    'hasAttribute',
11896
 
 
11897
 
    /**
11898
 
     * Passes through to DOM method.
11899
 
     * @method removeAttribute
11900
 
     * @param {String} attribute The attribute to be removed
11901
 
     * @chainable
11902
 
     */
11903
 
    'removeAttribute',
11904
 
 
11905
 
    /**
11906
 
     * Passes through to DOM method.
11907
 
     * @method scrollIntoView
11908
 
     * @chainable
11909
 
     */
11910
 
    'scrollIntoView',
11911
 
 
11912
 
    /**
11913
 
     * Passes through to DOM method.
11914
 
     * @method getElementsByTagName
11915
 
     * @param {String} tagName The tagName to collect
11916
 
     * @return {NodeList} A NodeList representing the HTMLCollection
11917
 
     */
11918
 
    'getElementsByTagName',
11919
 
 
11920
 
    /**
11921
 
     * Passes through to DOM method.
11922
 
     * @method focus
11923
 
     * @chainable
11924
 
     */
11925
 
    'focus',
11926
 
 
11927
 
    /**
11928
 
     * Passes through to DOM method.
11929
 
     * @method blur
11930
 
     * @chainable
11931
 
     */
11932
 
    'blur',
11933
 
 
11934
 
    /**
11935
 
     * Passes through to DOM method.
11936
 
     * Only valid on FORM elements
11937
 
     * @method submit
11938
 
     * @chainable
11939
 
     */
11940
 
    'submit',
11941
 
 
11942
 
    /**
11943
 
     * Passes through to DOM method.
11944
 
     * Only valid on FORM elements
11945
 
     * @method reset
11946
 
     * @chainable
11947
 
     */
11948
 
    'reset',
11949
 
 
11950
 
    /**
11951
 
     * Passes through to DOM method.
11952
 
     * @method select
11953
 
     * @chainable
11954
 
     */
11955
 
     'select',
11956
 
 
11957
 
    /**
11958
 
     * Passes through to DOM method.
11959
 
     * Only valid on TABLE elements
11960
 
     * @method createCaption
11961
 
     * @chainable
11962
 
     */
11963
 
    'createCaption'
11964
 
 
11965
 
], function(method) {
11966
 
    Y.log('adding: ' + method, 'info', 'node');
11967
 
    Y.Node.prototype[method] = function(arg1, arg2, arg3) {
11968
 
        var ret = this.invoke(method, arg1, arg2, arg3);
11969
 
        return ret;
11970
 
    };
11971
 
});
11972
 
 
11973
 
Y.Node.importMethod(Y.DOM, [
11974
 
    /**
11975
 
     * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
11976
 
     * @method contains
11977
 
     * @param {Node | HTMLElement} needle The possible node or descendent
11978
 
     * @return {Boolean} Whether or not this node is the needle its ancestor
11979
 
     */
11980
 
    'contains',
11981
 
    /**
11982
 
     * Allows setting attributes on DOM nodes, normalizing in some cases.
11983
 
     * This passes through to the DOM node, allowing for custom attributes.
11984
 
     * @method setAttribute
11985
 
     * @for Node
11986
 
     * @for NodeList
11987
 
     * @chainable
11988
 
     * @param {string} name The attribute name
11989
 
     * @param {string} value The value to set
11990
 
     */
11991
 
    'setAttribute',
11992
 
    /**
11993
 
     * Allows getting attributes on DOM nodes, normalizing in some cases.
11994
 
     * This passes through to the DOM node, allowing for custom attributes.
11995
 
     * @method getAttribute
11996
 
     * @for Node
11997
 
     * @for NodeList
11998
 
     * @param {string} name The attribute name
11999
 
     * @return {string} The attribute value
12000
 
     */
12001
 
    'getAttribute',
12002
 
 
12003
 
    /**
12004
 
     * Wraps the given HTML around the node.
12005
 
     * @method wrap
12006
 
     * @param {String} html The markup to wrap around the node.
12007
 
     * @chainable
12008
 
     * @for Node
12009
 
     */
12010
 
    'wrap',
12011
 
 
12012
 
    /**
12013
 
     * Removes the node's parent node.
12014
 
     * @method unwrap
12015
 
     * @chainable
12016
 
     */
12017
 
    'unwrap',
12018
 
 
12019
 
    /**
12020
 
     * Applies a unique ID to the node if none exists
12021
 
     * @method generateID
12022
 
     * @return {String} The existing or generated ID
12023
 
     */
12024
 
    'generateID'
12025
 
]);
12026
 
 
12027
 
Y.NodeList.importMethod(Y.Node.prototype, [
12028
 
/**
12029
 
 * Allows getting attributes on DOM nodes, normalizing in some cases.
12030
 
 * This passes through to the DOM node, allowing for custom attributes.
12031
 
 * @method getAttribute
12032
 
 * @see Node
12033
 
 * @for NodeList
12034
 
 * @param {string} name The attribute name
12035
 
 * @return {string} The attribute value
12036
 
 */
12037
 
 
12038
 
    'getAttribute',
12039
 
/**
12040
 
 * Allows setting attributes on DOM nodes, normalizing in some cases.
12041
 
 * This passes through to the DOM node, allowing for custom attributes.
12042
 
 * @method setAttribute
12043
 
 * @see Node
12044
 
 * @for NodeList
12045
 
 * @chainable
12046
 
 * @param {string} name The attribute name
12047
 
 * @param {string} value The value to set
12048
 
 */
12049
 
    'setAttribute',
12050
 
 
12051
 
/**
12052
 
 * Allows for removing attributes on DOM nodes.
12053
 
 * This passes through to the DOM node, allowing for custom attributes.
12054
 
 * @method removeAttribute
12055
 
 * @see Node
12056
 
 * @for NodeList
12057
 
 * @param {string} name The attribute to remove
12058
 
 */
12059
 
    'removeAttribute',
12060
 
/**
12061
 
 * Removes the parent node from node in the list.
12062
 
 * @method unwrap
12063
 
 * @chainable
12064
 
 */
12065
 
    'unwrap',
12066
 
/**
12067
 
 * Wraps the given HTML around each node.
12068
 
 * @method wrap
12069
 
 * @param {String} html The markup to wrap around the node.
12070
 
 * @chainable
12071
 
 */
12072
 
    'wrap',
12073
 
 
12074
 
/**
12075
 
 * Applies a unique ID to each node if none exists
12076
 
 * @method generateID
12077
 
 * @return {String} The existing or generated ID
12078
 
 */
12079
 
    'generateID'
12080
 
]);
12081
 
 
12082
 
 
12083
 
}, '3.4.1' ,{requires:['dom-core', 'selector']});
12084
 
YUI.add('node-base', function(Y) {
12085
 
 
12086
 
/**
12087
 
 * @module node
12088
 
 * @submodule node-base
12089
 
 */
12090
 
 
12091
 
var methods = [
12092
 
/**
12093
 
 * Determines whether each node has the given className.
12094
 
 * @method hasClass
12095
 
 * @for Node
12096
 
 * @param {String} className the class name to search for
12097
 
 * @return {Boolean} Whether or not the element has the specified class
12098
 
 */
12099
 
 'hasClass',
12100
 
 
12101
 
/**
12102
 
 * Adds a class name to each node.
12103
 
 * @method addClass
12104
 
 * @param {String} className the class name to add to the node's class attribute
12105
 
 * @chainable
12106
 
 */
12107
 
 'addClass',
12108
 
 
12109
 
/**
12110
 
 * Removes a class name from each node.
12111
 
 * @method removeClass
12112
 
 * @param {String} className the class name to remove from the node's class attribute
12113
 
 * @chainable
12114
 
 */
12115
 
 'removeClass',
12116
 
 
12117
 
/**
12118
 
 * Replace a class with another class for each node.
12119
 
 * If no oldClassName is present, the newClassName is simply added.
12120
 
 * @method replaceClass
12121
 
 * @param {String} oldClassName the class name to be replaced
12122
 
 * @param {String} newClassName the class name that will be replacing the old class name
12123
 
 * @chainable
12124
 
 */
12125
 
 'replaceClass',
12126
 
 
12127
 
/**
12128
 
 * If the className exists on the node it is removed, if it doesn't exist it is added.
12129
 
 * @method toggleClass
12130
 
 * @param {String} className the class name to be toggled
12131
 
 * @param {Boolean} force Option to force adding or removing the class.
12132
 
 * @chainable
12133
 
 */
12134
 
 'toggleClass'
12135
 
];
12136
 
 
12137
 
Y.Node.importMethod(Y.DOM, methods);
12138
 
/**
12139
 
 * Determines whether each node has the given className.
12140
 
 * @method hasClass
12141
 
 * @see Node.hasClass
12142
 
 * @for NodeList
12143
 
 * @param {String} className the class name to search for
12144
 
 * @return {Array} An array of booleans for each node bound to the NodeList.
12145
 
 */
12146
 
 
12147
 
/**
12148
 
 * Adds a class name to each node.
12149
 
 * @method addClass
12150
 
 * @see Node.addClass
12151
 
 * @param {String} className the class name to add to the node's class attribute
12152
 
 * @chainable
12153
 
 */
12154
 
 
12155
 
/**
12156
 
 * Removes a class name from each node.
12157
 
 * @method removeClass
12158
 
 * @see Node.removeClass
12159
 
 * @param {String} className the class name to remove from the node's class attribute
12160
 
 * @chainable
12161
 
 */
12162
 
 
12163
 
/**
12164
 
 * Replace a class with another class for each node.
12165
 
 * If no oldClassName is present, the newClassName is simply added.
12166
 
 * @method replaceClass
12167
 
 * @see Node.replaceClass
12168
 
 * @param {String} oldClassName the class name to be replaced
12169
 
 * @param {String} newClassName the class name that will be replacing the old class name
12170
 
 * @chainable
12171
 
 */
12172
 
 
12173
 
/**
12174
 
 * If the className exists on the node it is removed, if it doesn't exist it is added.
12175
 
 * @method toggleClass
12176
 
 * @see Node.toggleClass
12177
 
 * @param {String} className the class name to be toggled
12178
 
 * @chainable
12179
 
 */
12180
 
Y.NodeList.importMethod(Y.Node.prototype, methods);
12181
 
/**
12182
 
 * @module node
12183
 
 * @submodule node-base
12184
 
 */
12185
 
 
12186
 
var Y_Node = Y.Node,
12187
 
    Y_DOM = Y.DOM;
12188
 
 
12189
 
/**
12190
 
 * Returns a new dom node using the provided markup string.
12191
 
 * @method create
12192
 
 * @static
12193
 
 * @param {String} html The markup used to create the element
12194
 
 * @param {HTMLDocument} doc An optional document context
12195
 
 * @return {Node} A Node instance bound to a DOM node or fragment
12196
 
 * @for Node
12197
 
 */
12198
 
Y_Node.create = function(html, doc) {
12199
 
    if (doc && doc._node) {
12200
 
        doc = doc._node;
12201
 
    }
12202
 
    return Y.one(Y_DOM.create(html, doc));
12203
 
};
12204
 
 
12205
 
Y.mix(Y_Node.prototype, {
12206
 
    /**
12207
 
     * Creates a new Node using the provided markup string.
12208
 
     * @method create
12209
 
     * @param {String} html The markup used to create the element
12210
 
     * @param {HTMLDocument} doc An optional document context
12211
 
     * @return {Node} A Node instance bound to a DOM node or fragment
12212
 
     */
12213
 
    create: Y_Node.create,
12214
 
 
12215
 
    /**
12216
 
     * Inserts the content before the reference node.
12217
 
     * @method insert
12218
 
     * @param {String | Y.Node | HTMLElement | Y.NodeList | HTMLCollection} content The content to insert
12219
 
     * @param {Int | Y.Node | HTMLElement | String} where The position to insert at.
12220
 
     * Possible "where" arguments
12221
 
     * <dl>
12222
 
     * <dt>Y.Node</dt>
12223
 
     * <dd>The Node to insert before</dd>
12224
 
     * <dt>HTMLElement</dt>
12225
 
     * <dd>The element to insert before</dd>
12226
 
     * <dt>Int</dt>
12227
 
     * <dd>The index of the child element to insert before</dd>
12228
 
     * <dt>"replace"</dt>
12229
 
     * <dd>Replaces the existing HTML</dd>
12230
 
     * <dt>"before"</dt>
12231
 
     * <dd>Inserts before the existing HTML</dd>
12232
 
     * <dt>"before"</dt>
12233
 
     * <dd>Inserts content before the node</dd>
12234
 
     * <dt>"after"</dt>
12235
 
     * <dd>Inserts content after the node</dd>
12236
 
     * </dl>
12237
 
     * @chainable
12238
 
     */
12239
 
    insert: function(content, where) {
12240
 
        this._insert(content, where);
12241
 
        return this;
12242
 
    },
12243
 
 
12244
 
    _insert: function(content, where) {
12245
 
        var node = this._node,
12246
 
            ret = null;
12247
 
 
12248
 
        if (typeof where == 'number') { // allow index
12249
 
            where = this._node.childNodes[where];
12250
 
        } else if (where && where._node) { // Node
12251
 
            where = where._node;
12252
 
        }
12253
 
 
12254
 
        if (content && typeof content != 'string') { // allow Node or NodeList/Array instances
12255
 
            content = content._node || content._nodes || content;
12256
 
        }
12257
 
        ret = Y_DOM.addHTML(node, content, where);
12258
 
 
12259
 
        return ret;
12260
 
    },
12261
 
 
12262
 
    /**
12263
 
     * Inserts the content as the firstChild of the node.
12264
 
     * @method prepend
12265
 
     * @param {String | Y.Node | HTMLElement} content The content to insert
12266
 
     * @chainable
12267
 
     */
12268
 
    prepend: function(content) {
12269
 
        return this.insert(content, 0);
12270
 
    },
12271
 
 
12272
 
    /**
12273
 
     * Inserts the content as the lastChild of the node.
12274
 
     * @method append
12275
 
     * @param {String | Y.Node | HTMLElement} content The content to insert
12276
 
     * @chainable
12277
 
     */
12278
 
    append: function(content) {
12279
 
        return this.insert(content, null);
12280
 
    },
12281
 
 
12282
 
    /**
12283
 
     * @method appendChild
12284
 
     * @param {String | HTMLElement | Node} node Node to be appended
12285
 
     * @return {Node} The appended node
12286
 
     */
12287
 
    appendChild: function(node) {
12288
 
        return Y_Node.scrubVal(this._insert(node));
12289
 
    },
12290
 
 
12291
 
    /**
12292
 
     * @method insertBefore
12293
 
     * @param {String | HTMLElement | Node} newNode Node to be appended
12294
 
     * @param {HTMLElement | Node} refNode Node to be inserted before
12295
 
     * @return {Node} The inserted node
12296
 
     */
12297
 
    insertBefore: function(newNode, refNode) {
12298
 
        return Y.Node.scrubVal(this._insert(newNode, refNode));
12299
 
    },
12300
 
 
12301
 
    /**
12302
 
     * Appends the node to the given node.
12303
 
     * @method appendTo
12304
 
     * @param {Y.Node | HTMLElement} node The node to append to
12305
 
     * @chainable
12306
 
     */
12307
 
    appendTo: function(node) {
12308
 
        Y.one(node).append(this);
12309
 
        return this;
12310
 
    },
12311
 
 
12312
 
    /**
12313
 
     * Replaces the node's current content with the content.
12314
 
     * @method setContent
12315
 
     * @param {String | Y.Node | HTMLElement | Y.NodeList | HTMLCollection} content The content to insert
12316
 
     * @chainable
12317
 
     */
12318
 
    setContent: function(content) {
12319
 
        this._insert(content, 'replace');
12320
 
        return this;
12321
 
    },
12322
 
 
12323
 
    /**
12324
 
     * Returns the node's current content (e.g. innerHTML)
12325
 
     * @method getContent
12326
 
     * @return {String} The current content
12327
 
     */
12328
 
    getContent: function(content) {
12329
 
        return this.get('innerHTML');
12330
 
    }
12331
 
});
12332
 
 
12333
 
Y.NodeList.importMethod(Y.Node.prototype, [
12334
 
    /**
12335
 
     * Called on each Node instance
12336
 
     * @for NodeList
12337
 
     * @method append
12338
 
     * @see Node.append
12339
 
     */
12340
 
    'append',
12341
 
 
12342
 
    /** Called on each Node instance
12343
 
      * @method insert
12344
 
      * @see Node.insert
12345
 
      */
12346
 
    'insert',
12347
 
 
12348
 
    /**
12349
 
     * Called on each Node instance
12350
 
     * @for NodeList
12351
 
     * @method appendChild
12352
 
     * @see Node.appendChild
12353
 
     */
12354
 
    'appendChild',
12355
 
 
12356
 
    /** Called on each Node instance
12357
 
      * @method insertBefore
12358
 
      * @see Node.insertBefore
12359
 
      */
12360
 
    'insertBefore',
12361
 
 
12362
 
    /** Called on each Node instance
12363
 
      * @method prepend
12364
 
      * @see Node.prepend
12365
 
      */
12366
 
    'prepend',
12367
 
 
12368
 
    /** Called on each Node instance
12369
 
      * @method setContent
12370
 
      * @see Node.setContent
12371
 
      */
12372
 
    'setContent',
12373
 
 
12374
 
    /** Called on each Node instance
12375
 
      * @method getContent
12376
 
      * @see Node.getContent
12377
 
      */
12378
 
    'getContent'
12379
 
]);
12380
 
/**
12381
 
 * @module node
12382
 
 * @submodule node-base
12383
 
 */
12384
 
 
12385
 
var Y_Node = Y.Node,
12386
 
    Y_DOM = Y.DOM;
12387
 
 
12388
 
/**
12389
 
 * Static collection of configuration attributes for special handling
12390
 
 * @property ATTRS
12391
 
 * @static
12392
 
 * @type object
12393
 
 */
12394
 
Y_Node.ATTRS = {
12395
 
    /**
12396
 
     * Allows for getting and setting the text of an element.
12397
 
     * Formatting is preserved and special characters are treated literally.
12398
 
     * @config text
12399
 
     * @type String
12400
 
     */
12401
 
    text: {
12402
 
        getter: function() {
12403
 
            return Y_DOM.getText(this._node);
12404
 
        },
12405
 
 
12406
 
        setter: function(content) {
12407
 
            Y_DOM.setText(this._node, content);
12408
 
            return content;
12409
 
        }
12410
 
    },
12411
 
 
12412
 
    /**
12413
 
     * Allows for getting and setting the text of an element.
12414
 
     * Formatting is preserved and special characters are treated literally.
12415
 
     * @config for
12416
 
     * @type String
12417
 
     */
12418
 
    'for': {
12419
 
        getter: function() {
12420
 
            return Y_DOM.getAttribute(this._node, 'for');
12421
 
        },
12422
 
 
12423
 
        setter: function(val) {
12424
 
            Y_DOM.setAttribute(this._node, 'for', val);
12425
 
            return val;
12426
 
        }
12427
 
    },
12428
 
 
12429
 
    'options': {
12430
 
        getter: function() {
12431
 
            return this._node.getElementsByTagName('option');
12432
 
        }
12433
 
    },
12434
 
 
12435
 
    /**
12436
 
     * Returns a NodeList instance of all HTMLElement children.
12437
 
     * @readOnly
12438
 
     * @config children
12439
 
     * @type NodeList
12440
 
     */
12441
 
    'children': {
12442
 
        getter: function() {
12443
 
            var node = this._node,
12444
 
                children = node.children,
12445
 
                childNodes, i, len;
12446
 
 
12447
 
            if (!children) {
12448
 
                childNodes = node.childNodes;
12449
 
                children = [];
12450
 
 
12451
 
                for (i = 0, len = childNodes.length; i < len; ++i) {
12452
 
                    if (childNodes[i][TAG_NAME]) {
12453
 
                        children[children.length] = childNodes[i];
12454
 
                    }
12455
 
                }
12456
 
            }
12457
 
            return Y.all(children);
12458
 
        }
12459
 
    },
12460
 
 
12461
 
    value: {
12462
 
        getter: function() {
12463
 
            return Y_DOM.getValue(this._node);
12464
 
        },
12465
 
 
12466
 
        setter: function(val) {
12467
 
            Y_DOM.setValue(this._node, val);
12468
 
            return val;
12469
 
        }
12470
 
    }
12471
 
};
12472
 
 
12473
 
Y.Node.importMethod(Y.DOM, [
12474
 
    /**
12475
 
     * Allows setting attributes on DOM nodes, normalizing in some cases.
12476
 
     * This passes through to the DOM node, allowing for custom attributes.
12477
 
     * @method setAttribute
12478
 
     * @for Node
12479
 
     * @for NodeList
12480
 
     * @chainable
12481
 
     * @param {string} name The attribute name
12482
 
     * @param {string} value The value to set
12483
 
     */
12484
 
    'setAttribute',
12485
 
    /**
12486
 
     * Allows getting attributes on DOM nodes, normalizing in some cases.
12487
 
     * This passes through to the DOM node, allowing for custom attributes.
12488
 
     * @method getAttribute
12489
 
     * @for Node
12490
 
     * @for NodeList
12491
 
     * @param {string} name The attribute name
12492
 
     * @return {string} The attribute value
12493
 
     */
12494
 
    'getAttribute'
12495
 
 
12496
 
]);
12497
 
/**
12498
 
 * @module node
12499
 
 * @submodule node-base
12500
 
 */
12501
 
 
12502
 
var Y_Node = Y.Node;
12503
 
var Y_NodeList = Y.NodeList;
12504
 
/**
12505
 
 * List of events that route to DOM events
12506
 
 * @static
12507
 
 * @property DOM_EVENTS
12508
 
 * @for Node
12509
 
 */
12510
 
 
12511
 
Y_Node.DOM_EVENTS = {
12512
 
    abort: 1,
12513
 
    beforeunload: 1,
12514
 
    blur: 1,
12515
 
    change: 1,
12516
 
    click: 1,
12517
 
    close: 1,
12518
 
    command: 1,
12519
 
    contextmenu: 1,
12520
 
    dblclick: 1,
12521
 
    DOMMouseScroll: 1,
12522
 
    drag: 1,
12523
 
    dragstart: 1,
12524
 
    dragenter: 1,
12525
 
    dragover: 1,
12526
 
    dragleave: 1,
12527
 
    dragend: 1,
12528
 
    drop: 1,
12529
 
    error: 1,
12530
 
    focus: 1,
12531
 
    key: 1,
12532
 
    keydown: 1,
12533
 
    keypress: 1,
12534
 
    keyup: 1,
12535
 
    load: 1,
12536
 
    message: 1,
12537
 
    mousedown: 1,
12538
 
    mouseenter: 1,
12539
 
    mouseleave: 1,
12540
 
    mousemove: 1,
12541
 
    mousemultiwheel: 1,
12542
 
    mouseout: 1,
12543
 
    mouseover: 1,
12544
 
    mouseup: 1,
12545
 
    mousewheel: 1,
12546
 
    orientationchange: 1,
12547
 
    reset: 1,
12548
 
    resize: 1,
12549
 
    select: 1,
12550
 
    selectstart: 1,
12551
 
    submit: 1,
12552
 
    scroll: 1,
12553
 
    textInput: 1,
12554
 
    unload: 1
12555
 
};
12556
 
 
12557
 
// Add custom event adaptors to this list.  This will make it so
12558
 
// that delegate, key, available, contentready, etc all will
12559
 
// be available through Node.on
12560
 
Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
12561
 
 
12562
 
Y.augment(Y_Node, Y.EventTarget);
12563
 
 
12564
 
Y.mix(Y_Node.prototype, {
12565
 
    /**
12566
 
     * Removes event listeners from the node and (optionally) its subtree
12567
 
     * @method purge
12568
 
     * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
12569
 
     * node's subtree
12570
 
     * @param {String} type (optional) Only remove listeners of the specified type
12571
 
     * @chainable
12572
 
     *
12573
 
     */
12574
 
    purge: function(recurse, type) {
12575
 
        Y.Event.purgeElement(this._node, recurse, type);
12576
 
        return this;
12577
 
    }
12578
 
 
12579
 
});
12580
 
 
12581
 
Y.mix(Y.NodeList.prototype, {
12582
 
    _prepEvtArgs: function(type, fn, context) {
12583
 
        // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
12584
 
        var args = Y.Array(arguments, 0, true);
12585
 
 
12586
 
        if (args.length < 2) { // type only (event hash) just add nodes
12587
 
            args[2] = this._nodes;
12588
 
        } else {
12589
 
            args.splice(2, 0, this._nodes);
12590
 
        }
12591
 
 
12592
 
        args[3] = context || this; // default to NodeList instance as context
12593
 
 
12594
 
        return args;
12595
 
    },
12596
 
 
12597
 
    /**
12598
 
     * Applies an event listener to each Node bound to the NodeList.
12599
 
     * @method on
12600
 
     * @param {String} type The event being listened for
12601
 
     * @param {Function} fn The handler to call when the event fires
12602
 
     * @param {Object} context The context to call the handler with.
12603
 
     * Default is the NodeList instance.
12604
 
     * @param {Object} context The context to call the handler with.
12605
 
     * param {mixed} arg* 0..n additional arguments to supply to the subscriber
12606
 
     * when the event fires.
12607
 
     * @return {Object} Returns an event handle that can later be use to detach().
12608
 
     * @see Event.on
12609
 
     * @for NodeList
12610
 
     */
12611
 
    on: function(type, fn, context) {
12612
 
        return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
12613
 
    },
12614
 
 
12615
 
    /**
12616
 
     * Applies an one-time event listener to each Node bound to the NodeList.
12617
 
     * @method once
12618
 
     * @param {String} type The event being listened for
12619
 
     * @param {Function} fn The handler to call when the event fires
12620
 
     * @param {Object} context The context to call the handler with.
12621
 
     * Default is the NodeList instance.
12622
 
     * @return {Object} Returns an event handle that can later be use to detach().
12623
 
     * @see Event.on
12624
 
     */
12625
 
    once: function(type, fn, context) {
12626
 
        return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
12627
 
    },
12628
 
 
12629
 
    /**
12630
 
     * Applies an event listener to each Node bound to the NodeList.
12631
 
     * The handler is called only after all on() handlers are called
12632
 
     * and the event is not prevented.
12633
 
     * @method after
12634
 
     * @param {String} type The event being listened for
12635
 
     * @param {Function} fn The handler to call when the event fires
12636
 
     * @param {Object} context The context to call the handler with.
12637
 
     * Default is the NodeList instance.
12638
 
     * @return {Object} Returns an event handle that can later be use to detach().
12639
 
     * @see Event.on
12640
 
     */
12641
 
    after: function(type, fn, context) {
12642
 
        return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
12643
 
    },
12644
 
 
12645
 
    /**
12646
 
     * Applies an one-time event listener to each Node bound to the NodeList
12647
 
     * that will be called only after all on() handlers are called and the
12648
 
     * event is not prevented.
12649
 
     *
12650
 
     * @method onceAfter
12651
 
     * @param {String} type The event being listened for
12652
 
     * @param {Function} fn The handler to call when the event fires
12653
 
     * @param {Object} context The context to call the handler with.
12654
 
     * Default is the NodeList instance.
12655
 
     * @return {Object} Returns an event handle that can later be use to detach().
12656
 
     * @see Event.on
12657
 
     */
12658
 
    onceAfter: function(type, fn, context) {
12659
 
        return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
12660
 
    }
12661
 
});
12662
 
 
12663
 
Y_NodeList.importMethod(Y.Node.prototype, [
12664
 
    /**
12665
 
      * Called on each Node instance
12666
 
      * @method detach
12667
 
      * @see Node.detach
12668
 
      */
12669
 
    'detach',
12670
 
 
12671
 
    /** Called on each Node instance
12672
 
      * @method detachAll
12673
 
      * @see Node.detachAll
12674
 
      */
12675
 
    'detachAll'
12676
 
]);
12677
 
Y.mix(Y.Node.ATTRS, {
12678
 
    offsetHeight: {
12679
 
        setter: function(h) {
12680
 
            Y.DOM.setHeight(this._node, h);
12681
 
            return h;
12682
 
        },
12683
 
 
12684
 
        getter: function() {
12685
 
            return this._node.offsetHeight;
12686
 
        }
12687
 
    },
12688
 
 
12689
 
    offsetWidth: {
12690
 
        setter: function(w) {
12691
 
            Y.DOM.setWidth(this._node, w);
12692
 
            return w;
12693
 
        },
12694
 
 
12695
 
        getter: function() {
12696
 
            return this._node.offsetWidth;
12697
 
        }
12698
 
    }
12699
 
});
12700
 
 
12701
 
Y.mix(Y.Node.prototype, {
12702
 
    sizeTo: function(w, h) {
12703
 
        var node;
12704
 
        if (arguments.length < 2) {
12705
 
            node = Y.one(w);
12706
 
            w = node.get('offsetWidth');
12707
 
            h = node.get('offsetHeight');
12708
 
        }
12709
 
 
12710
 
        this.setAttrs({
12711
 
            offsetWidth: w,
12712
 
            offsetHeight: h
12713
 
        });
12714
 
    }
12715
 
});
12716
 
/**
12717
 
 * @module node
12718
 
 * @submodule node-base
12719
 
 */
12720
 
 
12721
 
var Y_Node = Y.Node;
12722
 
 
12723
 
Y.mix(Y_Node.prototype, {
12724
 
    /**
12725
 
     * Makes the node visible.
12726
 
     * If the "transition" module is loaded, show optionally
12727
 
     * animates the showing of the node using either the default
12728
 
     * transition effect ('fadeIn'), or the given named effect.
12729
 
     * @method show
12730
 
     * @for Node
12731
 
     * @param {String} name A named Transition effect to use as the show effect.
12732
 
     * @param {Object} config Options to use with the transition.
12733
 
     * @param {Function} callback An optional function to run after the transition completes.
12734
 
     * @chainable
12735
 
     */
12736
 
    show: function(callback) {
12737
 
        callback = arguments[arguments.length - 1];
12738
 
        this.toggleView(true, callback);
12739
 
        return this;
12740
 
    },
12741
 
 
12742
 
    /**
12743
 
     * The implementation for showing nodes.
12744
 
     * Default is to toggle the style.display property.
12745
 
     * @method _show
12746
 
     * @protected
12747
 
     * @chainable
12748
 
     */
12749
 
    _show: function() {
12750
 
        this.setStyle('display', '');
12751
 
 
12752
 
    },
12753
 
 
12754
 
    _isHidden: function() {
12755
 
        return Y.DOM.getStyle(this._node, 'display') === 'none';
12756
 
    },
12757
 
 
12758
 
    toggleView: function(on, callback) {
12759
 
        this._toggleView.apply(this, arguments);
12760
 
    },
12761
 
 
12762
 
    _toggleView: function(on, callback) {
12763
 
        callback = arguments[arguments.length - 1];
12764
 
 
12765
 
        // base on current state if not forcing
12766
 
        if (typeof on != 'boolean') {
12767
 
            on = (this._isHidden()) ? 1 : 0;
12768
 
        }
12769
 
 
12770
 
        if (on) {
12771
 
            this._show();
12772
 
        }  else {
12773
 
            this._hide();
12774
 
        }
12775
 
 
12776
 
        if (typeof callback == 'function') {
12777
 
            callback.call(this);
12778
 
        }
12779
 
 
12780
 
        return this;
12781
 
    },
12782
 
 
12783
 
    /**
12784
 
     * Hides the node.
12785
 
     * If the "transition" module is loaded, hide optionally
12786
 
     * animates the hiding of the node using either the default
12787
 
     * transition effect ('fadeOut'), or the given named effect.
12788
 
     * @method hide
12789
 
     * @param {String} name A named Transition effect to use as the show effect.
12790
 
     * @param {Object} config Options to use with the transition.
12791
 
     * @param {Function} callback An optional function to run after the transition completes.
12792
 
     * @chainable
12793
 
     */
12794
 
    hide: function(callback) {
12795
 
        callback = arguments[arguments.length - 1];
12796
 
        this.toggleView(false, callback);
12797
 
        return this;
12798
 
    },
12799
 
 
12800
 
    /**
12801
 
     * The implementation for hiding nodes.
12802
 
     * Default is to toggle the style.display property.
12803
 
     * @method _hide
12804
 
     * @protected
12805
 
     * @chainable
12806
 
     */
12807
 
    _hide: function() {
12808
 
        this.setStyle('display', 'none');
12809
 
    }
12810
 
});
12811
 
 
12812
 
Y.NodeList.importMethod(Y.Node.prototype, [
12813
 
    /**
12814
 
     * Makes each node visible.
12815
 
     * If the "transition" module is loaded, show optionally
12816
 
     * animates the showing of the node using either the default
12817
 
     * transition effect ('fadeIn'), or the given named effect.
12818
 
     * @method show
12819
 
     * @param {String} name A named Transition effect to use as the show effect.
12820
 
     * @param {Object} config Options to use with the transition.
12821
 
     * @param {Function} callback An optional function to run after the transition completes.
12822
 
     * @for NodeList
12823
 
     * @chainable
12824
 
     */
12825
 
    'show',
12826
 
 
12827
 
    /**
12828
 
     * Hides each node.
12829
 
     * If the "transition" module is loaded, hide optionally
12830
 
     * animates the hiding of the node using either the default
12831
 
     * transition effect ('fadeOut'), or the given named effect.
12832
 
     * @method hide
12833
 
     * @param {String} name A named Transition effect to use as the show effect.
12834
 
     * @param {Object} config Options to use with the transition.
12835
 
     * @param {Function} callback An optional function to run after the transition completes.
12836
 
     * @chainable
12837
 
     */
12838
 
    'hide',
12839
 
 
12840
 
    'toggleView'
12841
 
]);
12842
 
 
12843
 
if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
12844
 
    Y.Node.prototype.hasAttribute = function(attr) {
12845
 
        if (attr === 'value') {
12846
 
            if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
12847
 
                return true;
12848
 
            }
12849
 
        }
12850
 
        return !!(this._node.attributes[attr] &&
12851
 
                this._node.attributes[attr].specified);
12852
 
    };
12853
 
}
12854
 
 
12855
 
// IE throws an error when calling focus() on an element that's invisible, not
12856
 
// displayed, or disabled.
12857
 
Y.Node.prototype.focus = function () {
12858
 
    try {
12859
 
        this._node.focus();
12860
 
    } catch (e) {
12861
 
        Y.log('error focusing node: ' + e.toString(), 'error', 'node');
12862
 
    }
12863
 
 
12864
 
    return this;
12865
 
};
12866
 
 
12867
 
// IE throws error when setting input.type = 'hidden',
12868
 
// input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
12869
 
Y.Node.ATTRS.type = {
12870
 
    setter: function(val) {
12871
 
        if (val === 'hidden') {
12872
 
            try {
12873
 
                this._node.type = 'hidden';
12874
 
            } catch(e) {
12875
 
                this.setStyle('display', 'none');
12876
 
                this._inputType = 'hidden';
12877
 
            }
12878
 
        } else {
12879
 
            try { // IE errors when changing the type from "hidden'
12880
 
                this._node.type = val;
12881
 
            } catch (e) {
12882
 
                Y.log('error setting type: ' + val, 'info', 'node');
12883
 
            }
12884
 
        }
12885
 
        return val;
12886
 
    },
12887
 
 
12888
 
    getter: function() {
12889
 
        return this._inputType || this._node.type;
12890
 
    },
12891
 
 
12892
 
    _bypassProxy: true // don't update DOM when using with Attribute
12893
 
};
12894
 
 
12895
 
if (Y.config.doc.createElement('form').elements.nodeType) {
12896
 
    // IE: elements collection is also FORM node which trips up scrubVal.
12897
 
    Y.Node.ATTRS.elements = {
12898
 
            getter: function() {
12899
 
                return this.all('input, textarea, button, select');
12900
 
            }
12901
 
    };
12902
 
}
12903
 
 
12904
 
 
12905
 
 
12906
 
}, '3.4.1' ,{requires:['dom-base', 'node-core', 'event-base']});
12907
 
(function () {
12908
 
var GLOBAL_ENV = YUI.Env;
12909
 
 
12910
 
if (!GLOBAL_ENV._ready) {
12911
 
    GLOBAL_ENV._ready = function() {
12912
 
        GLOBAL_ENV.DOMReady = true;
12913
 
        GLOBAL_ENV.remove(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
12914
 
    };
12915
 
 
12916
 
    GLOBAL_ENV.add(YUI.config.doc, 'DOMContentLoaded', GLOBAL_ENV._ready);
12917
 
}
12918
 
})();
12919
 
YUI.add('event-base', function(Y) {
12920
 
 
12921
 
/*
12922
 
 * DOM event listener abstraction layer
12923
 
 * @module event
12924
 
 * @submodule event-base
12925
 
 */
12926
 
 
12927
 
/**
12928
 
 * The domready event fires at the moment the browser's DOM is
12929
 
 * usable. In most cases, this is before images are fully
12930
 
 * downloaded, allowing you to provide a more responsive user
12931
 
 * interface.
12932
 
 *
12933
 
 * In YUI 3, domready subscribers will be notified immediately if
12934
 
 * that moment has already passed when the subscription is created.
12935
 
 *
12936
 
 * One exception is if the yui.js file is dynamically injected into
12937
 
 * the page.  If this is done, you must tell the YUI instance that
12938
 
 * you did this in order for DOMReady (and window load events) to
12939
 
 * fire normally.  That configuration option is 'injected' -- set
12940
 
 * it to true if the yui.js script is not included inline.
12941
 
 *
12942
 
 * This method is part of the 'event-ready' module, which is a
12943
 
 * submodule of 'event'.
12944
 
 *
12945
 
 * @event domready
12946
 
 * @for YUI
12947
 
 */
12948
 
Y.publish('domready', {
12949
 
    fireOnce: true,
12950
 
    async: true
12951
 
});
12952
 
 
12953
 
if (YUI.Env.DOMReady) {
12954
 
    Y.fire('domready');
12955
 
} else {
12956
 
    Y.Do.before(function() { Y.fire('domready'); }, YUI.Env, '_ready');
12957
 
}
12958
 
 
12959
 
/**
12960
 
 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
12961
 
 * events.
12962
 
 * @module event
12963
 
 * @submodule event-base
12964
 
 */
12965
 
 
12966
 
/**
12967
 
 * Wraps a DOM event, properties requiring browser abstraction are
12968
 
 * fixed here.  Provids a security layer when required.
12969
 
 * @class DOMEventFacade
12970
 
 * @param ev {Event} the DOM event
12971
 
 * @param currentTarget {HTMLElement} the element the listener was attached to
12972
 
 * @param wrapper {Event.Custom} the custom event wrapper for this DOM event
12973
 
 */
12974
 
 
12975
 
    var ua = Y.UA,
12976
 
 
12977
 
    EMPTY = {},
12978
 
 
12979
 
    /**
12980
 
     * webkit key remapping required for Safari < 3.1
12981
 
     * @property webkitKeymap
12982
 
     * @private
12983
 
     */
12984
 
    webkitKeymap = {
12985
 
        63232: 38, // up
12986
 
        63233: 40, // down
12987
 
        63234: 37, // left
12988
 
        63235: 39, // right
12989
 
        63276: 33, // page up
12990
 
        63277: 34, // page down
12991
 
        25:     9, // SHIFT-TAB (Safari provides a different key code in
12992
 
                   // this case, even though the shiftKey modifier is set)
12993
 
        63272: 46, // delete
12994
 
        63273: 36, // home
12995
 
        63275: 35  // end
12996
 
    },
12997
 
 
12998
 
    /**
12999
 
     * Returns a wrapped node.  Intended to be used on event targets,
13000
 
     * so it will return the node's parent if the target is a text
13001
 
     * node.
13002
 
     *
13003
 
     * If accessing a property of the node throws an error, this is
13004
 
     * probably the anonymous div wrapper Gecko adds inside text
13005
 
     * nodes.  This likely will only occur when attempting to access
13006
 
     * the relatedTarget.  In this case, we now return null because
13007
 
     * the anonymous div is completely useless and we do not know
13008
 
     * what the related target was because we can't even get to
13009
 
     * the element's parent node.
13010
 
     *
13011
 
     * @method resolve
13012
 
     * @private
13013
 
     */
13014
 
    resolve = function(n) {
13015
 
        if (!n) {
13016
 
            return n;
13017
 
        }
13018
 
        try {
13019
 
            if (n && 3 == n.nodeType) {
13020
 
                n = n.parentNode;
13021
 
            }
13022
 
        } catch(e) {
13023
 
            return null;
13024
 
        }
13025
 
 
13026
 
        return Y.one(n);
13027
 
    },
13028
 
 
13029
 
    DOMEventFacade = function(ev, currentTarget, wrapper) {
13030
 
        this._event = ev;
13031
 
        this._currentTarget = currentTarget;
13032
 
        this._wrapper = wrapper || EMPTY;
13033
 
 
13034
 
        // if not lazy init
13035
 
        this.init();
13036
 
    };
13037
 
 
13038
 
Y.extend(DOMEventFacade, Object, {
13039
 
 
13040
 
    init: function() {
13041
 
 
13042
 
        var e = this._event,
13043
 
            overrides = this._wrapper.overrides,
13044
 
            x = e.pageX,
13045
 
            y = e.pageY,
13046
 
            c,
13047
 
            currentTarget = this._currentTarget;
13048
 
 
13049
 
        this.altKey   = e.altKey;
13050
 
        this.ctrlKey  = e.ctrlKey;
13051
 
        this.metaKey  = e.metaKey;
13052
 
        this.shiftKey = e.shiftKey;
13053
 
        this.type     = (overrides && overrides.type) || e.type;
13054
 
        this.clientX  = e.clientX;
13055
 
        this.clientY  = e.clientY;
13056
 
 
13057
 
        this.pageX = x;
13058
 
        this.pageY = y;
13059
 
 
13060
 
        c = e.keyCode || e.charCode;
13061
 
 
13062
 
        if (ua.webkit && (c in webkitKeymap)) {
13063
 
            c = webkitKeymap[c];
13064
 
        }
13065
 
 
13066
 
        this.keyCode = c;
13067
 
        this.charCode = c;
13068
 
        this.which = e.which || e.charCode || c;
13069
 
        // this.button = e.button;
13070
 
        this.button = this.which;
13071
 
 
13072
 
        this.target = resolve(e.target);
13073
 
        this.currentTarget = resolve(currentTarget);
13074
 
        this.relatedTarget = resolve(e.relatedTarget);
13075
 
 
13076
 
        if (e.type == "mousewheel" || e.type == "DOMMouseScroll") {
13077
 
            this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
13078
 
        }
13079
 
 
13080
 
        if (this._touch) {
13081
 
            this._touch(e, currentTarget, this._wrapper);
13082
 
        }
13083
 
    },
13084
 
 
13085
 
    stopPropagation: function() {
13086
 
        this._event.stopPropagation();
13087
 
        this._wrapper.stopped = 1;
13088
 
        this.stopped = 1;
13089
 
    },
13090
 
 
13091
 
    stopImmediatePropagation: function() {
13092
 
        var e = this._event;
13093
 
        if (e.stopImmediatePropagation) {
13094
 
            e.stopImmediatePropagation();
13095
 
        } else {
13096
 
            this.stopPropagation();
13097
 
        }
13098
 
        this._wrapper.stopped = 2;
13099
 
        this.stopped = 2;
13100
 
    },
13101
 
 
13102
 
    preventDefault: function(returnValue) {
13103
 
        var e = this._event;
13104
 
        e.preventDefault();
13105
 
        e.returnValue = returnValue || false;
13106
 
        this._wrapper.prevented = 1;
13107
 
        this.prevented = 1;
13108
 
    },
13109
 
 
13110
 
    halt: function(immediate) {
13111
 
        if (immediate) {
13112
 
            this.stopImmediatePropagation();
13113
 
        } else {
13114
 
            this.stopPropagation();
13115
 
        }
13116
 
 
13117
 
        this.preventDefault();
13118
 
    }
13119
 
 
13120
 
});
13121
 
 
13122
 
DOMEventFacade.resolve = resolve;
13123
 
Y.DOM2EventFacade = DOMEventFacade;
13124
 
Y.DOMEventFacade = DOMEventFacade;
13125
 
 
13126
 
    /**
13127
 
     * The native event
13128
 
     * @property _event
13129
 
     */
13130
 
 
13131
 
    /**
13132
 
     * The X location of the event on the page (including scroll)
13133
 
     * @property pageX
13134
 
     * @type int
13135
 
     */
13136
 
 
13137
 
    /**
13138
 
     * The Y location of the event on the page (including scroll)
13139
 
     * @property pageY
13140
 
     * @type int
13141
 
     */
13142
 
 
13143
 
    /**
13144
 
     * The keyCode for key events.  Uses charCode if keyCode is not available
13145
 
     * @property keyCode
13146
 
     * @type int
13147
 
     */
13148
 
 
13149
 
    /**
13150
 
     * The charCode for key events.  Same as keyCode
13151
 
     * @property charCode
13152
 
     * @type int
13153
 
     */
13154
 
 
13155
 
    /**
13156
 
     * The button that was pushed.
13157
 
     * @property button
13158
 
     * @type int
13159
 
     */
13160
 
 
13161
 
    /**
13162
 
     * The button that was pushed.  Same as button.
13163
 
     * @property which
13164
 
     * @type int
13165
 
     */
13166
 
 
13167
 
    /**
13168
 
     * Node reference for the targeted element
13169
 
     * @propery target
13170
 
     * @type Node
13171
 
     */
13172
 
 
13173
 
    /**
13174
 
     * Node reference for the element that the listener was attached to.
13175
 
     * @propery currentTarget
13176
 
     * @type Node
13177
 
     */
13178
 
 
13179
 
    /**
13180
 
     * Node reference to the relatedTarget
13181
 
     * @propery relatedTarget
13182
 
     * @type Node
13183
 
     */
13184
 
 
13185
 
    /**
13186
 
     * Number representing the direction and velocity of the movement of the mousewheel.
13187
 
     * Negative is down, the higher the number, the faster.  Applies to the mousewheel event.
13188
 
     * @property wheelDelta
13189
 
     * @type int
13190
 
     */
13191
 
 
13192
 
    /**
13193
 
     * Stops the propagation to the next bubble target
13194
 
     * @method stopPropagation
13195
 
     */
13196
 
 
13197
 
    /**
13198
 
     * Stops the propagation to the next bubble target and
13199
 
     * prevents any additional listeners from being exectued
13200
 
     * on the current target.
13201
 
     * @method stopImmediatePropagation
13202
 
     */
13203
 
 
13204
 
    /**
13205
 
     * Prevents the event's default behavior
13206
 
     * @method preventDefault
13207
 
     * @param returnValue {string} sets the returnValue of the event to this value
13208
 
     * (rather than the default false value).  This can be used to add a customized
13209
 
     * confirmation query to the beforeunload event).
13210
 
     */
13211
 
 
13212
 
    /**
13213
 
     * Stops the event propagation and prevents the default
13214
 
     * event behavior.
13215
 
     * @method halt
13216
 
     * @param immediate {boolean} if true additional listeners
13217
 
     * on the current target will not be executed
13218
 
     */
13219
 
(function() {
13220
 
/**
13221
 
 * DOM event listener abstraction layer
13222
 
 * @module event
13223
 
 * @submodule event-base
13224
 
 */
13225
 
 
13226
 
/**
13227
 
 * The event utility provides functions to add and remove event listeners,
13228
 
 * event cleansing.  It also tries to automatically remove listeners it
13229
 
 * registers during the unload event.
13230
 
 *
13231
 
 * @class Event
13232
 
 * @static
13233
 
 */
13234
 
 
13235
 
Y.Env.evt.dom_wrappers = {};
13236
 
Y.Env.evt.dom_map = {};
13237
 
 
13238
 
var _eventenv = Y.Env.evt,
13239
 
    config = Y.config,
13240
 
    win = config.win,
13241
 
    add = YUI.Env.add,
13242
 
    remove = YUI.Env.remove,
13243
 
 
13244
 
    onLoad = function() {
13245
 
        YUI.Env.windowLoaded = true;
13246
 
        Y.Event._load();
13247
 
        remove(win, "load", onLoad);
13248
 
    },
13249
 
 
13250
 
    onUnload = function() {
13251
 
        Y.Event._unload();
13252
 
    },
13253
 
 
13254
 
    EVENT_READY = 'domready',
13255
 
 
13256
 
    COMPAT_ARG = '~yui|2|compat~',
13257
 
 
13258
 
    shouldIterate = function(o) {
13259
 
        try {
13260
 
            return (o && typeof o !== "string" && Y.Lang.isNumber(o.length) &&
13261
 
                    !o.tagName && !o.alert);
13262
 
        } catch(ex) {
13263
 
            Y.log("collection check failure", "warn", "event");
13264
 
            return false;
13265
 
        }
13266
 
 
13267
 
    },
13268
 
 
13269
 
    // aliases to support DOM event subscription clean up when the last
13270
 
    // subscriber is detached. deleteAndClean overrides the DOM event's wrapper
13271
 
    // CustomEvent _delete method.
13272
 
    _ceProtoDelete = Y.CustomEvent.prototype._delete,
13273
 
    _deleteAndClean = function(s) {
13274
 
        var ret = _ceProtoDelete.apply(this, arguments);
13275
 
 
13276
 
        if (!this.subCount && !this.afterCount) {
13277
 
            Y.Event._clean(this);
13278
 
        }
13279
 
 
13280
 
        return ret;
13281
 
    },
13282
 
 
13283
 
Event = function() {
13284
 
 
13285
 
    /**
13286
 
     * True after the onload event has fired
13287
 
     * @property _loadComplete
13288
 
     * @type boolean
13289
 
     * @static
13290
 
     * @private
13291
 
     */
13292
 
    var _loadComplete =  false,
13293
 
 
13294
 
    /**
13295
 
     * The number of times to poll after window.onload.  This number is
13296
 
     * increased if additional late-bound handlers are requested after
13297
 
     * the page load.
13298
 
     * @property _retryCount
13299
 
     * @static
13300
 
     * @private
13301
 
     */
13302
 
    _retryCount = 0,
13303
 
 
13304
 
    /**
13305
 
     * onAvailable listeners
13306
 
     * @property _avail
13307
 
     * @static
13308
 
     * @private
13309
 
     */
13310
 
    _avail = [],
13311
 
 
13312
 
    /**
13313
 
     * Custom event wrappers for DOM events.  Key is
13314
 
     * 'event:' + Element uid stamp + event type
13315
 
     * @property _wrappers
13316
 
     * @type Y.Event.Custom
13317
 
     * @static
13318
 
     * @private
13319
 
     */
13320
 
    _wrappers = _eventenv.dom_wrappers,
13321
 
 
13322
 
    _windowLoadKey = null,
13323
 
 
13324
 
    /**
13325
 
     * Custom event wrapper map DOM events.  Key is
13326
 
     * Element uid stamp.  Each item is a hash of custom event
13327
 
     * wrappers as provided in the _wrappers collection.  This
13328
 
     * provides the infrastructure for getListeners.
13329
 
     * @property _el_events
13330
 
     * @static
13331
 
     * @private
13332
 
     */
13333
 
    _el_events = _eventenv.dom_map;
13334
 
 
13335
 
    return {
13336
 
 
13337
 
        /**
13338
 
         * The number of times we should look for elements that are not
13339
 
         * in the DOM at the time the event is requested after the document
13340
 
         * has been loaded.  The default is 1000@amp;40 ms, so it will poll
13341
 
         * for 40 seconds or until all outstanding handlers are bound
13342
 
         * (whichever comes first).
13343
 
         * @property POLL_RETRYS
13344
 
         * @type int
13345
 
         * @static
13346
 
         * @final
13347
 
         */
13348
 
        POLL_RETRYS: 1000,
13349
 
 
13350
 
        /**
13351
 
         * The poll interval in milliseconds
13352
 
         * @property POLL_INTERVAL
13353
 
         * @type int
13354
 
         * @static
13355
 
         * @final
13356
 
         */
13357
 
        POLL_INTERVAL: 40,
13358
 
 
13359
 
        /**
13360
 
         * addListener/removeListener can throw errors in unexpected scenarios.
13361
 
         * These errors are suppressed, the method returns false, and this property
13362
 
         * is set
13363
 
         * @property lastError
13364
 
         * @static
13365
 
         * @type Error
13366
 
         */
13367
 
        lastError: null,
13368
 
 
13369
 
 
13370
 
        /**
13371
 
         * poll handle
13372
 
         * @property _interval
13373
 
         * @static
13374
 
         * @private
13375
 
         */
13376
 
        _interval: null,
13377
 
 
13378
 
        /**
13379
 
         * document readystate poll handle
13380
 
         * @property _dri
13381
 
         * @static
13382
 
         * @private
13383
 
         */
13384
 
         _dri: null,
13385
 
 
13386
 
        /**
13387
 
         * True when the document is initially usable
13388
 
         * @property DOMReady
13389
 
         * @type boolean
13390
 
         * @static
13391
 
         */
13392
 
        DOMReady: false,
13393
 
 
13394
 
        /**
13395
 
         * @method startInterval
13396
 
         * @static
13397
 
         * @private
13398
 
         */
13399
 
        startInterval: function() {
13400
 
            if (!Event._interval) {
13401
 
Event._interval = setInterval(Event._poll, Event.POLL_INTERVAL);
13402
 
            }
13403
 
        },
13404
 
 
13405
 
        /**
13406
 
         * Executes the supplied callback when the item with the supplied
13407
 
         * id is found.  This is meant to be used to execute behavior as
13408
 
         * soon as possible as the page loads.  If you use this after the
13409
 
         * initial page load it will poll for a fixed time for the element.
13410
 
         * The number of times it will poll and the frequency are
13411
 
         * configurable.  By default it will poll for 10 seconds.
13412
 
         *
13413
 
         * <p>The callback is executed with a single parameter:
13414
 
         * the custom object parameter, if provided.</p>
13415
 
         *
13416
 
         * @method onAvailable
13417
 
         *
13418
 
         * @param {string||string[]}   id the id of the element, or an array
13419
 
         * of ids to look for.
13420
 
         * @param {function} fn what to execute when the element is found.
13421
 
         * @param {object}   p_obj an optional object to be passed back as
13422
 
         *                   a parameter to fn.
13423
 
         * @param {boolean|object}  p_override If set to true, fn will execute
13424
 
         *                   in the context of p_obj, if set to an object it
13425
 
         *                   will execute in the context of that object
13426
 
         * @param checkContent {boolean} check child node readiness (onContentReady)
13427
 
         * @static
13428
 
         * @deprecated Use Y.on("available")
13429
 
         */
13430
 
        // @TODO fix arguments
13431
 
        onAvailable: function(id, fn, p_obj, p_override, checkContent, compat) {
13432
 
 
13433
 
            var a = Y.Array(id), i, availHandle;
13434
 
 
13435
 
            // Y.log('onAvailable registered for: ' + id);
13436
 
 
13437
 
            for (i=0; i<a.length; i=i+1) {
13438
 
                _avail.push({
13439
 
                    id:         a[i],
13440
 
                    fn:         fn,
13441
 
                    obj:        p_obj,
13442
 
                    override:   p_override,
13443
 
                    checkReady: checkContent,
13444
 
                    compat:     compat
13445
 
                });
13446
 
            }
13447
 
            _retryCount = this.POLL_RETRYS;
13448
 
 
13449
 
            // We want the first test to be immediate, but async
13450
 
            setTimeout(Event._poll, 0);
13451
 
 
13452
 
            availHandle = new Y.EventHandle({
13453
 
 
13454
 
                _delete: function() {
13455
 
                    // set by the event system for lazy DOM listeners
13456
 
                    if (availHandle.handle) {
13457
 
                        availHandle.handle.detach();
13458
 
                        return;
13459
 
                    }
13460
 
 
13461
 
                    var i, j;
13462
 
 
13463
 
                    // otherwise try to remove the onAvailable listener(s)
13464
 
                    for (i = 0; i < a.length; i++) {
13465
 
                        for (j = 0; j < _avail.length; j++) {
13466
 
                            if (a[i] === _avail[j].id) {
13467
 
                                _avail.splice(j, 1);
13468
 
                            }
13469
 
                        }
13470
 
                    }
13471
 
                }
13472
 
 
13473
 
            });
13474
 
 
13475
 
            return availHandle;
13476
 
        },
13477
 
 
13478
 
        /**
13479
 
         * Works the same way as onAvailable, but additionally checks the
13480
 
         * state of sibling elements to determine if the content of the
13481
 
         * available element is safe to modify.
13482
 
         *
13483
 
         * <p>The callback is executed with a single parameter:
13484
 
         * the custom object parameter, if provided.</p>
13485
 
         *
13486
 
         * @method onContentReady
13487
 
         *
13488
 
         * @param {string}   id the id of the element to look for.
13489
 
         * @param {function} fn what to execute when the element is ready.
13490
 
         * @param {object}   obj an optional object to be passed back as
13491
 
         *                   a parameter to fn.
13492
 
         * @param {boolean|object}  override If set to true, fn will execute
13493
 
         *                   in the context of p_obj.  If an object, fn will
13494
 
         *                   exectute in the context of that object
13495
 
         *
13496
 
         * @static
13497
 
         * @deprecated Use Y.on("contentready")
13498
 
         */
13499
 
        // @TODO fix arguments
13500
 
        onContentReady: function(id, fn, obj, override, compat) {
13501
 
            return Event.onAvailable(id, fn, obj, override, true, compat);
13502
 
        },
13503
 
 
13504
 
        /**
13505
 
         * Adds an event listener
13506
 
         *
13507
 
         * @method attach
13508
 
         *
13509
 
         * @param {String}   type     The type of event to append
13510
 
         * @param {Function} fn        The method the event invokes
13511
 
         * @param {String|HTMLElement|Array|NodeList} el An id, an element
13512
 
         *  reference, or a collection of ids and/or elements to assign the
13513
 
         *  listener to.
13514
 
         * @param {Object}   context optional context object
13515
 
         * @param {Boolean|object}  args 0..n arguments to pass to the callback
13516
 
         * @return {EventHandle} an object to that can be used to detach the listener
13517
 
         *
13518
 
         * @static
13519
 
         */
13520
 
 
13521
 
        attach: function(type, fn, el, context) {
13522
 
            return Event._attach(Y.Array(arguments, 0, true));
13523
 
        },
13524
 
 
13525
 
        _createWrapper: function (el, type, capture, compat, facade) {
13526
 
 
13527
 
            var cewrapper,
13528
 
                ek  = Y.stamp(el),
13529
 
                key = 'event:' + ek + type;
13530
 
 
13531
 
            if (false === facade) {
13532
 
                key += 'native';
13533
 
            }
13534
 
            if (capture) {
13535
 
                key += 'capture';
13536
 
            }
13537
 
 
13538
 
 
13539
 
            cewrapper = _wrappers[key];
13540
 
 
13541
 
 
13542
 
            if (!cewrapper) {
13543
 
                // create CE wrapper
13544
 
                cewrapper = Y.publish(key, {
13545
 
                    silent: true,
13546
 
                    bubbles: false,
13547
 
                    contextFn: function() {
13548
 
                        if (compat) {
13549
 
                            return cewrapper.el;
13550
 
                        } else {
13551
 
                            cewrapper.nodeRef = cewrapper.nodeRef || Y.one(cewrapper.el);
13552
 
                            return cewrapper.nodeRef;
13553
 
                        }
13554
 
                    }
13555
 
                });
13556
 
 
13557
 
                cewrapper.overrides = {};
13558
 
 
13559
 
                // for later removeListener calls
13560
 
                cewrapper.el = el;
13561
 
                cewrapper.key = key;
13562
 
                cewrapper.domkey = ek;
13563
 
                cewrapper.type = type;
13564
 
                cewrapper.fn = function(e) {
13565
 
                    cewrapper.fire(Event.getEvent(e, el, (compat || (false === facade))));
13566
 
                };
13567
 
                cewrapper.capture = capture;
13568
 
 
13569
 
                if (el == win && type == "load") {
13570
 
                    // window load happens once
13571
 
                    cewrapper.fireOnce = true;
13572
 
                    _windowLoadKey = key;
13573
 
                }
13574
 
                cewrapper._delete = _deleteAndClean;
13575
 
 
13576
 
                _wrappers[key] = cewrapper;
13577
 
                _el_events[ek] = _el_events[ek] || {};
13578
 
                _el_events[ek][key] = cewrapper;
13579
 
 
13580
 
                add(el, type, cewrapper.fn, capture);
13581
 
            }
13582
 
 
13583
 
            return cewrapper;
13584
 
 
13585
 
        },
13586
 
 
13587
 
        _attach: function(args, conf) {
13588
 
 
13589
 
            var compat,
13590
 
                handles, oEl, cewrapper, context,
13591
 
                fireNow = false, ret,
13592
 
                type = args[0],
13593
 
                fn = args[1],
13594
 
                el = args[2] || win,
13595
 
                facade = conf && conf.facade,
13596
 
                capture = conf && conf.capture,
13597
 
                overrides = conf && conf.overrides;
13598
 
 
13599
 
            if (args[args.length-1] === COMPAT_ARG) {
13600
 
                compat = true;
13601
 
            }
13602
 
 
13603
 
            if (!fn || !fn.call) {
13604
 
// throw new TypeError(type + " attach call failed, callback undefined");
13605
 
Y.log(type + " attach call failed, invalid callback", "error", "event");
13606
 
                return false;
13607
 
            }
13608
 
 
13609
 
            // The el argument can be an array of elements or element ids.
13610
 
            if (shouldIterate(el)) {
13611
 
 
13612
 
                handles=[];
13613
 
 
13614
 
                Y.each(el, function(v, k) {
13615
 
                    args[2] = v;
13616
 
                    handles.push(Event._attach(args.slice(), conf));
13617
 
                });
13618
 
 
13619
 
                // return (handles.length === 1) ? handles[0] : handles;
13620
 
                return new Y.EventHandle(handles);
13621
 
 
13622
 
            // If the el argument is a string, we assume it is
13623
 
            // actually the id of the element.  If the page is loaded
13624
 
            // we convert el to the actual element, otherwise we
13625
 
            // defer attaching the event until the element is
13626
 
            // ready
13627
 
            } else if (Y.Lang.isString(el)) {
13628
 
 
13629
 
                // oEl = (compat) ? Y.DOM.byId(el) : Y.Selector.query(el);
13630
 
 
13631
 
                if (compat) {
13632
 
                    oEl = Y.DOM.byId(el);
13633
 
                } else {
13634
 
 
13635
 
                    oEl = Y.Selector.query(el);
13636
 
 
13637
 
                    switch (oEl.length) {
13638
 
                        case 0:
13639
 
                            oEl = null;
13640
 
                            break;
13641
 
                        case 1:
13642
 
                            oEl = oEl[0];
13643
 
                            break;
13644
 
                        default:
13645
 
                            args[2] = oEl;
13646
 
                            return Event._attach(args, conf);
13647
 
                    }
13648
 
                }
13649
 
 
13650
 
                if (oEl) {
13651
 
 
13652
 
                    el = oEl;
13653
 
 
13654
 
                // Not found = defer adding the event until the element is available
13655
 
                } else {
13656
 
 
13657
 
                    // Y.log(el + ' not found');
13658
 
                    ret = Event.onAvailable(el, function() {
13659
 
                        // Y.log('lazy attach: ' + args);
13660
 
 
13661
 
                        ret.handle = Event._attach(args, conf);
13662
 
 
13663
 
                    }, Event, true, false, compat);
13664
 
 
13665
 
                    return ret;
13666
 
 
13667
 
                }
13668
 
            }
13669
 
 
13670
 
            // Element should be an html element or node
13671
 
            if (!el) {
13672
 
                Y.log("unable to attach event " + type, "warn", "event");
13673
 
                return false;
13674
 
            }
13675
 
 
13676
 
            if (Y.Node && Y.instanceOf(el, Y.Node)) {
13677
 
                el = Y.Node.getDOMNode(el);
13678
 
            }
13679
 
 
13680
 
            cewrapper = Event._createWrapper(el, type, capture, compat, facade);
13681
 
            if (overrides) {
13682
 
                Y.mix(cewrapper.overrides, overrides);
13683
 
            }
13684
 
 
13685
 
            if (el == win && type == "load") {
13686
 
 
13687
 
                // if the load is complete, fire immediately.
13688
 
                // all subscribers, including the current one
13689
 
                // will be notified.
13690
 
                if (YUI.Env.windowLoaded) {
13691
 
                    fireNow = true;
13692
 
                }
13693
 
            }
13694
 
 
13695
 
            if (compat) {
13696
 
                args.pop();
13697
 
            }
13698
 
 
13699
 
            context = args[3];
13700
 
 
13701
 
            // set context to the Node if not specified
13702
 
            // ret = cewrapper.on.apply(cewrapper, trimmedArgs);
13703
 
            ret = cewrapper._on(fn, context, (args.length > 4) ? args.slice(4) : null);
13704
 
 
13705
 
            if (fireNow) {
13706
 
                cewrapper.fire();
13707
 
            }
13708
 
 
13709
 
            return ret;
13710
 
 
13711
 
        },
13712
 
 
13713
 
        /**
13714
 
         * Removes an event listener.  Supports the signature the event was bound
13715
 
         * with, but the preferred way to remove listeners is using the handle
13716
 
         * that is returned when using Y.on
13717
 
         *
13718
 
         * @method detach
13719
 
         *
13720
 
         * @param {String} type the type of event to remove.
13721
 
         * @param {Function} fn the method the event invokes.  If fn is
13722
 
         * undefined, then all event handlers for the type of event are
13723
 
         * removed.
13724
 
         * @param {String|HTMLElement|Array|NodeList|EventHandle} el An
13725
 
         * event handle, an id, an element reference, or a collection
13726
 
         * of ids and/or elements to remove the listener from.
13727
 
         * @return {boolean} true if the unbind was successful, false otherwise.
13728
 
         * @static
13729
 
         */
13730
 
        detach: function(type, fn, el, obj) {
13731
 
 
13732
 
            var args=Y.Array(arguments, 0, true), compat, l, ok, i,
13733
 
                id, ce;
13734
 
 
13735
 
            if (args[args.length-1] === COMPAT_ARG) {
13736
 
                compat = true;
13737
 
                // args.pop();
13738
 
            }
13739
 
 
13740
 
            if (type && type.detach) {
13741
 
                return type.detach();
13742
 
            }
13743
 
 
13744
 
            // The el argument can be a string
13745
 
            if (typeof el == "string") {
13746
 
 
13747
 
                // el = (compat) ? Y.DOM.byId(el) : Y.all(el);
13748
 
                if (compat) {
13749
 
                    el = Y.DOM.byId(el);
13750
 
                } else {
13751
 
                    el = Y.Selector.query(el);
13752
 
                    l = el.length;
13753
 
                    if (l < 1) {
13754
 
                        el = null;
13755
 
                    } else if (l == 1) {
13756
 
                        el = el[0];
13757
 
                    }
13758
 
                }
13759
 
                // return Event.detach.apply(Event, args);
13760
 
            }
13761
 
 
13762
 
            if (!el) {
13763
 
                return false;
13764
 
            }
13765
 
 
13766
 
            if (el.detach) {
13767
 
                args.splice(2, 1);
13768
 
                return el.detach.apply(el, args);
13769
 
            // The el argument can be an array of elements or element ids.
13770
 
            } else if (shouldIterate(el)) {
13771
 
                ok = true;
13772
 
                for (i=0, l=el.length; i<l; ++i) {
13773
 
                    args[2] = el[i];
13774
 
                    ok = ( Y.Event.detach.apply(Y.Event, args) && ok );
13775
 
                }
13776
 
 
13777
 
                return ok;
13778
 
            }
13779
 
 
13780
 
            if (!type || !fn || !fn.call) {
13781
 
                return Event.purgeElement(el, false, type);
13782
 
            }
13783
 
 
13784
 
            id = 'event:' + Y.stamp(el) + type;
13785
 
            ce = _wrappers[id];
13786
 
 
13787
 
            if (ce) {
13788
 
                return ce.detach(fn);
13789
 
            } else {
13790
 
                return false;
13791
 
            }
13792
 
 
13793
 
        },
13794
 
 
13795
 
        /**
13796
 
         * Finds the event in the window object, the caller's arguments, or
13797
 
         * in the arguments of another method in the callstack.  This is
13798
 
         * executed automatically for events registered through the event
13799
 
         * manager, so the implementer should not normally need to execute
13800
 
         * this function at all.
13801
 
         * @method getEvent
13802
 
         * @param {Event} e the event parameter from the handler
13803
 
         * @param {HTMLElement} el the element the listener was attached to
13804
 
         * @return {Event} the event
13805
 
         * @static
13806
 
         */
13807
 
        getEvent: function(e, el, noFacade) {
13808
 
            var ev = e || win.event;
13809
 
 
13810
 
            return (noFacade) ? ev :
13811
 
                new Y.DOMEventFacade(ev, el, _wrappers['event:' + Y.stamp(el) + e.type]);
13812
 
        },
13813
 
 
13814
 
        /**
13815
 
         * Generates an unique ID for the element if it does not already
13816
 
         * have one.
13817
 
         * @method generateId
13818
 
         * @param el the element to create the id for
13819
 
         * @return {string} the resulting id of the element
13820
 
         * @static
13821
 
         */
13822
 
        generateId: function(el) {
13823
 
            return Y.DOM.generateID(el);
13824
 
        },
13825
 
 
13826
 
        /**
13827
 
         * We want to be able to use getElementsByTagName as a collection
13828
 
         * to attach a group of events to.  Unfortunately, different
13829
 
         * browsers return different types of collections.  This function
13830
 
         * tests to determine if the object is array-like.  It will also
13831
 
         * fail if the object is an array, but is empty.
13832
 
         * @method _isValidCollection
13833
 
         * @param o the object to test
13834
 
         * @return {boolean} true if the object is array-like and populated
13835
 
         * @deprecated was not meant to be used directly
13836
 
         * @static
13837
 
         * @private
13838
 
         */
13839
 
        _isValidCollection: shouldIterate,
13840
 
 
13841
 
        /**
13842
 
         * hook up any deferred listeners
13843
 
         * @method _load
13844
 
         * @static
13845
 
         * @private
13846
 
         */
13847
 
        _load: function(e) {
13848
 
            if (!_loadComplete) {
13849
 
                // Y.log('Load Complete', 'info', 'event');
13850
 
                _loadComplete = true;
13851
 
 
13852
 
                // Just in case DOMReady did not go off for some reason
13853
 
                // E._ready();
13854
 
                if (Y.fire) {
13855
 
                    Y.fire(EVENT_READY);
13856
 
                }
13857
 
 
13858
 
                // Available elements may not have been detected before the
13859
 
                // window load event fires. Try to find them now so that the
13860
 
                // the user is more likely to get the onAvailable notifications
13861
 
                // before the window load notification
13862
 
                Event._poll();
13863
 
            }
13864
 
        },
13865
 
 
13866
 
        /**
13867
 
         * Polling function that runs before the onload event fires,
13868
 
         * attempting to attach to DOM Nodes as soon as they are
13869
 
         * available
13870
 
         * @method _poll
13871
 
         * @static
13872
 
         * @private
13873
 
         */
13874
 
        _poll: function() {
13875
 
            if (Event.locked) {
13876
 
                return;
13877
 
            }
13878
 
 
13879
 
            if (Y.UA.ie && !YUI.Env.DOMReady) {
13880
 
                // Hold off if DOMReady has not fired and check current
13881
 
                // readyState to protect against the IE operation aborted
13882
 
                // issue.
13883
 
                Event.startInterval();
13884
 
                return;
13885
 
            }
13886
 
 
13887
 
            Event.locked = true;
13888
 
 
13889
 
            // Y.log.debug("poll");
13890
 
            // keep trying until after the page is loaded.  We need to
13891
 
            // check the page load state prior to trying to bind the
13892
 
            // elements so that we can be certain all elements have been
13893
 
            // tested appropriately
13894
 
            var i, len, item, el, notAvail, executeItem,
13895
 
                tryAgain = !_loadComplete;
13896
 
 
13897
 
            if (!tryAgain) {
13898
 
                tryAgain = (_retryCount > 0);
13899
 
            }
13900
 
 
13901
 
            // onAvailable
13902
 
            notAvail = [];
13903
 
 
13904
 
            executeItem = function (el, item) {
13905
 
                var context, ov = item.override;
13906
 
                if (item.compat) {
13907
 
                    if (item.override) {
13908
 
                        if (ov === true) {
13909
 
                            context = item.obj;
13910
 
                        } else {
13911
 
                            context = ov;
13912
 
                        }
13913
 
                    } else {
13914
 
                        context = el;
13915
 
                    }
13916
 
                    item.fn.call(context, item.obj);
13917
 
                } else {
13918
 
                    context = item.obj || Y.one(el);
13919
 
                    item.fn.apply(context, (Y.Lang.isArray(ov)) ? ov : []);
13920
 
                }
13921
 
            };
13922
 
 
13923
 
            // onAvailable
13924
 
            for (i=0,len=_avail.length; i<len; ++i) {
13925
 
                item = _avail[i];
13926
 
                if (item && !item.checkReady) {
13927
 
 
13928
 
                    // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
13929
 
                    el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
13930
 
 
13931
 
                    if (el) {
13932
 
                        // Y.log('avail: ' + el);
13933
 
                        executeItem(el, item);
13934
 
                        _avail[i] = null;
13935
 
                    } else {
13936
 
                        // Y.log('NOT avail: ' + el);
13937
 
                        notAvail.push(item);
13938
 
                    }
13939
 
                }
13940
 
            }
13941
 
 
13942
 
            // onContentReady
13943
 
            for (i=0,len=_avail.length; i<len; ++i) {
13944
 
                item = _avail[i];
13945
 
                if (item && item.checkReady) {
13946
 
 
13947
 
                    // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
13948
 
                    el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
13949
 
 
13950
 
                    if (el) {
13951
 
                        // The element is available, but not necessarily ready
13952
 
                        // @todo should we test parentNode.nextSibling?
13953
 
                        if (_loadComplete || (el.get && el.get('nextSibling')) || el.nextSibling) {
13954
 
                            executeItem(el, item);
13955
 
                            _avail[i] = null;
13956
 
                        }
13957
 
                    } else {
13958
 
                        notAvail.push(item);
13959
 
                    }
13960
 
                }
13961
 
            }
13962
 
 
13963
 
            _retryCount = (notAvail.length === 0) ? 0 : _retryCount - 1;
13964
 
 
13965
 
            if (tryAgain) {
13966
 
                // we may need to strip the nulled out items here
13967
 
                Event.startInterval();
13968
 
            } else {
13969
 
                clearInterval(Event._interval);
13970
 
                Event._interval = null;
13971
 
            }
13972
 
 
13973
 
            Event.locked = false;
13974
 
 
13975
 
            return;
13976
 
 
13977
 
        },
13978
 
 
13979
 
        /**
13980
 
         * Removes all listeners attached to the given element via addListener.
13981
 
         * Optionally, the node's children can also be purged.
13982
 
         * Optionally, you can specify a specific type of event to remove.
13983
 
         * @method purgeElement
13984
 
         * @param {HTMLElement} el the element to purge
13985
 
         * @param {boolean} recurse recursively purge this element's children
13986
 
         * as well.  Use with caution.
13987
 
         * @param {string} type optional type of listener to purge. If
13988
 
         * left out, all listeners will be removed
13989
 
         * @static
13990
 
         */
13991
 
        purgeElement: function(el, recurse, type) {
13992
 
            // var oEl = (Y.Lang.isString(el)) ? Y.one(el) : el,
13993
 
            var oEl = (Y.Lang.isString(el)) ?  Y.Selector.query(el, null, true) : el,
13994
 
                lis = Event.getListeners(oEl, type), i, len, children, child;
13995
 
 
13996
 
            if (recurse && oEl) {
13997
 
                lis = lis || [];
13998
 
                children = Y.Selector.query('*', oEl);
13999
 
                i = 0;
14000
 
                len = children.length;
14001
 
                for (; i < len; ++i) {
14002
 
                    child = Event.getListeners(children[i], type);
14003
 
                    if (child) {
14004
 
                        lis = lis.concat(child);
14005
 
                    }
14006
 
                }
14007
 
            }
14008
 
 
14009
 
            if (lis) {
14010
 
                for (i = 0, len = lis.length; i < len; ++i) {
14011
 
                    lis[i].detachAll();
14012
 
                }
14013
 
            }
14014
 
 
14015
 
        },
14016
 
 
14017
 
        /**
14018
 
         * Removes all object references and the DOM proxy subscription for
14019
 
         * a given event for a DOM node.
14020
 
         *
14021
 
         * @method _clean
14022
 
         * @param wrapper {CustomEvent} Custom event proxy for the DOM
14023
 
         *                  subscription
14024
 
         * @private
14025
 
         * @static
14026
 
         * @since 3.4.0
14027
 
         */
14028
 
        _clean: function (wrapper) {
14029
 
            var key    = wrapper.key,
14030
 
                domkey = wrapper.domkey;
14031
 
 
14032
 
            remove(wrapper.el, wrapper.type, wrapper.fn, wrapper.capture);
14033
 
            delete _wrappers[key];
14034
 
            delete Y._yuievt.events[key];
14035
 
            if (_el_events[domkey]) {
14036
 
                delete _el_events[domkey][key];
14037
 
                if (!Y.Object.size(_el_events[domkey])) {
14038
 
                    delete _el_events[domkey];
14039
 
                }
14040
 
            }
14041
 
        },
14042
 
 
14043
 
        /**
14044
 
         * Returns all listeners attached to the given element via addListener.
14045
 
         * Optionally, you can specify a specific type of event to return.
14046
 
         * @method getListeners
14047
 
         * @param el {HTMLElement|string} the element or element id to inspect
14048
 
         * @param type {string} optional type of listener to return. If
14049
 
         * left out, all listeners will be returned
14050
 
         * @return {Y.Custom.Event} the custom event wrapper for the DOM event(s)
14051
 
         * @static
14052
 
         */
14053
 
        getListeners: function(el, type) {
14054
 
            var ek = Y.stamp(el, true), evts = _el_events[ek],
14055
 
                results=[] , key = (type) ? 'event:' + ek + type : null,
14056
 
                adapters = _eventenv.plugins;
14057
 
 
14058
 
            if (!evts) {
14059
 
                return null;
14060
 
            }
14061
 
 
14062
 
            if (key) {
14063
 
                // look for synthetic events
14064
 
                if (adapters[type] && adapters[type].eventDef) {
14065
 
                    key += '_synth';
14066
 
                }
14067
 
 
14068
 
                if (evts[key]) {
14069
 
                    results.push(evts[key]);
14070
 
                }
14071
 
 
14072
 
                // get native events as well
14073
 
                key += 'native';
14074
 
                if (evts[key]) {
14075
 
                    results.push(evts[key]);
14076
 
                }
14077
 
 
14078
 
            } else {
14079
 
                Y.each(evts, function(v, k) {
14080
 
                    results.push(v);
14081
 
                });
14082
 
            }
14083
 
 
14084
 
            return (results.length) ? results : null;
14085
 
        },
14086
 
 
14087
 
        /**
14088
 
         * Removes all listeners registered by pe.event.  Called
14089
 
         * automatically during the unload event.
14090
 
         * @method _unload
14091
 
         * @static
14092
 
         * @private
14093
 
         */
14094
 
        _unload: function(e) {
14095
 
            Y.each(_wrappers, function(v, k) {
14096
 
                if (v.type == 'unload') {
14097
 
                    v.fire(e);
14098
 
                }
14099
 
                v.detachAll();
14100
 
            });
14101
 
            remove(win, "unload", onUnload);
14102
 
        },
14103
 
 
14104
 
        /**
14105
 
         * Adds a DOM event directly without the caching, cleanup, context adj, etc
14106
 
         *
14107
 
         * @method nativeAdd
14108
 
         * @param {HTMLElement} el      the element to bind the handler to
14109
 
         * @param {string}      type   the type of event handler
14110
 
         * @param {function}    fn      the callback to invoke
14111
 
         * @param {boolen}      capture capture or bubble phase
14112
 
         * @static
14113
 
         * @private
14114
 
         */
14115
 
        nativeAdd: add,
14116
 
 
14117
 
        /**
14118
 
         * Basic remove listener
14119
 
         *
14120
 
         * @method nativeRemove
14121
 
         * @param {HTMLElement} el      the element to bind the handler to
14122
 
         * @param {string}      type   the type of event handler
14123
 
         * @param {function}    fn      the callback to invoke
14124
 
         * @param {boolen}      capture capture or bubble phase
14125
 
         * @static
14126
 
         * @private
14127
 
         */
14128
 
        nativeRemove: remove
14129
 
    };
14130
 
 
14131
 
}();
14132
 
 
14133
 
Y.Event = Event;
14134
 
 
14135
 
if (config.injected || YUI.Env.windowLoaded) {
14136
 
    onLoad();
14137
 
} else {
14138
 
    add(win, "load", onLoad);
14139
 
}
14140
 
 
14141
 
// Process onAvailable/onContentReady items when when the DOM is ready in IE
14142
 
if (Y.UA.ie) {
14143
 
    Y.on(EVENT_READY, Event._poll);
14144
 
}
14145
 
 
14146
 
add(win, "unload", onUnload);
14147
 
 
14148
 
Event.Custom = Y.CustomEvent;
14149
 
Event.Subscriber = Y.Subscriber;
14150
 
Event.Target = Y.EventTarget;
14151
 
Event.Handle = Y.EventHandle;
14152
 
Event.Facade = Y.EventFacade;
14153
 
 
14154
 
Event._poll();
14155
 
 
14156
 
})();
14157
 
 
14158
 
/**
14159
 
 * DOM event listener abstraction layer
14160
 
 * @module event
14161
 
 * @submodule event-base
14162
 
 */
14163
 
 
14164
 
/**
14165
 
 * Executes the callback as soon as the specified element
14166
 
 * is detected in the DOM.  This function expects a selector
14167
 
 * string for the element(s) to detect.  If you already have
14168
 
 * an element reference, you don't need this event.
14169
 
 * @event available
14170
 
 * @param type {string} 'available'
14171
 
 * @param fn {function} the callback function to execute.
14172
 
 * @param el {string} an selector for the element(s) to attach
14173
 
 * @param context optional argument that specifies what 'this' refers to.
14174
 
 * @param args* 0..n additional arguments to pass on to the callback function.
14175
 
 * These arguments will be added after the event object.
14176
 
 * @return {EventHandle} the detach handle
14177
 
 * @for YUI
14178
 
 */
14179
 
Y.Env.evt.plugins.available = {
14180
 
    on: function(type, fn, id, o) {
14181
 
        var a = arguments.length > 4 ?  Y.Array(arguments, 4, true) : null;
14182
 
        return Y.Event.onAvailable.call(Y.Event, id, fn, o, a);
14183
 
    }
14184
 
};
14185
 
 
14186
 
/**
14187
 
 * Executes the callback as soon as the specified element
14188
 
 * is detected in the DOM with a nextSibling property
14189
 
 * (indicating that the element's children are available).
14190
 
 * This function expects a selector
14191
 
 * string for the element(s) to detect.  If you already have
14192
 
 * an element reference, you don't need this event.
14193
 
 * @event contentready
14194
 
 * @param type {string} 'contentready'
14195
 
 * @param fn {function} the callback function to execute.
14196
 
 * @param el {string} an selector for the element(s) to attach.
14197
 
 * @param context optional argument that specifies what 'this' refers to.
14198
 
 * @param args* 0..n additional arguments to pass on to the callback function.
14199
 
 * These arguments will be added after the event object.
14200
 
 * @return {EventHandle} the detach handle
14201
 
 * @for YUI
14202
 
 */
14203
 
Y.Env.evt.plugins.contentready = {
14204
 
    on: function(type, fn, id, o) {
14205
 
        var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
14206
 
        return Y.Event.onContentReady.call(Y.Event, id, fn, o, a);
14207
 
    }
14208
 
};
14209
 
 
14210
 
 
14211
 
}, '3.4.1' ,{requires:['event-custom-base']});
14212
 
YUI.add('pluginhost-base', function(Y) {
14213
 
 
14214
 
    /**
14215
 
     * Provides the augmentable PluginHost interface, which can be added to any class.
14216
 
     * @module pluginhost
14217
 
     */
14218
 
 
14219
 
    /**
14220
 
     * Provides the augmentable PluginHost interface, which can be added to any class.
14221
 
     * @module pluginhost-base
14222
 
     */
14223
 
 
14224
 
    /**
14225
 
     * <p>
14226
 
     * An augmentable class, which provides the augmented class with the ability to host plugins.
14227
 
     * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can 
14228
 
     * be used to add or remove plugins from instances of the class.
14229
 
     * </p>
14230
 
     *
14231
 
     * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using
14232
 
     * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method. 
14233
 
     * 
14234
 
     * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
14235
 
     * <xmp>
14236
 
     * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
14237
 
     * </xmp>
14238
 
     * </p>
14239
 
     * <p>
14240
 
     * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a> 
14241
 
     * methods should be invoked by the host class at the appropriate point in the host's lifecyle.  
14242
 
     * </p>
14243
 
     *
14244
 
     * @class Plugin.Host
14245
 
     */
14246
 
 
14247
 
    var L = Y.Lang;
14248
 
 
14249
 
    function PluginHost() {
14250
 
        this._plugins = {};
14251
 
    }
14252
 
 
14253
 
    PluginHost.prototype = {
14254
 
 
14255
 
        /**
14256
 
         * Adds a plugin to the host object. This will instantiate the 
14257
 
         * plugin and attach it to the configured namespace on the host object.
14258
 
         *
14259
 
         * @method plug
14260
 
         * @chainable
14261
 
         * @param P {Function | Object |Array} Accepts the plugin class, or an 
14262
 
         * object with a "fn" property specifying the plugin class and 
14263
 
         * a "cfg" property specifying the configuration for the Plugin.
14264
 
         * <p>
14265
 
         * Additionally an Array can also be passed in, with the above function or 
14266
 
         * object values, allowing the user to add multiple plugins in a single call.
14267
 
         * </p>
14268
 
         * @param config (Optional) If the first argument is the plugin class, the second argument
14269
 
         * can be the configuration for the plugin.
14270
 
         * @return {Base} A reference to the host object
14271
 
         */
14272
 
        plug: function(Plugin, config) {
14273
 
            var i, ln, ns;
14274
 
 
14275
 
            if (L.isArray(Plugin)) {
14276
 
                for (i = 0, ln = Plugin.length; i < ln; i++) {
14277
 
                    this.plug(Plugin[i]);
14278
 
                }
14279
 
            } else {
14280
 
                if (Plugin && !L.isFunction(Plugin)) {
14281
 
                    config = Plugin.cfg;
14282
 
                    Plugin = Plugin.fn;
14283
 
                }
14284
 
 
14285
 
                // Plugin should be fn by now
14286
 
                if (Plugin && Plugin.NS) {
14287
 
                    ns = Plugin.NS;
14288
 
        
14289
 
                    config = config || {};
14290
 
                    config.host = this;
14291
 
        
14292
 
                    if (this.hasPlugin(ns)) {
14293
 
                        // Update config
14294
 
                        this[ns].setAttrs(config);
14295
 
                    } else {
14296
 
                        // Create new instance
14297
 
                        this[ns] = new Plugin(config);
14298
 
                        this._plugins[ns] = Plugin;
14299
 
                    }
14300
 
                }
14301
 
                else { Y.log("Attempt to plug in an invalid plugin. Host:" + this + ", Plugin:" + Plugin); }
14302
 
            }
14303
 
            return this;
14304
 
        },
14305
 
 
14306
 
        /**
14307
 
         * Removes a plugin from the host object. This will destroy the 
14308
 
         * plugin instance and delete the namepsace from the host object. 
14309
 
         *
14310
 
         * @method unplug
14311
 
         * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
14312
 
         * all registered plugins are unplugged.
14313
 
         * @return {Base} A reference to the host object
14314
 
         * @chainable
14315
 
         */
14316
 
        unplug: function(plugin) {
14317
 
            var ns = plugin, 
14318
 
                plugins = this._plugins;
14319
 
            
14320
 
            if (plugin) {
14321
 
                if (L.isFunction(plugin)) {
14322
 
                    ns = plugin.NS;
14323
 
                    if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
14324
 
                        ns = null;
14325
 
                    }
14326
 
                }
14327
 
        
14328
 
                if (ns) {
14329
 
                    if (this[ns]) {
14330
 
                        this[ns].destroy();
14331
 
                        delete this[ns];
14332
 
                    }
14333
 
                    if (plugins[ns]) {
14334
 
                        delete plugins[ns];
14335
 
                    }
14336
 
                }
14337
 
            } else {
14338
 
                for (ns in this._plugins) {
14339
 
                    if (this._plugins.hasOwnProperty(ns)) {
14340
 
                        this.unplug(ns);
14341
 
                    }
14342
 
                }
14343
 
            }
14344
 
            return this;
14345
 
        },
14346
 
 
14347
 
        /**
14348
 
         * Determines if a plugin has plugged into this host.
14349
 
         *
14350
 
         * @method hasPlugin
14351
 
         * @param {String} ns The plugin's namespace
14352
 
         * @return {boolean} returns true, if the plugin has been plugged into this host, false otherwise.
14353
 
         */
14354
 
        hasPlugin : function(ns) {
14355
 
            return (this._plugins[ns] && this[ns]);
14356
 
        },
14357
 
 
14358
 
        /**
14359
 
         * Initializes static plugins registered on the host (using the
14360
 
         * Base.plug static method) and any plugins passed to the 
14361
 
         * instance through the "plugins" configuration property.
14362
 
         *
14363
 
         * @method _initPlugins
14364
 
         * @param {Config} config The configuration object with property name/value pairs.
14365
 
         * @private
14366
 
         */
14367
 
        
14368
 
        _initPlugins: function(config) {
14369
 
            this._plugins = this._plugins || {};
14370
 
 
14371
 
            if (this._initConfigPlugins) {
14372
 
                this._initConfigPlugins(config);
14373
 
            }
14374
 
        },
14375
 
 
14376
 
        /**
14377
 
         * Unplugs and destroys all plugins on the host
14378
 
         * @method _destroyPlugins
14379
 
         * @private
14380
 
         */
14381
 
        _destroyPlugins: function() {
14382
 
            this.unplug();
14383
 
        }
14384
 
    };
14385
 
 
14386
 
    Y.namespace("Plugin").Host = PluginHost;
14387
 
 
14388
 
 
14389
 
}, '3.4.1' ,{requires:['yui-base']});
14390
 
YUI.add('pluginhost-config', function(Y) {
14391
 
 
14392
 
    /**
14393
 
     * Adds pluginhost constructor configuration and static configuration support
14394
 
     * @submodule pluginhost-config
14395
 
     */
14396
 
 
14397
 
    var PluginHost = Y.Plugin.Host,
14398
 
        L = Y.Lang;
14399
 
 
14400
 
    /**
14401
 
     * A protected initialization method, used by the host class to initialize
14402
 
     * plugin configurations passed the constructor, through the config object.
14403
 
     * 
14404
 
     * Host objects should invoke this method at the appropriate time in their
14405
 
     * construction lifecycle.
14406
 
     * 
14407
 
     * @method _initConfigPlugins
14408
 
     * @param {Object} config The configuration object passed to the constructor
14409
 
     * @protected
14410
 
     * @for Plugin.Host
14411
 
     */
14412
 
    PluginHost.prototype._initConfigPlugins = function(config) {
14413
 
 
14414
 
        // Class Configuration
14415
 
        var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
14416
 
            plug = [],
14417
 
            unplug = {},
14418
 
            constructor, i, classPlug, classUnplug, pluginClassName;
14419
 
 
14420
 
        // TODO: Room for optimization. Can we apply statically/unplug in same pass?
14421
 
        for (i = classes.length - 1; i >= 0; i--) {
14422
 
            constructor = classes[i];
14423
 
 
14424
 
            classUnplug = constructor._UNPLUG;
14425
 
            if (classUnplug) {
14426
 
                // subclasses over-write
14427
 
                Y.mix(unplug, classUnplug, true);
14428
 
            }
14429
 
 
14430
 
            classPlug = constructor._PLUG;
14431
 
            if (classPlug) {
14432
 
                // subclasses over-write
14433
 
                Y.mix(plug, classPlug, true);
14434
 
            }
14435
 
        }
14436
 
 
14437
 
        for (pluginClassName in plug) {
14438
 
            if (plug.hasOwnProperty(pluginClassName)) {
14439
 
                if (!unplug[pluginClassName]) {
14440
 
                    this.plug(plug[pluginClassName]);
14441
 
                }
14442
 
            }
14443
 
        }
14444
 
 
14445
 
        // User Configuration
14446
 
        if (config && config.plugins) {
14447
 
            this.plug(config.plugins);
14448
 
        }
14449
 
    };
14450
 
    
14451
 
    /**
14452
 
     * Registers plugins to be instantiated at the class level (plugins 
14453
 
     * which should be plugged into every instance of the class by default).
14454
 
     *
14455
 
     * @method Plugin.Host.plug
14456
 
     * @static
14457
 
     *
14458
 
     * @param {Function} hostClass The host class on which to register the plugins
14459
 
     * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
14460
 
     * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
14461
 
     */
14462
 
    PluginHost.plug = function(hostClass, plugin, config) {
14463
 
        // Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
14464
 
        var p, i, l, name;
14465
 
    
14466
 
        if (hostClass !== Y.Base) {
14467
 
            hostClass._PLUG = hostClass._PLUG || {};
14468
 
    
14469
 
            if (!L.isArray(plugin)) {
14470
 
                if (config) {
14471
 
                    plugin = {fn:plugin, cfg:config};
14472
 
                }
14473
 
                plugin = [plugin];
14474
 
            }
14475
 
    
14476
 
            for (i = 0, l = plugin.length; i < l;i++) {
14477
 
                p = plugin[i];
14478
 
                name = p.NAME || p.fn.NAME;
14479
 
                hostClass._PLUG[name] = p;
14480
 
            }
14481
 
        }
14482
 
    };
14483
 
 
14484
 
    /**
14485
 
     * Unregisters any class level plugins which have been registered by the host class, or any
14486
 
     * other class in the hierarchy.
14487
 
     *
14488
 
     * @method Plugin.Host.unplug
14489
 
     * @static
14490
 
     *
14491
 
     * @param {Function} hostClass The host class from which to unregister the plugins
14492
 
     * @param {Function | Array} plugin The plugin class, or an array of plugin classes
14493
 
     */
14494
 
    PluginHost.unplug = function(hostClass, plugin) {
14495
 
        var p, i, l, name;
14496
 
    
14497
 
        if (hostClass !== Y.Base) {
14498
 
            hostClass._UNPLUG = hostClass._UNPLUG || {};
14499
 
    
14500
 
            if (!L.isArray(plugin)) {
14501
 
                plugin = [plugin];
14502
 
            }
14503
 
    
14504
 
            for (i = 0, l = plugin.length; i < l; i++) {
14505
 
                p = plugin[i];
14506
 
                name = p.NAME;
14507
 
                if (!hostClass._PLUG[name]) {
14508
 
                    hostClass._UNPLUG[name] = p;
14509
 
                } else {
14510
 
                    delete hostClass._PLUG[name];
14511
 
                }
14512
 
            }
14513
 
        }
14514
 
    };
14515
 
 
14516
 
 
14517
 
}, '3.4.1' ,{requires:['pluginhost-base']});
14518
 
YUI.add('event-delegate', function(Y) {
14519
 
 
14520
 
/**
14521
 
 * Adds event delegation support to the library.
14522
 
 * 
14523
 
 * @module event
14524
 
 * @submodule event-delegate
14525
 
 */
14526
 
 
14527
 
var toArray          = Y.Array,
14528
 
    YLang            = Y.Lang,
14529
 
    isString         = YLang.isString,
14530
 
    isObject         = YLang.isObject,
14531
 
    isArray          = YLang.isArray,
14532
 
    selectorTest     = Y.Selector.test,
14533
 
    detachCategories = Y.Env.evt.handles;
14534
 
 
14535
 
/**
14536
 
 * <p>Sets up event delegation on a container element.  The delegated event
14537
 
 * will use a supplied selector or filtering function to test if the event
14538
 
 * references at least one node that should trigger the subscription
14539
 
 * callback.</p>
14540
 
 *
14541
 
 * <p>Selector string filters will trigger the callback if the event originated
14542
 
 * from a node that matches it or is contained in a node that matches it.
14543
 
 * Function filters are called for each Node up the parent axis to the
14544
 
 * subscribing container node, and receive at each level the Node and the event
14545
 
 * object.  The function should return true (or a truthy value) if that Node
14546
 
 * should trigger the subscription callback.  Note, it is possible for filters
14547
 
 * to match multiple Nodes for a single event.  In this case, the delegate
14548
 
 * callback will be executed for each matching Node.</p>
14549
 
 *
14550
 
 * <p>For each matching Node, the callback will be executed with its 'this'
14551
 
 * object set to the Node matched by the filter (unless a specific context was
14552
 
 * provided during subscription), and the provided event's
14553
 
 * <code>currentTarget</code> will also be set to the matching Node.  The
14554
 
 * containing Node from which the subscription was originally made can be
14555
 
 * referenced as <code>e.container</code>.
14556
 
 *
14557
 
 * @method delegate
14558
 
 * @param type {String} the event type to delegate
14559
 
 * @param fn {Function} the callback function to execute.  This function
14560
 
 *              will be provided the event object for the delegated event.
14561
 
 * @param el {String|node} the element that is the delegation container
14562
 
 * @param spec {string|Function} a selector that must match the target of the
14563
 
 *              event or a function to test target and its parents for a match
14564
 
 * @param context optional argument that specifies what 'this' refers to.
14565
 
 * @param args* 0..n additional arguments to pass on to the callback function.
14566
 
 *              These arguments will be added after the event object.
14567
 
 * @return {EventHandle} the detach handle
14568
 
 * @for YUI
14569
 
 */
14570
 
function delegate(type, fn, el, filter) {
14571
 
    var args     = toArray(arguments, 0, true),
14572
 
        query    = isString(el) ? el : null,
14573
 
        typeBits, synth, container, categories, cat, i, len, handles, handle;
14574
 
 
14575
 
    // Support Y.delegate({ click: fnA, key: fnB }, context, filter, ...);
14576
 
    // and Y.delegate(['click', 'key'], fn, context, filter, ...);
14577
 
    if (isObject(type)) {
14578
 
        handles = [];
14579
 
 
14580
 
        if (isArray(type)) {
14581
 
            for (i = 0, len = type.length; i < len; ++i) {
14582
 
                args[0] = type[i];
14583
 
                handles.push(Y.delegate.apply(Y, args));
14584
 
            }
14585
 
        } else {
14586
 
            // Y.delegate({'click', fn}, context, filter) =>
14587
 
            // Y.delegate('click', fn, context, filter)
14588
 
            args.unshift(null); // one arg becomes two; need to make space
14589
 
 
14590
 
            for (i in type) {
14591
 
                if (type.hasOwnProperty(i)) {
14592
 
                    args[0] = i;
14593
 
                    args[1] = type[i];
14594
 
                    handles.push(Y.delegate.apply(Y, args));
14595
 
                }
14596
 
            }
14597
 
        }
14598
 
 
14599
 
        return new Y.EventHandle(handles);
14600
 
    }
14601
 
 
14602
 
    typeBits = type.split(/\|/);
14603
 
 
14604
 
    if (typeBits.length > 1) {
14605
 
        cat  = typeBits.shift();
14606
 
        args[0] = type = typeBits.shift();
14607
 
    }
14608
 
 
14609
 
    synth = Y.Node.DOM_EVENTS[type];
14610
 
 
14611
 
    if (isObject(synth) && synth.delegate) {
14612
 
        handle = synth.delegate.apply(synth, arguments);
14613
 
    }
14614
 
 
14615
 
    if (!handle) {
14616
 
        if (!type || !fn || !el || !filter) {
14617
 
            Y.log("delegate requires type, callback, parent, & filter", "warn");
14618
 
            return;
14619
 
        }
14620
 
 
14621
 
        container = (query) ? Y.Selector.query(query, null, true) : el;
14622
 
 
14623
 
        if (!container && isString(el)) {
14624
 
            handle = Y.on('available', function () {
14625
 
                Y.mix(handle, Y.delegate.apply(Y, args), true);
14626
 
            }, el);
14627
 
        }
14628
 
 
14629
 
        if (!handle && container) {
14630
 
            args.splice(2, 2, container); // remove the filter
14631
 
 
14632
 
            handle = Y.Event._attach(args, { facade: false });
14633
 
            handle.sub.filter  = filter;
14634
 
            handle.sub._notify = delegate.notifySub;
14635
 
        }
14636
 
    }
14637
 
 
14638
 
    if (handle && cat) {
14639
 
        categories = detachCategories[cat]  || (detachCategories[cat] = {});
14640
 
        categories = categories[type] || (categories[type] = []);
14641
 
        categories.push(handle);
14642
 
    }
14643
 
 
14644
 
    return handle;
14645
 
}
14646
 
 
14647
 
/**
14648
 
 * Overrides the <code>_notify</code> method on the normal DOM subscription to
14649
 
 * inject the filtering logic and only proceed in the case of a match.
14650
 
 * 
14651
 
 * @method delegate.notifySub
14652
 
 * @param thisObj {Object} default 'this' object for the callback
14653
 
 * @param args {Array} arguments passed to the event's <code>fire()</code>
14654
 
 * @param ce {CustomEvent} the custom event managing the DOM subscriptions for
14655
 
 *              the subscribed event on the subscribing node.
14656
 
 * @return {Boolean} false if the event was stopped
14657
 
 * @private
14658
 
 * @static
14659
 
 * @since 3.2.0
14660
 
 */
14661
 
delegate.notifySub = function (thisObj, args, ce) {
14662
 
    // Preserve args for other subscribers
14663
 
    args = args.slice();
14664
 
    if (this.args) {
14665
 
        args.push.apply(args, this.args);
14666
 
    }
14667
 
 
14668
 
    // Only notify subs if the event occurred on a targeted element
14669
 
    var currentTarget = delegate._applyFilter(this.filter, args, ce),
14670
 
        //container     = e.currentTarget,
14671
 
        e, i, len, ret;
14672
 
 
14673
 
    if (currentTarget) {
14674
 
        // Support multiple matches up the the container subtree
14675
 
        currentTarget = toArray(currentTarget);
14676
 
 
14677
 
        // The second arg is the currentTarget, but we'll be reusing this
14678
 
        // facade, replacing the currentTarget for each use, so it doesn't
14679
 
        // matter what element we seed it with.
14680
 
        e = args[0] = new Y.DOMEventFacade(args[0], ce.el, ce);
14681
 
 
14682
 
        e.container = Y.one(ce.el);
14683
 
    
14684
 
        for (i = 0, len = currentTarget.length; i < len && !e.stopped; ++i) {
14685
 
            e.currentTarget = Y.one(currentTarget[i]);
14686
 
 
14687
 
            ret = this.fn.apply(this.context || e.currentTarget, args);
14688
 
 
14689
 
            if (ret === false) { // stop further notifications
14690
 
                break;
14691
 
            }
14692
 
        }
14693
 
 
14694
 
        return ret;
14695
 
    }
14696
 
};
14697
 
 
14698
 
/**
14699
 
 * <p>Compiles a selector string into a filter function to identify whether
14700
 
 * Nodes along the parent axis of an event's target should trigger event
14701
 
 * notification.</p>
14702
 
 *
14703
 
 * <p>This function is memoized, so previously compiled filter functions are
14704
 
 * returned if the same selector string is provided.</p>
14705
 
 *
14706
 
 * <p>This function may be useful when defining synthetic events for delegate
14707
 
 * handling.</p>
14708
 
 *
14709
 
 * @method delegate.compileFilter
14710
 
 * @param selector {String} the selector string to base the filtration on
14711
 
 * @return {Function}
14712
 
 * @since 3.2.0
14713
 
 * @static
14714
 
 */
14715
 
delegate.compileFilter = Y.cached(function (selector) {
14716
 
    return function (target, e) {
14717
 
        return selectorTest(target._node, selector, e.currentTarget._node);
14718
 
    };
14719
 
});
14720
 
 
14721
 
/**
14722
 
 * Walks up the parent axis of an event's target, and tests each element
14723
 
 * against a supplied filter function.  If any Nodes, including the container,
14724
 
 * satisfy the filter, the delegated callback will be triggered for each.
14725
 
 *
14726
 
 * @method delegate._applyFilter
14727
 
 * @param filter {Function} boolean function to test for inclusion in event
14728
 
 *                  notification
14729
 
 * @param args {Array} the arguments that would be passed to subscribers
14730
 
 * @param ce   {CustomEvent} the DOM event wrapper
14731
 
 * @return {Node|Node[]|undefined} The Node or Nodes that satisfy the filter
14732
 
 * @protected
14733
 
 */
14734
 
delegate._applyFilter = function (filter, args, ce) {
14735
 
    var e         = args[0],
14736
 
        container = ce.el, // facadeless events in IE, have no e.currentTarget
14737
 
        target    = e.target || e.srcElement,
14738
 
        match     = [],
14739
 
        isContainer = false;
14740
 
 
14741
 
    // Resolve text nodes to their containing element
14742
 
    if (target.nodeType === 3) {
14743
 
        target = target.parentNode;
14744
 
    }
14745
 
 
14746
 
    // passing target as the first arg rather than leaving well enough alone
14747
 
    // making 'this' in the filter function refer to the target.  This is to
14748
 
    // support bound filter functions.
14749
 
    args.unshift(target);
14750
 
 
14751
 
    if (isString(filter)) {
14752
 
        while (target) {
14753
 
            isContainer = (target === container);
14754
 
            if (selectorTest(target, filter, (isContainer ?null: container))) {
14755
 
                match.push(target);
14756
 
            }
14757
 
 
14758
 
            if (isContainer) {
14759
 
                break;
14760
 
            }
14761
 
 
14762
 
            target = target.parentNode;
14763
 
        }
14764
 
    } else {
14765
 
        // filter functions are implementer code and should receive wrappers
14766
 
        args[0] = Y.one(target);
14767
 
        args[1] = new Y.DOMEventFacade(e, container, ce);
14768
 
 
14769
 
        while (target) {
14770
 
            // filter(target, e, extra args...) - this === target
14771
 
            if (filter.apply(args[0], args)) {
14772
 
                match.push(target);
14773
 
            }
14774
 
 
14775
 
            if (target === container) {
14776
 
                break;
14777
 
            }
14778
 
 
14779
 
            target = target.parentNode;
14780
 
            args[0] = Y.one(target);
14781
 
        }
14782
 
        args[1] = e; // restore the raw DOM event
14783
 
    }
14784
 
 
14785
 
    if (match.length <= 1) {
14786
 
        match = match[0]; // single match or undefined
14787
 
    }
14788
 
 
14789
 
    // remove the target
14790
 
    args.shift();
14791
 
 
14792
 
    return match;
14793
 
};
14794
 
 
14795
 
/**
14796
 
 * Sets up event delegation on a container element.  The delegated event
14797
 
 * will use a supplied filter to test if the callback should be executed.
14798
 
 * This filter can be either a selector string or a function that returns
14799
 
 * a Node to use as the currentTarget for the event.
14800
 
 *
14801
 
 * The event object for the delegated event is supplied to the callback
14802
 
 * function.  It is modified slightly in order to support all properties
14803
 
 * that may be needed for event delegation.  'currentTarget' is set to
14804
 
 * the element that matched the selector string filter or the Node returned
14805
 
 * from the filter function.  'container' is set to the element that the
14806
 
 * listener is delegated from (this normally would be the 'currentTarget').
14807
 
 *
14808
 
 * Filter functions will be called with the arguments that would be passed to
14809
 
 * the callback function, including the event object as the first parameter.
14810
 
 * The function should return false (or a falsey value) if the success criteria
14811
 
 * aren't met, and the Node to use as the event's currentTarget and 'this'
14812
 
 * object if they are.
14813
 
 *
14814
 
 * @method delegate
14815
 
 * @param type {string} the event type to delegate
14816
 
 * @param fn {function} the callback function to execute.  This function
14817
 
 * will be provided the event object for the delegated event.
14818
 
 * @param el {string|node} the element that is the delegation container
14819
 
 * @param filter {string|function} a selector that must match the target of the
14820
 
 * event or a function that returns a Node or false.
14821
 
 * @param context optional argument that specifies what 'this' refers to.
14822
 
 * @param args* 0..n additional arguments to pass on to the callback function.
14823
 
 * These arguments will be added after the event object.
14824
 
 * @return {EventHandle} the detach handle
14825
 
 * @for YUI
14826
 
 */
14827
 
Y.delegate = Y.Event.delegate = delegate;
14828
 
 
14829
 
 
14830
 
}, '3.4.1' ,{requires:['node-base']});
14831
 
YUI.add('node-event-delegate', function(Y) {
14832
 
 
14833
 
/**
14834
 
 * Functionality to make the node a delegated event container
14835
 
 * @module node
14836
 
 * @submodule node-event-delegate
14837
 
 */
14838
 
 
14839
 
/**
14840
 
 * <p>Sets up a delegation listener for an event occurring inside the Node.
14841
 
 * The delegated event will be verified against a supplied selector or
14842
 
 * filtering function to test if the event references at least one node that
14843
 
 * should trigger the subscription callback.</p>
14844
 
 *
14845
 
 * <p>Selector string filters will trigger the callback if the event originated
14846
 
 * from a node that matches it or is contained in a node that matches it.
14847
 
 * Function filters are called for each Node up the parent axis to the
14848
 
 * subscribing container node, and receive at each level the Node and the event
14849
 
 * object.  The function should return true (or a truthy value) if that Node
14850
 
 * should trigger the subscription callback.  Note, it is possible for filters
14851
 
 * to match multiple Nodes for a single event.  In this case, the delegate
14852
 
 * callback will be executed for each matching Node.</p>
14853
 
 *
14854
 
 * <p>For each matching Node, the callback will be executed with its 'this'
14855
 
 * object set to the Node matched by the filter (unless a specific context was
14856
 
 * provided during subscription), and the provided event's
14857
 
 * <code>currentTarget</code> will also be set to the matching Node.  The
14858
 
 * containing Node from which the subscription was originally made can be
14859
 
 * referenced as <code>e.container</code>.
14860
 
 *
14861
 
 * @method delegate
14862
 
 * @param type {String} the event type to delegate
14863
 
 * @param fn {Function} the callback function to execute.  This function
14864
 
 *              will be provided the event object for the delegated event.
14865
 
 * @param spec {String|Function} a selector that must match the target of the
14866
 
 *              event or a function to test target and its parents for a match
14867
 
 * @param context {Object} optional argument that specifies what 'this' refers to.
14868
 
 * @param args* {any} 0..n additional arguments to pass on to the callback function.
14869
 
 *              These arguments will be added after the event object.
14870
 
 * @return {EventHandle} the detach handle
14871
 
 * @for Node
14872
 
 */
14873
 
Y.Node.prototype.delegate = function(type) {
14874
 
 
14875
 
    var args = Y.Array(arguments, 0, true),
14876
 
        index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2;
14877
 
 
14878
 
    args.splice(index, 0, this._node);
14879
 
 
14880
 
    return Y.delegate.apply(Y, args);
14881
 
};
14882
 
 
14883
 
 
14884
 
}, '3.4.1' ,{requires:['node-base', 'event-delegate']});
14885
 
YUI.add('node-pluginhost', function(Y) {
14886
 
 
14887
 
/**
14888
 
 * @module node
14889
 
 * @submodule node-pluginhost
14890
 
 */
14891
 
 
14892
 
/**
14893
 
 * Registers plugins to be instantiated at the class level (plugins
14894
 
 * which should be plugged into every instance of Node by default).
14895
 
 *
14896
 
 * @method plug
14897
 
 * @static
14898
 
 * @for Node
14899
 
 * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
14900
 
 * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
14901
 
 */
14902
 
Y.Node.plug = function() {
14903
 
    var args = Y.Array(arguments);
14904
 
    args.unshift(Y.Node);
14905
 
    Y.Plugin.Host.plug.apply(Y.Base, args);
14906
 
    return Y.Node;
14907
 
};
14908
 
 
14909
 
/**
14910
 
 * Unregisters any class level plugins which have been registered by the Node
14911
 
 *
14912
 
 * @method unplug
14913
 
 * @static
14914
 
 *
14915
 
 * @param {Function | Array} plugin The plugin class, or an array of plugin classes
14916
 
 */
14917
 
Y.Node.unplug = function() {
14918
 
    var args = Y.Array(arguments);
14919
 
    args.unshift(Y.Node);
14920
 
    Y.Plugin.Host.unplug.apply(Y.Base, args);
14921
 
    return Y.Node;
14922
 
};
14923
 
 
14924
 
Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
14925
 
 
14926
 
// allow batching of plug/unplug via NodeList
14927
 
// doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
14928
 
Y.NodeList.prototype.plug = function() {
14929
 
    var args = arguments;
14930
 
    Y.NodeList.each(this, function(node) {
14931
 
        Y.Node.prototype.plug.apply(Y.one(node), args);
14932
 
    });
14933
 
};
14934
 
 
14935
 
Y.NodeList.prototype.unplug = function() {
14936
 
    var args = arguments;
14937
 
    Y.NodeList.each(this, function(node) {
14938
 
        Y.Node.prototype.unplug.apply(Y.one(node), args);
14939
 
    });
14940
 
};
14941
 
 
14942
 
 
14943
 
}, '3.4.1' ,{requires:['node-base', 'pluginhost']});
14944
 
YUI.add('node-screen', function(Y) {
14945
 
 
14946
 
/**
14947
 
 * Extended Node interface for managing regions and screen positioning.
14948
 
 * Adds support for positioning elements and normalizes window size and scroll detection. 
14949
 
 * @module node
14950
 
 * @submodule node-screen
14951
 
 */
14952
 
 
14953
 
// these are all "safe" returns, no wrapping required
14954
 
Y.each([
14955
 
    /**
14956
 
     * Returns the inner width of the viewport (exludes scrollbar). 
14957
 
     * @config winWidth
14958
 
     * @for Node
14959
 
     * @type {Int}
14960
 
     */
14961
 
    'winWidth',
14962
 
 
14963
 
    /**
14964
 
     * Returns the inner height of the viewport (exludes scrollbar). 
14965
 
     * @config winHeight
14966
 
     * @type {Int}
14967
 
     */
14968
 
    'winHeight',
14969
 
 
14970
 
    /**
14971
 
     * Document width 
14972
 
     * @config winHeight
14973
 
     * @type {Int}
14974
 
     */
14975
 
    'docWidth',
14976
 
 
14977
 
    /**
14978
 
     * Document height 
14979
 
     * @config docHeight
14980
 
     * @type {Int}
14981
 
     */
14982
 
    'docHeight',
14983
 
 
14984
 
    /**
14985
 
     * Pixel distance the page has been scrolled horizontally 
14986
 
     * @config docScrollX
14987
 
     * @type {Int}
14988
 
     */
14989
 
    'docScrollX',
14990
 
 
14991
 
    /**
14992
 
     * Pixel distance the page has been scrolled vertically 
14993
 
     * @config docScrollY
14994
 
     * @type {Int}
14995
 
     */
14996
 
    'docScrollY'
14997
 
    ],
14998
 
    function(name) {
14999
 
        Y.Node.ATTRS[name] = {
15000
 
            getter: function() {
15001
 
                var args = Array.prototype.slice.call(arguments);
15002
 
                args.unshift(Y.Node.getDOMNode(this));
15003
 
 
15004
 
                return Y.DOM[name].apply(this, args);
15005
 
            }
15006
 
        };
15007
 
    }
15008
 
);
15009
 
 
15010
 
Y.Node.ATTRS.scrollLeft = {
15011
 
    getter: function() {
15012
 
        var node = Y.Node.getDOMNode(this);
15013
 
        return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
15014
 
    },
15015
 
 
15016
 
    setter: function(val) {
15017
 
        var node = Y.Node.getDOMNode(this);
15018
 
        if (node) {
15019
 
            if ('scrollLeft' in node) {
15020
 
                node.scrollLeft = val;
15021
 
            } else if (node.document || node.nodeType === 9) {
15022
 
                Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
15023
 
            }
15024
 
        } else {
15025
 
            Y.log('unable to set scrollLeft for ' + node, 'error', 'Node');
15026
 
        }
15027
 
    }
15028
 
};
15029
 
 
15030
 
Y.Node.ATTRS.scrollTop = {
15031
 
    getter: function() {
15032
 
        var node = Y.Node.getDOMNode(this);
15033
 
        return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
15034
 
    },
15035
 
 
15036
 
    setter: function(val) {
15037
 
        var node = Y.Node.getDOMNode(this);
15038
 
        if (node) {
15039
 
            if ('scrollTop' in node) {
15040
 
                node.scrollTop = val;
15041
 
            } else if (node.document || node.nodeType === 9) {
15042
 
                Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
15043
 
            }
15044
 
        } else {
15045
 
            Y.log('unable to set scrollTop for ' + node, 'error', 'Node');
15046
 
        }
15047
 
    }
15048
 
};
15049
 
 
15050
 
Y.Node.importMethod(Y.DOM, [
15051
 
/**
15052
 
 * Gets the current position of the node in page coordinates. 
15053
 
 * @method getXY
15054
 
 * @for Node
15055
 
 * @return {Array} The XY position of the node
15056
 
*/
15057
 
    'getXY',
15058
 
 
15059
 
/**
15060
 
 * Set the position of the node in page coordinates, regardless of how the node is positioned.
15061
 
 * @method setXY
15062
 
 * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
15063
 
 * @chainable
15064
 
 */
15065
 
    'setXY',
15066
 
 
15067
 
/**
15068
 
 * Gets the current position of the node in page coordinates. 
15069
 
 * @method getX
15070
 
 * @return {Int} The X position of the node
15071
 
*/
15072
 
    'getX',
15073
 
 
15074
 
/**
15075
 
 * Set the position of the node in page coordinates, regardless of how the node is positioned.
15076
 
 * @method setX
15077
 
 * @param {Int} x X value for new position (coordinates are page-based)
15078
 
 * @chainable
15079
 
 */
15080
 
    'setX',
15081
 
 
15082
 
/**
15083
 
 * Gets the current position of the node in page coordinates. 
15084
 
 * @method getY
15085
 
 * @return {Int} The Y position of the node
15086
 
*/
15087
 
    'getY',
15088
 
 
15089
 
/**
15090
 
 * Set the position of the node in page coordinates, regardless of how the node is positioned.
15091
 
 * @method setY
15092
 
 * @param {Int} y Y value for new position (coordinates are page-based)
15093
 
 * @chainable
15094
 
 */
15095
 
    'setY',
15096
 
 
15097
 
/**
15098
 
 * Swaps the XY position of this node with another node. 
15099
 
 * @method swapXY
15100
 
 * @param {Y.Node || HTMLElement} otherNode The node to swap with.
15101
 
 * @chainable
15102
 
 */
15103
 
    'swapXY'
15104
 
]);
15105
 
 
15106
 
/**
15107
 
 * @module node
15108
 
 * @submodule node-screen
15109
 
 */
15110
 
 
15111
 
/**
15112
 
 * Returns a region object for the node
15113
 
 * @config region
15114
 
 * @for Node
15115
 
 * @type Node
15116
 
 */
15117
 
Y.Node.ATTRS.region = {
15118
 
    getter: function() {
15119
 
        var node = this.getDOMNode(),
15120
 
            region;
15121
 
 
15122
 
        if (node && !node.tagName) {
15123
 
            if (node.nodeType === 9) { // document
15124
 
                node = node.documentElement;
15125
 
            }
15126
 
        }
15127
 
        if (Y.DOM.isWindow(node)) {
15128
 
            region = Y.DOM.viewportRegion(node);
15129
 
        } else {
15130
 
            region = Y.DOM.region(node);
15131
 
        }
15132
 
        return region;
15133
 
    }
15134
 
};
15135
 
 
15136
 
/**
15137
 
 * Returns a region object for the node's viewport
15138
 
 * @config viewportRegion
15139
 
 * @type Node
15140
 
 */
15141
 
Y.Node.ATTRS.viewportRegion = {
15142
 
    getter: function() {
15143
 
        return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
15144
 
    }
15145
 
};
15146
 
 
15147
 
Y.Node.importMethod(Y.DOM, 'inViewportRegion');
15148
 
 
15149
 
// these need special treatment to extract 2nd node arg
15150
 
/**
15151
 
 * Compares the intersection of the node with another node or region
15152
 
 * @method intersect
15153
 
 * @for Node
15154
 
 * @param {Node|Object} node2 The node or region to compare with.
15155
 
 * @param {Object} altRegion An alternate region to use (rather than this node's).
15156
 
 * @return {Object} An object representing the intersection of the regions.
15157
 
 */
15158
 
Y.Node.prototype.intersect = function(node2, altRegion) {
15159
 
    var node1 = Y.Node.getDOMNode(this);
15160
 
    if (Y.instanceOf(node2, Y.Node)) { // might be a region object
15161
 
        node2 = Y.Node.getDOMNode(node2);
15162
 
    }
15163
 
    return Y.DOM.intersect(node1, node2, altRegion);
15164
 
};
15165
 
 
15166
 
/**
15167
 
 * Determines whether or not the node is within the giving region.
15168
 
 * @method inRegion
15169
 
 * @param {Node|Object} node2 The node or region to compare with.
15170
 
 * @param {Boolean} all Whether or not all of the node must be in the region.
15171
 
 * @param {Object} altRegion An alternate region to use (rather than this node's).
15172
 
 * @return {Object} An object representing the intersection of the regions.
15173
 
 */
15174
 
Y.Node.prototype.inRegion = function(node2, all, altRegion) {
15175
 
    var node1 = Y.Node.getDOMNode(this);
15176
 
    if (Y.instanceOf(node2, Y.Node)) { // might be a region object
15177
 
        node2 = Y.Node.getDOMNode(node2);
15178
 
    }
15179
 
    return Y.DOM.inRegion(node1, node2, all, altRegion);
15180
 
};
15181
 
 
15182
 
 
15183
 
}, '3.4.1' ,{requires:['node-base', 'dom-screen']});
15184
 
YUI.add('node-style', function(Y) {
15185
 
 
15186
 
(function(Y) {
15187
 
/**
15188
 
 * Extended Node interface for managing node styles.
15189
 
 * @module node
15190
 
 * @submodule node-style
15191
 
 */
15192
 
 
15193
 
var methods = [
15194
 
    /**
15195
 
     * Returns the style's current value.
15196
 
     * @method getStyle
15197
 
     * @for Node
15198
 
     * @param {String} attr The style attribute to retrieve. 
15199
 
     * @return {String} The current value of the style property for the element.
15200
 
     */
15201
 
    'getStyle',
15202
 
 
15203
 
    /**
15204
 
     * Returns the computed value for the given style property.
15205
 
     * @method getComputedStyle
15206
 
     * @param {String} attr The style attribute to retrieve. 
15207
 
     * @return {String} The computed value of the style property for the element.
15208
 
     */
15209
 
    'getComputedStyle',
15210
 
 
15211
 
    /**
15212
 
     * Sets a style property of the node.
15213
 
     * @method setStyle
15214
 
     * @param {String} attr The style attribute to set. 
15215
 
     * @param {String|Number} val The value. 
15216
 
     * @chainable
15217
 
     */
15218
 
    'setStyle',
15219
 
 
15220
 
    /**
15221
 
     * Sets multiple style properties on the node.
15222
 
     * @method setStyles
15223
 
     * @param {Object} hash An object literal of property:value pairs. 
15224
 
     * @chainable
15225
 
     */
15226
 
    'setStyles'
15227
 
];
15228
 
Y.Node.importMethod(Y.DOM, methods);
15229
 
/**
15230
 
 * Returns an array of values for each node.
15231
 
 * @method getStyle
15232
 
 * @for NodeList
15233
 
 * @see Node.getStyle
15234
 
 * @param {String} attr The style attribute to retrieve. 
15235
 
 * @return {Array} The current values of the style property for the element.
15236
 
 */
15237
 
 
15238
 
/**
15239
 
 * Returns an array of the computed value for each node.
15240
 
 * @method getComputedStyle
15241
 
 * @see Node.getComputedStyle
15242
 
 * @param {String} attr The style attribute to retrieve. 
15243
 
 * @return {Array} The computed values for each node.
15244
 
 */
15245
 
 
15246
 
/**
15247
 
 * Sets a style property on each node.
15248
 
 * @method setStyle
15249
 
 * @see Node.setStyle
15250
 
 * @param {String} attr The style attribute to set. 
15251
 
 * @param {String|Number} val The value. 
15252
 
 * @chainable
15253
 
 */
15254
 
 
15255
 
/**
15256
 
 * Sets multiple style properties on each node.
15257
 
 * @method setStyles
15258
 
 * @see Node.setStyles
15259
 
 * @param {Object} hash An object literal of property:value pairs. 
15260
 
 * @chainable
15261
 
 */
15262
 
Y.NodeList.importMethod(Y.Node.prototype, methods);
15263
 
})(Y);
15264
 
 
15265
 
 
15266
 
}, '3.4.1' ,{requires:['dom-style', 'node-base']});
15267
 
YUI.add('querystring-stringify-simple', function(Y) {
15268
 
 
15269
 
/*global Y */
15270
 
/**
15271
 
 * <p>Provides Y.QueryString.stringify method for converting objects to Query Strings.
15272
 
 * This is a subset implementation of the full querystring-stringify.</p>
15273
 
 * <p>This module provides the bare minimum functionality (encoding a hash of simple values),
15274
 
 * without the additional support for nested data structures.  Every key-value pair is
15275
 
 * encoded by encodeURIComponent.</p>
15276
 
 * <p>This module provides a minimalistic way for io to handle  single-level objects
15277
 
 * as transaction data.</p>
15278
 
 *
15279
 
 * @module querystring
15280
 
 * @submodule querystring-stringify-simple
15281
 
 * @for QueryString
15282
 
 * @static
15283
 
 */
15284
 
 
15285
 
var QueryString = Y.namespace("QueryString"),
15286
 
    EUC = encodeURIComponent;
15287
 
 
15288
 
/**
15289
 
 * <p>Converts a simple object to a Query String representation.</p>
15290
 
 * <p>Nested objects, Arrays, and so on, are not supported.</p>
15291
 
 *
15292
 
 * @method stringify
15293
 
 * @for QueryString
15294
 
 * @public
15295
 
 * @submodule querystring-stringify-simple
15296
 
 * @param obj {Object} A single-level object to convert to a querystring.
15297
 
 * @param cfg {Object} (optional) Configuration object.  In the simple
15298
 
 *                                module, only the arrayKey setting is
15299
 
 *                                supported.  When set to true, the key of an
15300
 
 *                                array will have the '[]' notation appended
15301
 
 *                                to the key;.
15302
 
 * @static
15303
 
 */
15304
 
QueryString.stringify = function (obj, c) {
15305
 
    var qs = [],
15306
 
        // Default behavior is false; standard key notation.
15307
 
        s = c && c.arrayKey ? true : false,
15308
 
        key, i, l;
15309
 
 
15310
 
    for (key in obj) {
15311
 
        if (obj.hasOwnProperty(key)) {
15312
 
            if (Y.Lang.isArray(obj[key])) {
15313
 
                for (i = 0, l = obj[key].length; i < l; i++) {
15314
 
                    qs.push(EUC(s ? key + '[]' : key) + '=' + EUC(obj[key][i]));
15315
 
                }
15316
 
            }
15317
 
            else {
15318
 
                qs.push(EUC(key) + '=' + EUC(obj[key]));
15319
 
            }
15320
 
        }
15321
 
    }
15322
 
 
15323
 
    return qs.join('&');
15324
 
};
15325
 
 
15326
 
 
15327
 
}, '3.4.1' ,{requires:['yui-base']});
15328
 
YUI.add('io-base', function(Y) {
15329
 
 
15330
 
   /**
15331
 
    * Base IO functionality. Provides basic XHR transport support.
15332
 
    * @module io
15333
 
    * @submodule io-base
15334
 
    */
15335
 
 
15336
 
        // Window reference
15337
 
        var L = Y.Lang,
15338
 
                // List of events that comprise the IO event lifecycle.
15339
 
                E = ['start', 'complete', 'end', 'success', 'failure'],
15340
 
                // Whitelist of used XHR response object properties.
15341
 
                P = ['status', 'statusText', 'responseText', 'responseXML'],
15342
 
                aH = 'getAllResponseHeaders',
15343
 
                oH = 'getResponseHeader',
15344
 
                w = Y.config.win,
15345
 
                xhr = w.XMLHttpRequest,
15346
 
                xdr = w.XDomainRequest,
15347
 
                _i = 0;
15348
 
 
15349
 
   /**
15350
 
    * The io class is a utility that brokers HTTP requests through a simplified
15351
 
    * interface.  Specifically, it allows JavaScript to make HTTP requests to
15352
 
    * a resource without a page reload.  The underlying transport for making
15353
 
    * same-domain requests is the XMLHttpRequest object.  YUI.io can also use
15354
 
    * Flash, if specified as a transport, for cross-domain requests.
15355
 
    *
15356
 
        * @class IO
15357
 
        * @constructor
15358
 
    * @param {object} c - Object of EventTarget's publish method configurations
15359
 
    *                     used to configure IO's events.
15360
 
        */
15361
 
        function IO (c) {
15362
 
                var io = this;
15363
 
 
15364
 
                io._uid = 'io:' + _i++;
15365
 
                io._init(c);
15366
 
                Y.io._map[io._uid] = io;
15367
 
        }
15368
 
 
15369
 
        IO.prototype = {
15370
 
                //--------------------------------------
15371
 
                //  Properties
15372
 
                //--------------------------------------
15373
 
 
15374
 
           /**
15375
 
                * @description A counter that increments for each transaction.
15376
 
                *
15377
 
                * @property _id
15378
 
                * @private
15379
 
                * @type int
15380
 
                */
15381
 
                _id: 0,
15382
 
 
15383
 
           /**
15384
 
                * @description Object of IO HTTP headers sent with each transaction.
15385
 
                *
15386
 
                * @property _headers
15387
 
                * @private
15388
 
                * @type object
15389
 
                */
15390
 
                _headers: {
15391
 
                        'X-Requested-With' : 'XMLHttpRequest'
15392
 
                },
15393
 
 
15394
 
           /**
15395
 
                * @description Object that stores timeout values for any transaction with
15396
 
                * a defined "timeout" configuration property.
15397
 
                *
15398
 
                * @property _timeout
15399
 
                * @private
15400
 
                * @type object
15401
 
                */
15402
 
                _timeout: {},
15403
 
 
15404
 
                //--------------------------------------
15405
 
                //  Methods
15406
 
                //--------------------------------------
15407
 
 
15408
 
                _init: function(c) {
15409
 
                        var io = this, i;
15410
 
                        
15411
 
                        io.cfg = c || {};
15412
 
        
15413
 
                        Y.augment(io, Y.EventTarget);
15414
 
                        for (i = 0; i < 5; i++) {
15415
 
                                // Publish IO global events with configurations, if any.
15416
 
                                // IO global events are set to broadcast by default.
15417
 
                                // These events use the "io:" namespace.
15418
 
                                io.publish('io:' + E[i], Y.merge({ broadcast: 1 }, c));
15419
 
                                // Publish IO transaction events with configurations, if
15420
 
                                // any.  These events use the "io-trn:" namespace.
15421
 
                                io.publish('io-trn:' + E[i], c);
15422
 
                        }
15423
 
                },
15424
 
 
15425
 
           /**
15426
 
                * @description Method that creates a unique transaction object for each
15427
 
                * request.
15428
 
                *
15429
 
                * @method _create
15430
 
                * @private
15431
 
                * @param {number} c - configuration object subset to determine if
15432
 
                *                     the transaction is an XDR or file upload,
15433
 
                *                     requiring an alternate transport.
15434
 
                * @param {number} i - transaction id
15435
 
                * @return object
15436
 
                */
15437
 
                _create: function(c, i) {
15438
 
                        var io = this,
15439
 
                                o = { id: L.isNumber(i) ? i : io._id++, uid: io._uid },
15440
 
                                x = c.xdr,
15441
 
                                u = x ? x.use : c.form && c.form.upload ? 'iframe' : 'xhr',
15442
 
                                ie = (x && x.use === 'native' && xdr),
15443
 
                                t = io._transport;
15444
 
 
15445
 
                        switch (u) {
15446
 
                                case 'native':
15447
 
                                case 'xhr':
15448
 
                                        o.c = ie ? new xdr() : xhr ? new xhr() : new ActiveXObject('Microsoft.XMLHTTP');
15449
 
                                        o.t =  ie ? true : false;
15450
 
                                        break;
15451
 
                                default:
15452
 
                                        o.c = t ? t[u] : {};
15453
 
                                        o.t = true;
15454
 
                        }
15455
 
 
15456
 
                        return o;
15457
 
                },
15458
 
 
15459
 
                _destroy: function(o) {
15460
 
                        if (w) {
15461
 
                                if (xhr && o.t === true) {
15462
 
                                        o.c.onreadystatechange = null;
15463
 
                                }
15464
 
                                else if (Y.UA.ie) {
15465
 
                                        // IE, when using XMLHttpRequest as an ActiveX Object, will throw
15466
 
                                        // a "Type Mismatch" error if the event handler is set to "null".
15467
 
                                        o.c.abort();
15468
 
                                }
15469
 
                        }
15470
 
 
15471
 
                        o.c = null;
15472
 
                        o = null;
15473
 
                },
15474
 
 
15475
 
           /**
15476
 
                * @description Method for creating and firing events.
15477
 
                *
15478
 
                * @method _evt
15479
 
                * @private
15480
 
                * @param {string} e - event to be published.
15481
 
                * @param {object} o - transaction object.
15482
 
                * @param {object} c - configuration data subset for event subscription.
15483
 
                *
15484
 
                * @return void
15485
 
                */
15486
 
                _evt: function(e, o, c) {
15487
 
                        var io = this,
15488
 
                                a = c['arguments'],
15489
 
                                eF = io.cfg.emitFacade,
15490
 
                                // Use old-style parameters or use an Event Facade
15491
 
                                p = eF ? [{ id: o.id, data: o.c, cfg: c, arguments: a }] : [o.id],
15492
 
                                // IO Global events namespace.
15493
 
                                gE = "io:" + e,
15494
 
                                // IO Transaction events namespace.
15495
 
                                tE = "io-trn:" + e;
15496
 
 
15497
 
                                if (!eF) {
15498
 
                                        if (e === E[0] || e === E[2]) {
15499
 
                                                if (a) {
15500
 
                                                        p.push(a);
15501
 
                                                }
15502
 
                                        }
15503
 
                                        else {
15504
 
                                                a ? p.push(o.c, a) : p.push(o.c);
15505
 
                                        }
15506
 
                                }
15507
 
                                
15508
 
                                p.unshift(gE);
15509
 
                                io.fire.apply(io, p);
15510
 
                                if (c.on) {
15511
 
                                        p[0] = tE;
15512
 
                                        io.once(tE, c.on[e], c.context || Y);
15513
 
                                        io.fire.apply(io, p);
15514
 
                                }
15515
 
                },
15516
 
 
15517
 
           /**
15518
 
                * @description Fires event "io:start" and creates, fires a
15519
 
                * transaction-specific start event, if config.on.start is
15520
 
                * defined.
15521
 
                *
15522
 
                * @method start
15523
 
                * @public
15524
 
                * @param {object} o - transaction object.
15525
 
                * @param {object} c - configuration object for the transaction.
15526
 
                *
15527
 
                * @return void
15528
 
                */
15529
 
                start: function(o, c) {
15530
 
                        this._evt(E[0], o, c);
15531
 
                },
15532
 
 
15533
 
           /**
15534
 
                * @description Fires event "io:complete" and creates, fires a
15535
 
                * transaction-specific "complete" event, if config.on.complete is
15536
 
                * defined.
15537
 
                *
15538
 
                * @method complete
15539
 
                * @public
15540
 
                * @param {object} o - transaction object.
15541
 
                * @param {object} c - configuration object for the transaction.
15542
 
                *
15543
 
                * @return void
15544
 
                */
15545
 
                complete: function(o, c) {
15546
 
                        this._evt(E[1], o, c);
15547
 
                },
15548
 
 
15549
 
           /**
15550
 
                * @description Fires event "io:end" and creates, fires a
15551
 
                * transaction-specific "end" event, if config.on.end is
15552
 
                * defined.
15553
 
                *
15554
 
                * @method end
15555
 
                * @public
15556
 
                * @param {object} o - transaction object.
15557
 
                * @param {object} c - configuration object for the transaction.
15558
 
                *
15559
 
                * @return void
15560
 
                */
15561
 
                end: function(o, c) {
15562
 
                        this._evt(E[2], o, c);
15563
 
                        this._destroy(o);
15564
 
                },
15565
 
 
15566
 
           /**
15567
 
                * @description Fires event "io:success" and creates, fires a
15568
 
                * transaction-specific "success" event, if config.on.success is
15569
 
                * defined.
15570
 
                *
15571
 
                * @method success
15572
 
                * @public
15573
 
                * @param {object} o - transaction object.
15574
 
                * @param {object} c - configuration object for the transaction.
15575
 
                *
15576
 
                * @return void
15577
 
                */
15578
 
                success: function(o, c) {
15579
 
                        this._evt(E[3], o, c);
15580
 
                        this.end(o, c);
15581
 
                },
15582
 
 
15583
 
           /**
15584
 
                * @description Fires event "io:failure" and creates, fires a
15585
 
                * transaction-specific "failure" event, if config.on.failure is
15586
 
                * defined.
15587
 
                *
15588
 
                * @method failure
15589
 
                * @public
15590
 
                * @param {object} o - transaction object.
15591
 
                * @param {object} c - configuration object for the transaction.
15592
 
                *
15593
 
                * @return void
15594
 
                */
15595
 
                failure: function(o, c) {
15596
 
                        this._evt(E[4], o, c);
15597
 
                        this.end(o, c);
15598
 
                },
15599
 
 
15600
 
           /**
15601
 
                * @description Retry an XDR transaction, using the Flash tranport,
15602
 
                * if the native transport fails.
15603
 
                *
15604
 
                * @method _retry
15605
 
                * @private
15606
 
 
15607
 
                * @param {object} o - Transaction object generated by _create().
15608
 
                * @param {string} uri - qualified path to transaction resource.
15609
 
                * @param {object} c - configuration object for the transaction.
15610
 
                *
15611
 
                * @return void
15612
 
                */
15613
 
                _retry: function(o, uri, c) {
15614
 
                        this._destroy(o);
15615
 
                        c.xdr.use = 'flash';
15616
 
                        return this.send(uri, c, o.id);
15617
 
                },
15618
 
 
15619
 
           /**
15620
 
                * @description Method that concatenates string data for HTTP GET transactions.
15621
 
                *
15622
 
                * @method _concat
15623
 
                * @private
15624
 
                * @param {string} s - URI or root data.
15625
 
                * @param {string} d - data to be concatenated onto URI.
15626
 
                * @return int
15627
 
                */
15628
 
                _concat: function(s, d) {
15629
 
                        s += (s.indexOf('?') === -1 ? '?' : '&') + d;
15630
 
                        return s;
15631
 
                },
15632
 
 
15633
 
           /**
15634
 
                * @description Method that stores default client headers for all transactions.
15635
 
                * If a label is passed with no value argument, the header will be deleted.
15636
 
                *
15637
 
                * @method _setHeader
15638
 
                * @private
15639
 
                * @param {string} l - HTTP header
15640
 
                * @param {string} v - HTTP header value
15641
 
                * @return int
15642
 
                */
15643
 
                setHeader: function(l, v) {
15644
 
                        if (v) {
15645
 
                                this._headers[l] = v;
15646
 
                        }
15647
 
                        else {
15648
 
                                delete this._headers[l];
15649
 
                        }
15650
 
                },
15651
 
 
15652
 
           /**
15653
 
                * @description Method that sets all HTTP headers to be sent in a transaction.
15654
 
                *
15655
 
                * @method _setHeaders
15656
 
                * @private
15657
 
                * @param {object} o - XHR instance for the specific transaction.
15658
 
                * @param {object} h - HTTP headers for the specific transaction, as defined
15659
 
                *                     in the configuration object passed to YUI.io().
15660
 
                * @return void
15661
 
                */
15662
 
                _setHeaders: function(o, h) {
15663
 
                        h = Y.merge(this._headers, h);
15664
 
                        Y.Object.each(h, function(v, p) {
15665
 
                                if (v !== 'disable') {
15666
 
                                        o.setRequestHeader(p, h[p]);
15667
 
                                }
15668
 
                        });
15669
 
                },
15670
 
 
15671
 
           /**
15672
 
                * @description Starts timeout count if the configuration object
15673
 
                * has a defined timeout property.
15674
 
                *
15675
 
                * @method _startTimeout
15676
 
                * @private
15677
 
                * @param {object} o - Transaction object generated by _create().
15678
 
                * @param {object} t - Timeout in milliseconds.
15679
 
                * @return void
15680
 
                */
15681
 
                _startTimeout: function(o, t) {
15682
 
                        var io = this;
15683
 
                        io._timeout[o.id] = w.setTimeout(function() { io._abort(o, 'timeout'); }, t);
15684
 
                },
15685
 
 
15686
 
           /**
15687
 
                * @description Clears the timeout interval started by _startTimeout().
15688
 
                *
15689
 
                * @method _clearTimeout
15690
 
                * @private
15691
 
                * @param {number} id - Transaction id.
15692
 
                * @return void
15693
 
                */
15694
 
                _clearTimeout: function(id) {
15695
 
                        w.clearTimeout(this._timeout[id]);
15696
 
                        delete this._timeout[id];
15697
 
                },
15698
 
 
15699
 
           /**
15700
 
                * @description Method that determines if a transaction response qualifies
15701
 
                * as success or failure, based on the response HTTP status code, and
15702
 
                * fires the appropriate success or failure events.
15703
 
                *
15704
 
                * @method _result
15705
 
                * @private
15706
 
                * @static
15707
 
                * @param {object} o - Transaction object generated by _create().
15708
 
                * @param {object} c - Configuration object passed to io().
15709
 
                * @return void
15710
 
                */
15711
 
                _result: function(o, c) {
15712
 
                        var s = o.c.status;
15713
 
 
15714
 
                        // IE reports HTTP 204 as HTTP 1223.
15715
 
                        if (s >= 200 && s < 300 || s === 1223) {
15716
 
                                this.success(o, c);
15717
 
                        }
15718
 
                        else {
15719
 
                                this.failure(o, c);
15720
 
                        }
15721
 
                },
15722
 
 
15723
 
           /**
15724
 
                * @description Event handler bound to onreadystatechange.
15725
 
                *
15726
 
                * @method _rS
15727
 
                * @private
15728
 
                * @param {object} o - Transaction object generated by _create().
15729
 
                * @param {object} c - Configuration object passed to YUI.io().
15730
 
                * @return void
15731
 
                */
15732
 
                _rS: function(o, c) {
15733
 
                        var io = this;
15734
 
 
15735
 
                        if (o.c.readyState === 4) {
15736
 
                                if (c.timeout) {
15737
 
                                        io._clearTimeout(o.id);
15738
 
                                }
15739
 
 
15740
 
                                // Yield in the event of request timeout or  abort.
15741
 
                                w.setTimeout(function() { io.complete(o, c); io._result(o, c); }, 0);
15742
 
                        }
15743
 
                },
15744
 
 
15745
 
           /**
15746
 
                * @description Terminates a transaction due to an explicit abort or
15747
 
                * timeout.
15748
 
                *
15749
 
                * @method _abort
15750
 
                * @private
15751
 
                * @param {object} o - Transaction object generated by _create().
15752
 
                * @param {string} s - Identifies timed out or aborted transaction.
15753
 
                *
15754
 
                * @return void
15755
 
                */
15756
 
                _abort: function(o, s) {
15757
 
                        if (o && o.c) {
15758
 
                                o.e = s;
15759
 
                                o.c.abort();
15760
 
                        }
15761
 
                },
15762
 
 
15763
 
           /**
15764
 
                * @description Method for requesting a transaction. send() is implemented as
15765
 
                * yui.io().  Each transaction may include a configuration object.  Its
15766
 
                * properties are:
15767
 
                *
15768
 
                * method: HTTP method verb (e.g., GET or POST). If this property is not
15769
 
                *         not defined, the default value will be GET.
15770
 
                *
15771
 
                * data: This is the name-value string that will be sent as the transaction
15772
 
                *       data.  If the request is HTTP GET, the data become part of
15773
 
                *       querystring. If HTTP POST, the data are sent in the message body.
15774
 
                *
15775
 
                * xdr: Defines the transport to be used for cross-domain requests.  By
15776
 
                *      setting this property, the transaction will use the specified
15777
 
                *      transport instead of XMLHttpRequest.
15778
 
                *      The properties are:
15779
 
                *      {
15780
 
                *        use: Specify the transport to be used: 'flash' and 'native'
15781
 
                *        dataType: Set the value to 'XML' if that is the expected
15782
 
                *                  response content type.
15783
 
                *      }
15784
 
                *
15785
 
                *
15786
 
                * form: This is a defined object used to process HTML form as data.  The
15787
 
                *       properties are:
15788
 
                *       {
15789
 
                *         id: Node object or id of HTML form.
15790
 
                *         useDisabled: Boolean value to allow disabled HTML form field
15791
 
                *                      values to be sent as part of the data.
15792
 
                *       }
15793
 
                *
15794
 
                * on: This is a defined object used to create and handle specific
15795
 
                *     events during a transaction lifecycle.  These events will fire in
15796
 
                *     addition to the global io events. The events are:
15797
 
                *     start - This event is fired when a request is sent to a resource.
15798
 
                *     complete - This event fires when the transaction is complete.
15799
 
                *     success - This event fires when the response status resolves to
15800
 
                *               HTTP 2xx.
15801
 
                *     failure - This event fires when the response status resolves to
15802
 
                *               HTTP 4xx, 5xx; and, for all transaction exceptions,
15803
 
                *               including aborted transactions and transaction timeouts.
15804
 
                *     end -  This even is fired at the conclusion of the transaction
15805
 
                *            lifecycle, after a success or failure resolution.
15806
 
                *
15807
 
                *     The properties are:
15808
 
                *     {
15809
 
                *       start: function(id, arguments){},
15810
 
                *       complete: function(id, responseobject, arguments){},
15811
 
                *       success: function(id, responseobject, arguments){},
15812
 
                *       failure: function(id, responseobject, arguments){},
15813
 
                *       end: function(id, arguments){}
15814
 
                *     }
15815
 
                *     Each property can reference a function or be written as an
15816
 
                *     inline function.
15817
 
                *
15818
 
                * sync: To enable synchronous transactions, set the configuration property
15819
 
                *       "sync" to true. Synchronous requests are limited to same-domain
15820
 
                *       requests only.
15821
 
                *
15822
 
                * context: Object reference for all defined transaction event handlers
15823
 
                *          when it is implemented as a method of a base object. Defining
15824
 
                *          "context" will set the reference of "this," used in the
15825
 
                *          event handlers, to the context value.  In the case where
15826
 
                *          different event handlers all have different contexts,
15827
 
                *          use Y.bind() to set the execution context, instead.
15828
 
                *
15829
 
                * headers: This is a defined object of client headers, as many as
15830
 
                *          desired for this specific transaction.  The object pattern is:
15831
 
                *          { 'header': 'value' }.
15832
 
                *
15833
 
                * timeout: This value, defined as milliseconds, is a time threshold for the
15834
 
                *          transaction. When this threshold is reached, and the transaction's
15835
 
                *          Complete event has not yet fired, the transaction will be aborted.
15836
 
                *
15837
 
                * arguments: User-defined data passed to all registered event handlers.
15838
 
                *            This value is available as the second argument in the "start"
15839
 
                *            and "end" event handlers. It is the third argument in the
15840
 
                *            "complete", "success", and "failure" event handlers.
15841
 
                *
15842
 
                * @method send
15843
 
                * @private
15844
 
                * @
15845
 
                * @param {string} uri - qualified path to transaction resource.
15846
 
                * @param {object} c - configuration object for the transaction.
15847
 
                * @param {number} i - transaction id, if already set.
15848
 
                * @return object
15849
 
                */
15850
 
                send: function(uri, c, i) {
15851
 
                        var o, m, r, s, d, io = this,
15852
 
                                u = uri;
15853
 
                                c = c ? Y.Object(c) : {};
15854
 
                                o = io._create(c, i);
15855
 
                                m = c.method ? c.method.toUpperCase() : 'GET';
15856
 
                                s = c.sync;
15857
 
                                d = c.data;
15858
 
 
15859
 
                        // Serialize an object into a key-value string using
15860
 
                        // querystring-stringify-simple.
15861
 
                        if (L.isObject(d)) {
15862
 
                                d = Y.QueryString.stringify(d);
15863
 
                        }
15864
 
 
15865
 
                        if (c.form) {
15866
 
                                if (c.form.upload) {
15867
 
                                        // This is a file upload transaction, calling
15868
 
                                        // upload() in io-upload-iframe.
15869
 
                                        return io.upload(o, uri, c);
15870
 
                                }
15871
 
                                else {
15872
 
                                        // Serialize HTML form data into a key-value string.
15873
 
                                        d = io._serialize(c.form, d);
15874
 
                                }
15875
 
                        }
15876
 
 
15877
 
                        if (d) {
15878
 
                                switch (m) {
15879
 
                                        case 'GET':
15880
 
                                        case 'HEAD':
15881
 
                                        case 'DELETE':
15882
 
                                                u = io._concat(u, d);
15883
 
                                                d = '';
15884
 
                                                Y.log('HTTP' + m + ' with data.  The querystring is: ' + u, 'info', 'io');
15885
 
                                                break;
15886
 
                                        case 'POST':
15887
 
                                        case 'PUT':
15888
 
                                                // If Content-Type is defined in the configuration object, or
15889
 
                                                // or as a default header, it will be used instead of
15890
 
                                                // 'application/x-www-form-urlencoded; charset=UTF-8'
15891
 
                                                c.headers = Y.merge({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, c.headers);
15892
 
                                                break;
15893
 
                                }
15894
 
                        }
15895
 
 
15896
 
                        if (o.t) {
15897
 
                                // Cross-domain request or custom transport configured.
15898
 
                                return io.xdr(u, o, c);
15899
 
                        }
15900
 
 
15901
 
                        if (!s) {
15902
 
                                o.c.onreadystatechange = function() { io._rS(o, c); };
15903
 
                        }
15904
 
 
15905
 
                        try {
15906
 
                                // Determine if request is to be set as
15907
 
                                // synchronous or asynchronous.
15908
 
                                o.c.open(m, u, s ? false : true, c.username || null, c.password || null);
15909
 
                                io._setHeaders(o.c, c.headers || {});
15910
 
                                io.start(o, c);
15911
 
 
15912
 
                                // Will work only in browsers that implement the
15913
 
                                // Cross-Origin Resource Sharing draft.
15914
 
                                if (c.xdr && c.xdr.credentials) {
15915
 
                                        if (!Y.UA.ie) {
15916
 
                                                o.c.withCredentials = true;
15917
 
                                        }
15918
 
                                }
15919
 
 
15920
 
                                // Using "null" with HTTP POST will result in a request
15921
 
                                // with no Content-Length header defined.
15922
 
                                o.c.send(d);
15923
 
 
15924
 
                                if (s) {
15925
 
                                        // Create a response object for synchronous transactions,
15926
 
                                        // mixing id and arguments properties with the xhr
15927
 
                                        // properties whitelist.
15928
 
                                        r = Y.mix({ id: o.id, 'arguments': c['arguments'] }, o.c, false, P);
15929
 
                                        r[aH] = function() { return o.c[aH](); };
15930
 
                                        r[oH] = function(h) { return o.c[oH](h); };
15931
 
                                        io.complete(o, c);
15932
 
                                        io._result(o, c);
15933
 
 
15934
 
                                        return r;
15935
 
                                }
15936
 
                        }
15937
 
                        catch(e) {
15938
 
                                if (o.t) {
15939
 
                                        // This exception is usually thrown by browsers
15940
 
                                        // that do not support XMLHttpRequest Level 2.
15941
 
                                        // Retry the request with the XDR transport set
15942
 
                                        // to 'flash'.  If the Flash transport is not
15943
 
                                        // initialized or available, the transaction
15944
 
                                        // will resolve to a transport error.
15945
 
                                        return io._retry(o, uri, c);
15946
 
                                }
15947
 
                                else {
15948
 
                                        io.complete(o, c);
15949
 
                                        io._result(o, c);
15950
 
                                }
15951
 
                        }
15952
 
 
15953
 
                        // If config.timeout is defined, and the request is standard XHR,
15954
 
                        // initialize timeout polling.
15955
 
                        if (c.timeout) {
15956
 
                                io._startTimeout(o, c.timeout);
15957
 
                                Y.log('Configuration timeout set to: ' + c.timeout, 'info', 'io');
15958
 
                        }
15959
 
 
15960
 
                        return {
15961
 
                                id: o.id,
15962
 
                                abort: function() {
15963
 
                                        return o.c ? io._abort(o, 'abort') : false;
15964
 
                                },
15965
 
                                isInProgress: function() {
15966
 
                                        return o.c ? o.c.readyState !== 4 && o.c.readyState !== 0 : false;
15967
 
                                },
15968
 
                                io: io
15969
 
                        };
15970
 
                }
15971
 
        };
15972
 
 
15973
 
   /**
15974
 
    * @description Method for requesting a transaction.
15975
 
    *
15976
 
    * @method io
15977
 
    * @public
15978
 
    * @static
15979
 
    * @param {string} u - qualified path to transaction resource.
15980
 
    * @param {object} c - configuration object for the transaction.
15981
 
    * @return object
15982
 
    */
15983
 
    Y.io = function(u, c) {
15984
 
                // Calling IO through the static interface will use and reuse
15985
 
                // an instance of IO.
15986
 
                var o = Y.io._map['io:0'] || new IO();
15987
 
                return o.send.apply(o, [u, c]);
15988
 
        };
15989
 
 
15990
 
        Y.IO = IO;
15991
 
        // Map of all IO instances created.
15992
 
        Y.io._map = {};
15993
 
 
15994
 
 
15995
 
 
15996
 
}, '3.4.1' ,{requires:['event-custom-base', 'querystring-stringify-simple']});
15997
 
YUI.add('json-parse', function(Y) {
15998
 
 
15999
 
/**
16000
 
 * <p>The JSON module adds support for serializing JavaScript objects into
16001
 
 * JSON strings and parsing JavaScript objects from strings in JSON format.</p>
16002
 
 *
16003
 
 * <p>The JSON namespace is added to your YUI instance including static methods
16004
 
 * Y.JSON.parse(..) and Y.JSON.stringify(..).</p>
16005
 
 *
16006
 
 * <p>The functionality and method signatures follow the ECMAScript 5
16007
 
 * specification.  In browsers with native JSON support, the native
16008
 
 * implementation is used.</p>
16009
 
 *
16010
 
 * <p>The <code>json</code> module is a rollup of <code>json-parse</code> and
16011
 
 * <code>json-stringify</code>.</p>
16012
 
 * 
16013
 
 * <p>As their names suggest, <code>json-parse</code> adds support for parsing
16014
 
 * JSON data (Y.JSON.parse) and <code>json-stringify</code> for serializing
16015
 
 * JavaScript data into JSON strings (Y.JSON.stringify).  You may choose to
16016
 
 * include either of the submodules individually if you don't need the
16017
 
 * complementary functionality, or include the rollup for both.</p>
16018
 
 *
16019
 
 * @module json
16020
 
 * @class JSON
16021
 
 * @static
16022
 
 */
16023
 
 
16024
 
/**
16025
 
 * Provides Y.JSON.parse method to accept JSON strings and return native
16026
 
 * JavaScript objects.
16027
 
 *
16028
 
 * @module json
16029
 
 * @submodule json-parse
16030
 
 * @for JSON
16031
 
 * @static
16032
 
 */
16033
 
 
16034
 
 
16035
 
// All internals kept private for security reasons
16036
 
function fromGlobal(ref) {
16037
 
    return (Y.config.win || this || {})[ref];
16038
 
}
16039
 
 
16040
 
 
16041
 
    /**
16042
 
     * Alias to native browser implementation of the JSON object if available.
16043
 
     *
16044
 
     * @property Native
16045
 
     * @type {Object}
16046
 
     * @private
16047
 
     */
16048
 
var _JSON  = fromGlobal('JSON'),
16049
 
 
16050
 
    Native = (Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON),
16051
 
    useNative = !!Native,
16052
 
 
16053
 
    /**
16054
 
     * Replace certain Unicode characters that JavaScript may handle incorrectly
16055
 
     * during eval--either by deleting them or treating them as line
16056
 
     * endings--with escape sequences.
16057
 
     * IMPORTANT NOTE: This regex will be used to modify the input if a match is
16058
 
     * found.
16059
 
     *
16060
 
     * @property _UNICODE_EXCEPTIONS
16061
 
     * @type {RegExp}
16062
 
     * @private
16063
 
     */
16064
 
    _UNICODE_EXCEPTIONS = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
16065
 
 
16066
 
 
16067
 
    /**
16068
 
     * First step in the safety evaluation.  Regex used to replace all escape
16069
 
     * sequences (i.e. "\\", etc) with '@' characters (a non-JSON character).
16070
 
     *
16071
 
     * @property _ESCAPES
16072
 
     * @type {RegExp}
16073
 
     * @private
16074
 
     */
16075
 
    _ESCAPES = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
16076
 
 
16077
 
    /**
16078
 
     * Second step in the safety evaluation.  Regex used to replace all simple
16079
 
     * values with ']' characters.
16080
 
     *
16081
 
     * @property _VALUES
16082
 
     * @type {RegExp}
16083
 
     * @private
16084
 
     */
16085
 
    _VALUES  = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
16086
 
 
16087
 
    /**
16088
 
     * Third step in the safety evaluation.  Regex used to remove all open
16089
 
     * square brackets following a colon, comma, or at the beginning of the
16090
 
     * string.
16091
 
     *
16092
 
     * @property _BRACKETS
16093
 
     * @type {RegExp}
16094
 
     * @private
16095
 
     */
16096
 
    _BRACKETS = /(?:^|:|,)(?:\s*\[)+/g,
16097
 
 
16098
 
    /**
16099
 
     * Final step in the safety evaluation.  Regex used to test the string left
16100
 
     * after all previous replacements for invalid characters.
16101
 
     *
16102
 
     * @property _UNSAFE
16103
 
     * @type {RegExp}
16104
 
     * @private
16105
 
     */
16106
 
    _UNSAFE = /[^\],:{}\s]/,
16107
 
    
16108
 
    /**
16109
 
     * Replaces specific unicode characters with their appropriate \unnnn
16110
 
     * format. Some browsers ignore certain characters during eval.
16111
 
     *
16112
 
     * @method escapeException
16113
 
     * @param c {String} Unicode character
16114
 
     * @return {String} the \unnnn escapement of the character
16115
 
     * @private
16116
 
     */
16117
 
    _escapeException = function (c) {
16118
 
        return '\\u'+('0000'+(+(c.charCodeAt(0))).toString(16)).slice(-4);
16119
 
    },
16120
 
 
16121
 
    /**
16122
 
     * Traverses nested objects, applying a reviver function to each (key,value)
16123
 
     * from the scope if the key:value's containing object.  The value returned
16124
 
     * from the function will replace the original value in the key:value pair.
16125
 
     * If the value returned is undefined, the key will be omitted from the
16126
 
     * returned object.
16127
 
     *
16128
 
     * @method _revive
16129
 
     * @param data {MIXED} Any JavaScript data
16130
 
     * @param reviver {Function} filter or mutation function
16131
 
     * @return {MIXED} The results of the filtered data
16132
 
     * @private
16133
 
     */
16134
 
    _revive = function (data, reviver) {
16135
 
        var walk = function (o,key) {
16136
 
            var k,v,value = o[key];
16137
 
            if (value && typeof value === 'object') {
16138
 
                for (k in value) {
16139
 
                    if (value.hasOwnProperty(k)) {
16140
 
                        v = walk(value, k);
16141
 
                        if (v === undefined) {
16142
 
                            delete value[k];
16143
 
                        } else {
16144
 
                            value[k] = v;
16145
 
                        }
16146
 
                    }
16147
 
                }
16148
 
            }
16149
 
            return reviver.call(o,key,value);
16150
 
        };
16151
 
 
16152
 
        return typeof reviver === 'function' ? walk({'':data},'') : data;
16153
 
    },
16154
 
 
16155
 
    /**
16156
 
     * Parse a JSON string, returning the native JavaScript representation.
16157
 
     *
16158
 
     * @param s {string} JSON string data
16159
 
     * @param reviver {function} (optional) function(k,v) passed each key value
16160
 
     *          pair of object literals, allowing pruning or altering values
16161
 
     * @return {MIXED} the native JavaScript representation of the JSON string
16162
 
     * @throws SyntaxError
16163
 
     * @method parse
16164
 
     * @static
16165
 
     */
16166
 
    // JavaScript implementation in lieu of native browser support.  Based on
16167
 
    // the json2.js library from http://json.org
16168
 
    _parse = function (s,reviver) {
16169
 
        // Replace certain Unicode characters that are otherwise handled
16170
 
        // incorrectly by some browser implementations.
16171
 
        // NOTE: This modifies the input if such characters are found!
16172
 
        s = s.replace(_UNICODE_EXCEPTIONS, _escapeException);
16173
 
        
16174
 
        // Test for any remaining invalid characters
16175
 
        if (!_UNSAFE.test(s.replace(_ESCAPES,'@').
16176
 
                            replace(_VALUES,']').
16177
 
                            replace(_BRACKETS,''))) {
16178
 
 
16179
 
            // Eval the text into a JavaScript data structure, apply any
16180
 
            // reviver function, and return
16181
 
            return _revive( eval('(' + s + ')'), reviver );
16182
 
        }
16183
 
 
16184
 
        throw new SyntaxError('JSON.parse');
16185
 
    };
16186
 
    
16187
 
Y.namespace('JSON').parse = function (s,reviver) {
16188
 
        if (typeof s !== 'string') {
16189
 
            s += '';
16190
 
        }
16191
 
 
16192
 
        return Native && Y.JSON.useNativeParse ?
16193
 
            Native.parse(s,reviver) : _parse(s,reviver);
16194
 
};
16195
 
 
16196
 
function workingNative( k, v ) {
16197
 
    return k === "ok" ? true : v;
16198
 
}
16199
 
 
16200
 
// Double check basic functionality.  This is mainly to catch early broken
16201
 
// implementations of the JSON API in Firefox 3.1 beta1 and beta2
16202
 
if ( Native ) {
16203
 
    try {
16204
 
        useNative = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
16205
 
    }
16206
 
    catch ( e ) {
16207
 
        useNative = false;
16208
 
    }
16209
 
}
16210
 
 
16211
 
/**
16212
 
 * Leverage native JSON parse if the browser has a native implementation.
16213
 
 * In general, this is a good idea.  See the Known Issues section in the
16214
 
 * JSON user guide for caveats.  The default value is true for browsers with
16215
 
 * native JSON support.
16216
 
 *
16217
 
 * @property useNativeParse
16218
 
 * @type Boolean
16219
 
 * @default true
16220
 
 * @static
16221
 
 */
16222
 
Y.JSON.useNativeParse = useNative;
16223
 
 
16224
 
 
16225
 
}, '3.4.1' );
16226
 
YUI.add('transition', function(Y) {
16227
 
 
16228
 
/**
16229
 
* Provides the transition method for Node.
16230
 
* Transition has no API of its own, but adds the transition method to Node.
16231
 
*
16232
 
* @module transition
16233
 
* @requires node-style
16234
 
*/
16235
 
 
16236
 
var CAMEL_VENDOR_PREFIX = '',
16237
 
    VENDOR_PREFIX = '',
16238
 
    DOCUMENT = Y.config.doc,
16239
 
    DOCUMENT_ELEMENT = 'documentElement',
16240
 
    TRANSITION = 'transition',
16241
 
    TRANSITION_CAMEL = 'Transition',
16242
 
    TRANSITION_PROPERTY_CAMEL,
16243
 
    TRANSITION_PROPERTY,
16244
 
    TRANSITION_DURATION,
16245
 
    TRANSITION_TIMING_FUNCTION,
16246
 
    TRANSITION_DELAY,
16247
 
    TRANSITION_END,
16248
 
    ON_TRANSITION_END,
16249
 
    TRANSFORM_CAMEL,
16250
 
 
16251
 
    EMPTY_OBJ = {},
16252
 
 
16253
 
    VENDORS = [
16254
 
        'Webkit',
16255
 
        'Moz'
16256
 
    ],
16257
 
 
16258
 
    VENDOR_TRANSITION_END = {
16259
 
        Webkit: 'webkitTransitionEnd'
16260
 
    },
16261
 
 
16262
 
/**
16263
 
 * A class for constructing transition instances.
16264
 
 * Adds the "transition" method to Node.
16265
 
 * @class Transition
16266
 
 * @constructor
16267
 
 */
16268
 
 
16269
 
Transition = function() {
16270
 
    this.init.apply(this, arguments);
16271
 
};
16272
 
 
16273
 
Transition._toCamel = function(property) {
16274
 
    property = property.replace(/-([a-z])/gi, function(m0, m1) {
16275
 
        return m1.toUpperCase();
16276
 
    });
16277
 
 
16278
 
    return property;
16279
 
};
16280
 
 
16281
 
Transition._toHyphen = function(property) {
16282
 
    property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) {
16283
 
        var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2;
16284
 
        
16285
 
        if (m3) {
16286
 
            str += '-' + m3.toLowerCase();
16287
 
        }
16288
 
 
16289
 
        return str;
16290
 
    }); 
16291
 
 
16292
 
    return property;
16293
 
};
16294
 
 
16295
 
Transition.SHOW_TRANSITION = 'fadeIn';
16296
 
Transition.HIDE_TRANSITION = 'fadeOut';
16297
 
 
16298
 
Transition.useNative = false;
16299
 
 
16300
 
Y.Array.each(VENDORS, function(val) { // then vendor specific
16301
 
    var property = val + TRANSITION_CAMEL;
16302
 
    if (property in DOCUMENT[DOCUMENT_ELEMENT].style) {
16303
 
        CAMEL_VENDOR_PREFIX = val;
16304
 
        VENDOR_PREFIX = Transition._toHyphen(val) + '-';
16305
 
 
16306
 
        Transition.useNative = true;
16307
 
        Transition.supported = true; // TODO: remove
16308
 
        Transition._VENDOR_PREFIX = val;
16309
 
    }
16310
 
});
16311
 
 
16312
 
TRANSITION_CAMEL = CAMEL_VENDOR_PREFIX + TRANSITION_CAMEL;
16313
 
TRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty';
16314
 
TRANSITION_PROPERTY = VENDOR_PREFIX + 'transition-property';
16315
 
TRANSITION_DURATION = VENDOR_PREFIX + 'transition-duration';
16316
 
TRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function';
16317
 
TRANSITION_DELAY = VENDOR_PREFIX + 'transition-delay';
16318
 
TRANSITION_END = 'transitionend';
16319
 
ON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend';
16320
 
 
16321
 
TRANSITION_END = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END;
16322
 
 
16323
 
TRANSFORM_CAMEL = CAMEL_VENDOR_PREFIX + 'Transform';
16324
 
 
16325
 
Transition.fx = {};
16326
 
Transition.toggles = {};
16327
 
 
16328
 
Transition._hasEnd = {};
16329
 
 
16330
 
Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i;
16331
 
 
16332
 
Y.Node.DOM_EVENTS[TRANSITION_END] = 1; 
16333
 
 
16334
 
Transition.NAME = 'transition';
16335
 
 
16336
 
Transition.DEFAULT_EASING = 'ease';
16337
 
Transition.DEFAULT_DURATION = 0.5;
16338
 
Transition.DEFAULT_DELAY = 0;
16339
 
 
16340
 
Transition._nodeAttrs = {};
16341
 
 
16342
 
Transition.prototype = {
16343
 
    constructor: Transition,
16344
 
    init: function(node, config) {
16345
 
        var anim = this;
16346
 
        anim._node = node;
16347
 
        if (!anim._running && config) {
16348
 
            anim._config = config;
16349
 
            node._transition = anim; // cache for reuse
16350
 
 
16351
 
            anim._duration = ('duration' in config) ?
16352
 
                config.duration: anim.constructor.DEFAULT_DURATION;
16353
 
 
16354
 
            anim._delay = ('delay' in config) ?
16355
 
                config.delay: anim.constructor.DEFAULT_DELAY;
16356
 
 
16357
 
            anim._easing = config.easing || anim.constructor.DEFAULT_EASING;
16358
 
            anim._count = 0; // track number of animated properties
16359
 
            anim._running = false;
16360
 
 
16361
 
        }
16362
 
 
16363
 
        return anim;
16364
 
    },
16365
 
 
16366
 
    addProperty: function(prop, config) {
16367
 
        var anim = this,
16368
 
            node = this._node,
16369
 
            uid = Y.stamp(node),
16370
 
            nodeInstance = Y.one(node),
16371
 
            attrs = Transition._nodeAttrs[uid],
16372
 
            computed,
16373
 
            compareVal,
16374
 
            dur,
16375
 
            attr,
16376
 
            val;
16377
 
 
16378
 
        if (!attrs) {
16379
 
            attrs = Transition._nodeAttrs[uid] = {};
16380
 
        }
16381
 
 
16382
 
        attr = attrs[prop];
16383
 
 
16384
 
        // might just be a value
16385
 
        if (config && config.value !== undefined) {
16386
 
            val = config.value;
16387
 
        } else if (config !== undefined) {
16388
 
            val = config; 
16389
 
            config = EMPTY_OBJ;
16390
 
        }
16391
 
 
16392
 
        if (typeof val === 'function') {
16393
 
            val = val.call(nodeInstance, nodeInstance);
16394
 
        }
16395
 
 
16396
 
        if (attr && attr.transition) {
16397
 
            // take control if another transition owns this property
16398
 
            if (attr.transition !== anim) {
16399
 
                attr.transition._count--; // remapping attr to this transition
16400
 
            }
16401
 
        } 
16402
 
 
16403
 
        anim._count++; // properties per transition
16404
 
 
16405
 
        // make 0 async and fire events
16406
 
        dur = ((typeof config.duration != 'undefined') ? config.duration :
16407
 
                    anim._duration) || 0.0001;
16408
 
 
16409
 
        attrs[prop] = {
16410
 
            value: val,
16411
 
            duration: dur,
16412
 
            delay: (typeof config.delay != 'undefined') ? config.delay :
16413
 
                    anim._delay,
16414
 
 
16415
 
            easing: config.easing || anim._easing,
16416
 
 
16417
 
            transition: anim
16418
 
        };
16419
 
 
16420
 
        // native end event doesnt fire when setting to same value
16421
 
        // supplementing with timer
16422
 
        // val may be a string or number (height: 0, etc), but computedStyle is always string
16423
 
        computed = Y.DOM.getComputedStyle(node, prop);
16424
 
        compareVal = (typeof val === 'string') ? computed : parseFloat(computed);
16425
 
 
16426
 
        if (Transition.useNative && compareVal === val) {
16427
 
            setTimeout(function() {
16428
 
                anim._onNativeEnd.call(node, {
16429
 
                    propertyName: prop,
16430
 
                    elapsedTime: dur
16431
 
                });
16432
 
            }, dur * 1000);
16433
 
        }
16434
 
    },
16435
 
 
16436
 
    removeProperty: function(prop) {
16437
 
        var anim = this,
16438
 
            attrs = Transition._nodeAttrs[Y.stamp(anim._node)];
16439
 
 
16440
 
        if (attrs && attrs[prop]) {
16441
 
            delete attrs[prop];
16442
 
            anim._count--;
16443
 
        }
16444
 
 
16445
 
    },
16446
 
 
16447
 
    initAttrs: function(config) {
16448
 
        var attr,
16449
 
            node = this._node;
16450
 
 
16451
 
        if (config.transform && !config[TRANSFORM_CAMEL]) {
16452
 
            config[TRANSFORM_CAMEL] = config.transform;
16453
 
            delete config.transform; // TODO: copy
16454
 
        }
16455
 
 
16456
 
        for (attr in config) {
16457
 
            if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) {
16458
 
                this.addProperty(attr, config[attr]);
16459
 
 
16460
 
                // when size is auto or % webkit starts from zero instead of computed 
16461
 
                // (https://bugs.webkit.org/show_bug.cgi?id=16020)
16462
 
                // TODO: selective set
16463
 
                if (node.style[attr] === '') {
16464
 
                    Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr));
16465
 
                }
16466
 
            }
16467
 
        }
16468
 
    },
16469
 
 
16470
 
    /**
16471
 
     * Starts or an animation.
16472
 
     * @method run
16473
 
     * @chainable
16474
 
     * @private
16475
 
     */    
16476
 
    run: function(callback) {
16477
 
        var anim = this,
16478
 
            node = anim._node,
16479
 
            config = anim._config,
16480
 
            data = {
16481
 
                type: 'transition:start',
16482
 
                config: config
16483
 
            };
16484
 
 
16485
 
 
16486
 
        if (!anim._running) {
16487
 
            anim._running = true;
16488
 
 
16489
 
            //anim._node.fire('transition:start', data);
16490
 
 
16491
 
            if (config.on && config.on.start) {
16492
 
                config.on.start.call(Y.one(node), data);
16493
 
            }
16494
 
 
16495
 
            anim.initAttrs(anim._config);
16496
 
 
16497
 
            anim._callback = callback;
16498
 
            anim._start();
16499
 
        }
16500
 
 
16501
 
 
16502
 
        return anim;
16503
 
    },
16504
 
 
16505
 
    _start: function() {
16506
 
        this._runNative();
16507
 
    },
16508
 
 
16509
 
    _prepDur: function(dur) {
16510
 
        dur = parseFloat(dur);
16511
 
 
16512
 
        return dur + 's';
16513
 
    },
16514
 
 
16515
 
    _runNative: function(time) {
16516
 
        var anim = this,
16517
 
            node = anim._node,
16518
 
            uid = Y.stamp(node),
16519
 
            style = node.style,
16520
 
            computed = getComputedStyle(node),
16521
 
            attrs = Transition._nodeAttrs[uid],
16522
 
            cssText = '',
16523
 
            cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)],
16524
 
 
16525
 
            transitionText = TRANSITION_PROPERTY + ': ',
16526
 
            duration = TRANSITION_DURATION + ': ',
16527
 
            easing = TRANSITION_TIMING_FUNCTION + ': ',
16528
 
            delay = TRANSITION_DELAY + ': ',
16529
 
            hyphy,
16530
 
            attr,
16531
 
            name;
16532
 
 
16533
 
        // preserve existing transitions
16534
 
        if (cssTransition !== 'all') {
16535
 
            transitionText += cssTransition + ',';
16536
 
            duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ',';
16537
 
            easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ',';
16538
 
            delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ',';
16539
 
 
16540
 
        }
16541
 
 
16542
 
        // run transitions mapped to this instance
16543
 
        for (name in attrs) {
16544
 
            hyphy = Transition._toHyphen(name);
16545
 
            attr = attrs[name];
16546
 
            if ((attr = attrs[name]) && attr.transition === anim) {
16547
 
                if (name in node.style) { // only native styles allowed
16548
 
                    duration += anim._prepDur(attr.duration) + ',';
16549
 
                    delay += anim._prepDur(attr.delay) + ',';
16550
 
                    easing += (attr.easing) + ',';
16551
 
 
16552
 
                    transitionText += hyphy + ',';
16553
 
                    cssText += hyphy + ': ' + attr.value + '; ';
16554
 
                } else {
16555
 
                    this.removeProperty(name);
16556
 
                }
16557
 
            }
16558
 
        }
16559
 
 
16560
 
        transitionText = transitionText.replace(/,$/, ';');
16561
 
        duration = duration.replace(/,$/, ';');
16562
 
        easing = easing.replace(/,$/, ';');
16563
 
        delay = delay.replace(/,$/, ';');
16564
 
 
16565
 
        // only one native end event per node
16566
 
        if (!Transition._hasEnd[uid]) {
16567
 
            //anim._detach = Y.on(TRANSITION_END, anim._onNativeEnd, node);
16568
 
            //node[ON_TRANSITION_END] = anim._onNativeEnd;
16569
 
            node.addEventListener(TRANSITION_END, anim._onNativeEnd, '');
16570
 
            Transition._hasEnd[uid] = true;
16571
 
 
16572
 
        }
16573
 
        
16574
 
        //setTimeout(function() { // allow updates to apply (size fix, onstart, etc)
16575
 
            style.cssText += transitionText + duration + easing + delay + cssText;
16576
 
        //}, 1);
16577
 
 
16578
 
    },
16579
 
 
16580
 
    _end: function(elapsed) {
16581
 
        var anim = this,
16582
 
            node = anim._node,
16583
 
            callback = anim._callback,
16584
 
            config = anim._config,
16585
 
            data = {
16586
 
                type: 'transition:end',
16587
 
                config: config,
16588
 
                elapsedTime: elapsed 
16589
 
            },
16590
 
 
16591
 
            nodeInstance = Y.one(node); 
16592
 
 
16593
 
        anim._running = false;
16594
 
        anim._callback = null;
16595
 
 
16596
 
        if (node) {
16597
 
            if (config.on && config.on.end) {
16598
 
                setTimeout(function() { // IE: allow previous update to finish
16599
 
                    config.on.end.call(nodeInstance, data);
16600
 
 
16601
 
                    // nested to ensure proper fire order
16602
 
                    if (callback) {
16603
 
                        callback.call(nodeInstance, data);
16604
 
                    }
16605
 
 
16606
 
                }, 1);
16607
 
            } else if (callback) {
16608
 
                setTimeout(function() { // IE: allow previous update to finish
16609
 
                    callback.call(nodeInstance, data);
16610
 
                }, 1);
16611
 
            }
16612
 
            //node.fire('transition:end', data);
16613
 
        }
16614
 
 
16615
 
    },
16616
 
 
16617
 
    _endNative: function(name) {
16618
 
        var node = this._node,
16619
 
            value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)];
16620
 
 
16621
 
        if (typeof value === 'string') {
16622
 
            value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ',');
16623
 
            value = value.replace(/^,|,$/, '');
16624
 
            node.style[TRANSITION_CAMEL] = value;
16625
 
        }
16626
 
    },
16627
 
 
16628
 
    _onNativeEnd: function(e) {
16629
 
        var node = this,
16630
 
            uid = Y.stamp(node),
16631
 
            event = e,//e._event,
16632
 
            name = Transition._toCamel(event.propertyName),
16633
 
            elapsed = event.elapsedTime,
16634
 
            attrs = Transition._nodeAttrs[uid],
16635
 
            attr = attrs[name],
16636
 
            anim = (attr) ? attr.transition : null,
16637
 
            data,
16638
 
            config;
16639
 
 
16640
 
        if (anim) {
16641
 
            anim.removeProperty(name);
16642
 
            anim._endNative(name);
16643
 
            config = anim._config[name];
16644
 
 
16645
 
            data = {
16646
 
                type: 'propertyEnd',
16647
 
                propertyName: name,
16648
 
                elapsedTime: elapsed,
16649
 
                config: config
16650
 
            };
16651
 
 
16652
 
            if (config && config.on && config.on.end) {
16653
 
                config.on.end.call(Y.one(node), data);
16654
 
            }
16655
 
 
16656
 
            //node.fire('transition:propertyEnd', data);
16657
 
 
16658
 
            if (anim._count <= 0)  { // after propertyEnd fires
16659
 
                anim._end(elapsed);
16660
 
            }
16661
 
        }
16662
 
    },
16663
 
 
16664
 
    destroy: function() {
16665
 
        var anim = this,
16666
 
            node = anim._node;
16667
 
        /*
16668
 
        if (anim._detach) {
16669
 
            anim._detach.detach();
16670
 
        }
16671
 
        */
16672
 
        //anim._node[ON_TRANSITION_END] = null;
16673
 
        if (node) {
16674
 
            node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false);
16675
 
            anim._node = null;
16676
 
        }
16677
 
    }
16678
 
};
16679
 
 
16680
 
Y.Transition = Transition;
16681
 
Y.TransitionNative = Transition; // TODO: remove
16682
 
 
16683
 
/** 
16684
 
 *   Animate one or more css properties to a given value. Requires the "transition" module.
16685
 
 *   <pre>example usage:
16686
 
 *       Y.one('#demo').transition({
16687
 
 *           duration: 1, // in seconds, default is 0.5
16688
 
 *           easing: 'ease-out', // default is 'ease'
16689
 
 *           delay: '1', // delay start for 1 second, default is 0
16690
 
 *
16691
 
 *           height: '10px',
16692
 
 *           width: '10px',
16693
 
 *
16694
 
 *           opacity: { // per property
16695
 
 *               value: 0,
16696
 
 *               duration: 2,
16697
 
 *               delay: 2,
16698
 
 *               easing: 'ease-in'
16699
 
 *           }
16700
 
 *       });
16701
 
 *   </pre>
16702
 
 *   @for Node
16703
 
 *   @method transition
16704
 
 *   @param {Object} config An object containing one or more style properties, a duration and an easing.
16705
 
 *   @param {Function} callback A function to run after the transition has completed. 
16706
 
 *   @chainable
16707
 
*/
16708
 
Y.Node.prototype.transition = function(name, config, callback) {
16709
 
    var 
16710
 
        transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)],
16711
 
        anim = (transitionAttrs) ? transitionAttrs.transition || null : null,
16712
 
        fxConfig,
16713
 
        prop;
16714
 
    
16715
 
    if (typeof name === 'string') { // named effect, pull config from registry
16716
 
        if (typeof config === 'function') {
16717
 
            callback = config;
16718
 
            config = null;
16719
 
        }
16720
 
 
16721
 
        fxConfig = Transition.fx[name];
16722
 
 
16723
 
        if (config && typeof config !== 'boolean') {
16724
 
            config = Y.clone(config);
16725
 
 
16726
 
            for (prop in fxConfig) {
16727
 
                if (fxConfig.hasOwnProperty(prop)) {
16728
 
                    if (! (prop in config)) {
16729
 
                        config[prop] = fxConfig[prop]; 
16730
 
                    }
16731
 
                }
16732
 
            }
16733
 
        } else {
16734
 
            config = fxConfig;
16735
 
        }
16736
 
 
16737
 
    } else { // name is a config, config is a callback or undefined
16738
 
        callback = config;
16739
 
        config = name;
16740
 
    }
16741
 
 
16742
 
    if (anim && !anim._running) {
16743
 
        anim.init(this, config);
16744
 
    } else {
16745
 
        anim = new Transition(this._node, config);
16746
 
    }
16747
 
 
16748
 
    anim.run(callback);
16749
 
    return this;
16750
 
};
16751
 
 
16752
 
Y.Node.prototype.show = function(name, config, callback) {
16753
 
    this._show(); // show prior to transition
16754
 
    if (name && Y.Transition) {
16755
 
        if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
16756
 
            if (typeof config === 'function') {
16757
 
                callback = config;
16758
 
                config = name;
16759
 
            }
16760
 
            name = Transition.SHOW_TRANSITION; 
16761
 
        }    
16762
 
        this.transition(name, config, callback);
16763
 
    }    
16764
 
    else if (name && !Y.Transition) { Y.log('unable to transition show; missing transition module', 'warn', 'node'); }
16765
 
    return this;
16766
 
};
16767
 
 
16768
 
var _wrapCallBack = function(anim, fn, callback) {
16769
 
    return function() {
16770
 
        if (fn) {
16771
 
            fn.call(anim);
16772
 
        }
16773
 
        if (callback) {
16774
 
            callback.apply(anim._node, arguments);
16775
 
        }
16776
 
    };
16777
 
};
16778
 
 
16779
 
Y.Node.prototype.hide = function(name, config, callback) {
16780
 
    if (name && Y.Transition) {
16781
 
        if (typeof config === 'function') {
16782
 
            callback = config;
16783
 
            config = null;
16784
 
        }
16785
 
 
16786
 
        callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback
16787
 
        if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default
16788
 
            if (typeof config === 'function') {
16789
 
                callback = config;
16790
 
                config = name;
16791
 
            }
16792
 
            name = Transition.HIDE_TRANSITION; 
16793
 
        }    
16794
 
        this.transition(name, config, callback);
16795
 
    } else if (name && !Y.Transition) { Y.log('unable to transition hide; missing transition module', 'warn', 'node'); // end if on nex
16796
 
    } else {
16797
 
        this._hide();
16798
 
    }    
16799
 
    return this;
16800
 
}; 
16801
 
 
16802
 
/** 
16803
 
 *   Animate one or more css properties to a given value. Requires the "transition" module.
16804
 
 *   <pre>example usage:
16805
 
 *       Y.all('.demo').transition({
16806
 
 *           duration: 1, // in seconds, default is 0.5
16807
 
 *           easing: 'ease-out', // default is 'ease'
16808
 
 *           delay: '1', // delay start for 1 second, default is 0
16809
 
 *
16810
 
 *           height: '10px',
16811
 
 *           width: '10px',
16812
 
 *
16813
 
 *           opacity: { // per property
16814
 
 *               value: 0,
16815
 
 *               duration: 2,
16816
 
 *               delay: 2,
16817
 
 *               easing: 'ease-in'
16818
 
 *           }
16819
 
 *       });
16820
 
 *   </pre>
16821
 
 *   @for NodeList
16822
 
 *   @method transition
16823
 
 *   @param {Object} config An object containing one or more style properties, a duration and an easing.
16824
 
 *   @param {Function} callback A function to run after the transition has completed. The callback fires
16825
 
 *       once per item in the NodeList.
16826
 
 *   @chainable
16827
 
*/
16828
 
Y.NodeList.prototype.transition = function(config, callback) {
16829
 
    var nodes = this._nodes,
16830
 
        i = 0,
16831
 
        node;
16832
 
 
16833
 
    while ((node = nodes[i++])) {
16834
 
        Y.one(node).transition(config, callback);
16835
 
    }
16836
 
 
16837
 
    return this;
16838
 
};
16839
 
 
16840
 
Y.Node.prototype.toggleView = function(name, on, callback) {
16841
 
    this._toggles = this._toggles || [];
16842
 
    callback = arguments[arguments.length - 1];
16843
 
 
16844
 
    if (typeof name == 'boolean') { // no transition, just toggle
16845
 
        on = name;
16846
 
        name = null;
16847
 
    }
16848
 
 
16849
 
    name = name || Y.Transition.DEFAULT_TOGGLE;
16850
 
 
16851
 
    if (typeof on == 'undefined' && name in this._toggles) { // reverse current toggle
16852
 
        on = ! this._toggles[name];
16853
 
    }
16854
 
 
16855
 
    on = (on) ? 1 : 0;
16856
 
    if (on) {
16857
 
        this._show();
16858
 
    }  else {
16859
 
        callback = _wrapCallBack(this, this._hide, callback);
16860
 
    }
16861
 
 
16862
 
    this._toggles[name] = on;
16863
 
    this.transition(Y.Transition.toggles[name][on], callback);
16864
 
 
16865
 
    return this;
16866
 
};
16867
 
 
16868
 
Y.NodeList.prototype.toggleView = function(name, on, callback) {
16869
 
    var nodes = this._nodes,
16870
 
        i = 0,
16871
 
        node;
16872
 
 
16873
 
    while ((node = nodes[i++])) {
16874
 
        Y.one(node).toggleView(name, on, callback);
16875
 
    }
16876
 
 
16877
 
    return this;
16878
 
};
16879
 
 
16880
 
Y.mix(Transition.fx, {
16881
 
    fadeOut: {
16882
 
        opacity: 0,
16883
 
        duration: 0.5,
16884
 
        easing: 'ease-out'
16885
 
    },
16886
 
 
16887
 
    fadeIn: {
16888
 
        opacity: 1,
16889
 
        duration: 0.5,
16890
 
        easing: 'ease-in'
16891
 
    },
16892
 
 
16893
 
    sizeOut: {
16894
 
        height: 0,
16895
 
        width: 0,
16896
 
        duration: 0.75,
16897
 
        easing: 'ease-out'
16898
 
    },
16899
 
 
16900
 
    sizeIn: {
16901
 
        height: function(node) {
16902
 
            return node.get('scrollHeight') + 'px';
16903
 
        },
16904
 
        width: function(node) {
16905
 
            return node.get('scrollWidth') + 'px';
16906
 
        },
16907
 
        duration: 0.5,
16908
 
        easing: 'ease-in',
16909
 
        
16910
 
        on: {
16911
 
            start: function() {
16912
 
                var overflow = this.getStyle('overflow');
16913
 
                if (overflow !== 'hidden') { // enable scrollHeight/Width
16914
 
                    this.setStyle('overflow', 'hidden');
16915
 
                    this._transitionOverflow = overflow;
16916
 
                }
16917
 
            },
16918
 
 
16919
 
            end: function() {
16920
 
                if (this._transitionOverflow) { // revert overridden value
16921
 
                    this.setStyle('overflow', this._transitionOverflow);
16922
 
                    delete this._transitionOverflow;
16923
 
                }
16924
 
            }
16925
 
        } 
16926
 
    }
16927
 
});
16928
 
 
16929
 
Y.mix(Transition.toggles, {
16930
 
    size: ['sizeOut', 'sizeIn'],
16931
 
    fade: ['fadeOut', 'fadeIn']
16932
 
});
16933
 
 
16934
 
Transition.DEFAULT_TOGGLE = 'fade';
16935
 
 
16936
 
 
16937
 
 
16938
 
}, '3.4.1' ,{requires:['node-style']});
16939
 
YUI.add('selector-css2', function(Y) {
16940
 
 
16941
 
/**
16942
 
 * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
16943
 
 * @module dom
16944
 
 * @submodule selector-css2
16945
 
 * @for Selector
16946
 
 */
16947
 
 
16948
 
/**
16949
 
 * Provides helper methods for collecting and filtering DOM elements.
16950
 
 */
16951
 
 
16952
 
var PARENT_NODE = 'parentNode',
16953
 
    TAG_NAME = 'tagName',
16954
 
    ATTRIBUTES = 'attributes',
16955
 
    COMBINATOR = 'combinator',
16956
 
    PSEUDOS = 'pseudos',
16957
 
 
16958
 
    Selector = Y.Selector,
16959
 
 
16960
 
    SelectorCSS2 = {
16961
 
        _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/, // TODO: move?
16962
 
        SORT_RESULTS: true,
16963
 
        _children: function(node, tag) {
16964
 
            var ret = node.children,
16965
 
                i,
16966
 
                children = [],
16967
 
                childNodes,
16968
 
                child;
16969
 
 
16970
 
            if (node.children && tag && node.children.tags) {
16971
 
                children = node.children.tags(tag);
16972
 
            } else if ((!ret && node[TAG_NAME]) || (ret && tag)) { // only HTMLElements have children
16973
 
                childNodes = ret || node.childNodes;
16974
 
                ret = [];
16975
 
                for (i = 0; (child = childNodes[i++]);) {
16976
 
                    if (child.tagName) {
16977
 
                        if (!tag || tag === child.tagName) {
16978
 
                            ret.push(child);
16979
 
                        }
16980
 
                    }
16981
 
                }
16982
 
            }
16983
 
 
16984
 
            return ret || [];
16985
 
        },
16986
 
 
16987
 
        _re: {
16988
 
            attr: /(\[[^\]]*\])/g,
16989
 
            esc: /\\[:\[\]\(\)#\.\'\>+~"]/gi,
16990
 
            pseudos: /(\([^\)]*\))/g
16991
 
        },
16992
 
 
16993
 
        /**
16994
 
         * Mapping of shorthand tokens to corresponding attribute selector 
16995
 
         * @property shorthand
16996
 
         * @type object
16997
 
         */
16998
 
        shorthand: {
16999
 
            '\\#(-?[_a-z0-9]+[-\\w\\uE000]*)': '[id=$1]',
17000
 
            '\\.(-?[_a-z]+[-\\w\\uE000]*)': '[className~=$1]'
17001
 
        },
17002
 
 
17003
 
        /**
17004
 
         * List of operators and corresponding boolean functions. 
17005
 
         * These functions are passed the attribute and the current node's value of the attribute.
17006
 
         * @property operators
17007
 
         * @type object
17008
 
         */
17009
 
        operators: {
17010
 
            '': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute
17011
 
            //'': '.+',
17012
 
            //'=': '^{val}$', // equality
17013
 
            '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
17014
 
            '|=': '^{val}-?' // optional hyphen-delimited
17015
 
        },
17016
 
 
17017
 
        pseudos: {
17018
 
           'first-child': function(node) { 
17019
 
                return Y.Selector._children(node[PARENT_NODE])[0] === node; 
17020
 
            } 
17021
 
        },
17022
 
 
17023
 
        _bruteQuery: function(selector, root, firstOnly) {
17024
 
            var ret = [],
17025
 
                nodes = [],
17026
 
                tokens = Selector._tokenize(selector),
17027
 
                token = tokens[tokens.length - 1],
17028
 
                rootDoc = Y.DOM._getDoc(root),
17029
 
                child,
17030
 
                id,
17031
 
                className,
17032
 
                tagName;
17033
 
 
17034
 
 
17035
 
            // if we have an initial ID, set to root when in document
17036
 
            /*
17037
 
            if (tokens[0] && rootDoc === root &&  
17038
 
                    (id = tokens[0].id) &&
17039
 
                    rootDoc.getElementById(id)) {
17040
 
                root = rootDoc.getElementById(id);
17041
 
            }
17042
 
            */
17043
 
 
17044
 
            if (token) {
17045
 
                // prefilter nodes
17046
 
                id = token.id;
17047
 
                className = token.className;
17048
 
                tagName = token.tagName || '*';
17049
 
 
17050
 
                if (root.getElementsByTagName) { // non-IE lacks DOM api on doc frags
17051
 
                    // try ID first, unless no root.all && root not in document
17052
 
                    // (root.all works off document, but not getElementById)
17053
 
                    // TODO: move to allById?
17054
 
                    if (id && (root.all || (root.nodeType === 9 || Y.DOM.inDoc(root)))) {
17055
 
                        nodes = Y.DOM.allById(id, root);
17056
 
                    // try className
17057
 
                    } else if (className) {
17058
 
                        nodes = root.getElementsByClassName(className);
17059
 
                    } else { // default to tagName
17060
 
                        nodes = root.getElementsByTagName(tagName);
17061
 
                    }
17062
 
 
17063
 
                } else { // brute getElementsByTagName('*')
17064
 
                    child = root.firstChild;
17065
 
                    while (child) {
17066
 
                        if (child.tagName) { // only collect HTMLElements
17067
 
                            nodes.push(child);
17068
 
                        }
17069
 
                        child = child.nextSilbing || child.firstChild;
17070
 
                    }
17071
 
                }
17072
 
                if (nodes.length) {
17073
 
                    ret = Selector._filterNodes(nodes, tokens, firstOnly);
17074
 
                }
17075
 
            }
17076
 
 
17077
 
            return ret;
17078
 
        },
17079
 
        
17080
 
        _filterNodes: function(nodes, tokens, firstOnly) {
17081
 
            var i = 0,
17082
 
                j,
17083
 
                len = tokens.length,
17084
 
                n = len - 1,
17085
 
                result = [],
17086
 
                node = nodes[0],
17087
 
                tmpNode = node,
17088
 
                getters = Y.Selector.getters,
17089
 
                operator,
17090
 
                combinator,
17091
 
                token,
17092
 
                path,
17093
 
                pass,
17094
 
                //FUNCTION = 'function',
17095
 
                value,
17096
 
                tests,
17097
 
                test;
17098
 
 
17099
 
            //do {
17100
 
            for (i = 0; (tmpNode = node = nodes[i++]);) {
17101
 
                n = len - 1;
17102
 
                path = null;
17103
 
                
17104
 
                testLoop:
17105
 
                while (tmpNode && tmpNode.tagName) {
17106
 
                    token = tokens[n];
17107
 
                    tests = token.tests;
17108
 
                    j = tests.length;
17109
 
                    if (j && !pass) {
17110
 
                        while ((test = tests[--j])) {
17111
 
                            operator = test[1];
17112
 
                            if (getters[test[0]]) {
17113
 
                                value = getters[test[0]](tmpNode, test[0]);
17114
 
                            } else {
17115
 
                                value = tmpNode[test[0]];
17116
 
                                // use getAttribute for non-standard attributes
17117
 
                                if (value === undefined && tmpNode.getAttribute) {
17118
 
                                    value = tmpNode.getAttribute(test[0]);
17119
 
                                }
17120
 
                            }
17121
 
 
17122
 
                            if ((operator === '=' && value !== test[2]) ||  // fast path for equality
17123
 
                                (typeof operator !== 'string' && // protect against String.test monkey-patch (Moo)
17124
 
                                operator.test && !operator.test(value)) ||  // regex test
17125
 
                                (!operator.test && // protect against RegExp as function (webkit)
17126
 
                                        typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // function test
17127
 
 
17128
 
                                // skip non element nodes or non-matching tags
17129
 
                                if ((tmpNode = tmpNode[path])) {
17130
 
                                    while (tmpNode &&
17131
 
                                        (!tmpNode.tagName ||
17132
 
                                            (token.tagName && token.tagName !== tmpNode.tagName))
17133
 
                                    ) {
17134
 
                                        tmpNode = tmpNode[path]; 
17135
 
                                    }
17136
 
                                }
17137
 
                                continue testLoop;
17138
 
                            }
17139
 
                        }
17140
 
                    }
17141
 
 
17142
 
                    n--; // move to next token
17143
 
                    // now that we've passed the test, move up the tree by combinator
17144
 
                    if (!pass && (combinator = token.combinator)) {
17145
 
                        path = combinator.axis;
17146
 
                        tmpNode = tmpNode[path];
17147
 
 
17148
 
                        // skip non element nodes
17149
 
                        while (tmpNode && !tmpNode.tagName) {
17150
 
                            tmpNode = tmpNode[path]; 
17151
 
                        }
17152
 
 
17153
 
                        if (combinator.direct) { // one pass only
17154
 
                            path = null; 
17155
 
                        }
17156
 
 
17157
 
                    } else { // success if we made it this far
17158
 
                        result.push(node);
17159
 
                        if (firstOnly) {
17160
 
                            return result;
17161
 
                        }
17162
 
                        break;
17163
 
                    }
17164
 
                }
17165
 
            }// while (tmpNode = node = nodes[++i]);
17166
 
            node = tmpNode = null;
17167
 
            return result;
17168
 
        },
17169
 
 
17170
 
        combinators: {
17171
 
            ' ': {
17172
 
                axis: 'parentNode'
17173
 
            },
17174
 
 
17175
 
            '>': {
17176
 
                axis: 'parentNode',
17177
 
                direct: true
17178
 
            },
17179
 
 
17180
 
 
17181
 
            '+': {
17182
 
                axis: 'previousSibling',
17183
 
                direct: true
17184
 
            }
17185
 
        },
17186
 
 
17187
 
        _parsers: [
17188
 
            {
17189
 
                name: ATTRIBUTES,
17190
 
                re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,
17191
 
                fn: function(match, token) {
17192
 
                    var operator = match[2] || '',
17193
 
                        operators = Selector.operators,
17194
 
                        escVal = (match[3]) ? match[3].replace(/\\/g, '') : '',
17195
 
                        test;
17196
 
 
17197
 
                    // add prefiltering for ID and CLASS
17198
 
                    if ((match[1] === 'id' && operator === '=') ||
17199
 
                            (match[1] === 'className' &&
17200
 
                            Y.config.doc.documentElement.getElementsByClassName &&
17201
 
                            (operator === '~=' || operator === '='))) {
17202
 
                        token.prefilter = match[1];
17203
 
 
17204
 
 
17205
 
                        match[3] = escVal; 
17206
 
 
17207
 
                        // escape all but ID for prefilter, which may run through QSA (via Dom.allById)
17208
 
                        token[match[1]] = (match[1] === 'id') ? match[3] : escVal;
17209
 
 
17210
 
                    }
17211
 
 
17212
 
                    // add tests
17213
 
                    if (operator in operators) {
17214
 
                        test = operators[operator];
17215
 
                        if (typeof test === 'string') {
17216
 
                            match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1');
17217
 
                            test = new RegExp(test.replace('{val}', match[3]));
17218
 
                        }
17219
 
                        match[2] = test;
17220
 
                    }
17221
 
                    if (!token.last || token.prefilter !== match[1]) {
17222
 
                        return match.slice(1);
17223
 
                    }
17224
 
                }
17225
 
            },
17226
 
            {
17227
 
                name: TAG_NAME,
17228
 
                re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
17229
 
                fn: function(match, token) {
17230
 
                    var tag = match[1].toUpperCase();
17231
 
                    token.tagName = tag;
17232
 
 
17233
 
                    if (tag !== '*' && (!token.last || token.prefilter)) {
17234
 
                        return [TAG_NAME, '=', tag];
17235
 
                    }
17236
 
                    if (!token.prefilter) {
17237
 
                        token.prefilter = 'tagName';
17238
 
                    }
17239
 
                }
17240
 
            },
17241
 
            {
17242
 
                name: COMBINATOR,
17243
 
                re: /^\s*([>+~]|\s)\s*/,
17244
 
                fn: function(match, token) {
17245
 
                }
17246
 
            },
17247
 
            {
17248
 
                name: PSEUDOS,
17249
 
                re: /^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,
17250
 
                fn: function(match, token) {
17251
 
                    var test = Selector[PSEUDOS][match[1]];
17252
 
                    if (test) { // reorder match array and unescape special chars for tests
17253
 
                        if (match[2]) {
17254
 
                            match[2] = match[2].replace(/\\/g, '');
17255
 
                        }
17256
 
                        return [match[2], test]; 
17257
 
                    } else { // selector token not supported (possibly missing CSS3 module)
17258
 
                        return false;
17259
 
                    }
17260
 
                }
17261
 
            }
17262
 
            ],
17263
 
 
17264
 
        _getToken: function(token) {
17265
 
            return {
17266
 
                tagName: null,
17267
 
                id: null,
17268
 
                className: null,
17269
 
                attributes: {},
17270
 
                combinator: null,
17271
 
                tests: []
17272
 
            };
17273
 
        },
17274
 
 
17275
 
        /**
17276
 
            Break selector into token units per simple selector.
17277
 
            Combinator is attached to the previous token.
17278
 
         */
17279
 
        _tokenize: function(selector) {
17280
 
            selector = selector || '';
17281
 
            selector = Selector._replaceShorthand(Y.Lang.trim(selector)); 
17282
 
            var token = Selector._getToken(),     // one token per simple selector (left selector holds combinator)
17283
 
                query = selector, // original query for debug report
17284
 
                tokens = [],    // array of tokens
17285
 
                found = false,  // whether or not any matches were found this pass
17286
 
                match,         // the regex match
17287
 
                test,
17288
 
                i, parser;
17289
 
 
17290
 
            /*
17291
 
                Search for selector patterns, store, and strip them from the selector string
17292
 
                until no patterns match (invalid selector) or we run out of chars.
17293
 
 
17294
 
                Multiple attributes and pseudos are allowed, in any order.
17295
 
                for example:
17296
 
                    'form:first-child[type=button]:not(button)[lang|=en]'
17297
 
            */
17298
 
            outer:
17299
 
            do {
17300
 
                found = false; // reset after full pass
17301
 
                for (i = 0; (parser = Selector._parsers[i++]);) {
17302
 
                    if ( (match = parser.re.exec(selector)) ) { // note assignment
17303
 
                        if (parser.name !== COMBINATOR ) {
17304
 
                            token.selector = selector;
17305
 
                        }
17306
 
                        selector = selector.replace(match[0], ''); // strip current match from selector
17307
 
                        if (!selector.length) {
17308
 
                            token.last = true;
17309
 
                        }
17310
 
 
17311
 
                        if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
17312
 
                            match[1] = Selector._attrFilters[match[1]];
17313
 
                        }
17314
 
 
17315
 
                        test = parser.fn(match, token);
17316
 
                        if (test === false) { // selector not supported
17317
 
                            found = false;
17318
 
                            break outer;
17319
 
                        } else if (test) {
17320
 
                            token.tests.push(test);
17321
 
                        }
17322
 
 
17323
 
                        if (!selector.length || parser.name === COMBINATOR) {
17324
 
                            tokens.push(token);
17325
 
                            token = Selector._getToken(token);
17326
 
                            if (parser.name === COMBINATOR) {
17327
 
                                token.combinator = Y.Selector.combinators[match[1]];
17328
 
                            }
17329
 
                        }
17330
 
                        found = true;
17331
 
                    }
17332
 
                }
17333
 
            } while (found && selector.length);
17334
 
 
17335
 
            if (!found || selector.length) { // not fully parsed
17336
 
                Y.log('query: ' + query + ' contains unsupported token in: ' + selector, 'warn', 'Selector');
17337
 
                tokens = [];
17338
 
            }
17339
 
            return tokens;
17340
 
        },
17341
 
 
17342
 
        _replaceShorthand: function(selector) {
17343
 
            var shorthand = Selector.shorthand,
17344
 
                esc = selector.match(Selector._re.esc), // pull escaped colon, brackets, etc. 
17345
 
                attrs,
17346
 
                pseudos,
17347
 
                re, i, len;
17348
 
 
17349
 
            if (esc) {
17350
 
                selector = selector.replace(Selector._re.esc, '\uE000');
17351
 
            }
17352
 
 
17353
 
            attrs = selector.match(Selector._re.attr);
17354
 
            pseudos = selector.match(Selector._re.pseudos);
17355
 
 
17356
 
            if (attrs) {
17357
 
                selector = selector.replace(Selector._re.attr, '\uE001');
17358
 
            }
17359
 
 
17360
 
            if (pseudos) {
17361
 
                selector = selector.replace(Selector._re.pseudos, '\uE002');
17362
 
            }
17363
 
 
17364
 
 
17365
 
            for (re in shorthand) {
17366
 
                if (shorthand.hasOwnProperty(re)) {
17367
 
                    selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]);
17368
 
                }
17369
 
            }
17370
 
 
17371
 
            if (attrs) {
17372
 
                for (i = 0, len = attrs.length; i < len; ++i) {
17373
 
                    selector = selector.replace(/\uE001/, attrs[i]);
17374
 
                }
17375
 
            }
17376
 
 
17377
 
            if (pseudos) {
17378
 
                for (i = 0, len = pseudos.length; i < len; ++i) {
17379
 
                    selector = selector.replace(/\uE002/, pseudos[i]);
17380
 
                }
17381
 
            }
17382
 
 
17383
 
            selector = selector.replace(/\[/g, '\uE003');
17384
 
            selector = selector.replace(/\]/g, '\uE004');
17385
 
 
17386
 
            selector = selector.replace(/\(/g, '\uE005');
17387
 
            selector = selector.replace(/\)/g, '\uE006');
17388
 
 
17389
 
            if (esc) {
17390
 
                for (i = 0, len = esc.length; i < len; ++i) {
17391
 
                    selector = selector.replace('\uE000', esc[i]);
17392
 
                }
17393
 
            }
17394
 
 
17395
 
            return selector;
17396
 
        },
17397
 
 
17398
 
        _attrFilters: {
17399
 
            'class': 'className',
17400
 
            'for': 'htmlFor'
17401
 
        },
17402
 
 
17403
 
        getters: {
17404
 
            href: function(node, attr) {
17405
 
                return Y.DOM.getAttribute(node, attr);
17406
 
            }
17407
 
        }
17408
 
    };
17409
 
 
17410
 
Y.mix(Y.Selector, SelectorCSS2, true);
17411
 
Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
17412
 
 
17413
 
// IE wants class with native queries
17414
 
if (Y.Selector.useNative && Y.config.doc.querySelector) {
17415
 
    Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
17416
 
}
17417
 
 
17418
 
 
17419
 
 
17420
 
}, '3.4.1' ,{requires:['selector-native']});
17421
 
YUI.add('selector-css3', function(Y) {
17422
 
 
17423
 
/**
17424
 
 * The selector css3 module provides support for css3 selectors.
17425
 
 * @module dom
17426
 
 * @submodule selector-css3
17427
 
 * @for Selector
17428
 
 */
17429
 
 
17430
 
/*
17431
 
    an+b = get every _a_th node starting at the _b_th
17432
 
    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
17433
 
    1n+b =  get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
17434
 
    an+0 = get every _a_th element, "0" may be omitted 
17435
 
*/
17436
 
 
17437
 
Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
17438
 
 
17439
 
Y.Selector._getNth = function(node, expr, tag, reverse) {
17440
 
    Y.Selector._reNth.test(expr);
17441
 
    var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
17442
 
        n = RegExp.$2, // "n"
17443
 
        oddeven = RegExp.$3, // "odd" or "even"
17444
 
        b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
17445
 
        result = [],
17446
 
        siblings = Y.Selector._children(node.parentNode, tag),
17447
 
        op;
17448
 
 
17449
 
    if (oddeven) {
17450
 
        a = 2; // always every other
17451
 
        op = '+';
17452
 
        n = 'n';
17453
 
        b = (oddeven === 'odd') ? 1 : 0;
17454
 
    } else if ( isNaN(a) ) {
17455
 
        a = (n) ? 1 : 0; // start from the first or no repeat
17456
 
    }
17457
 
 
17458
 
    if (a === 0) { // just the first
17459
 
        if (reverse) {
17460
 
            b = siblings.length - b + 1; 
17461
 
        }
17462
 
 
17463
 
        if (siblings[b - 1] === node) {
17464
 
            return true;
17465
 
        } else {
17466
 
            return false;
17467
 
        }
17468
 
 
17469
 
    } else if (a < 0) {
17470
 
        reverse = !!reverse;
17471
 
        a = Math.abs(a);
17472
 
    }
17473
 
 
17474
 
    if (!reverse) {
17475
 
        for (var i = b - 1, len = siblings.length; i < len; i += a) {
17476
 
            if ( i >= 0 && siblings[i] === node ) {
17477
 
                return true;
17478
 
            }
17479
 
        }
17480
 
    } else {
17481
 
        for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
17482
 
            if ( i < len && siblings[i] === node ) {
17483
 
                return true;
17484
 
            }
17485
 
        }
17486
 
    }
17487
 
    return false;
17488
 
};
17489
 
 
17490
 
Y.mix(Y.Selector.pseudos, {
17491
 
    'root': function(node) {
17492
 
        return node === node.ownerDocument.documentElement;
17493
 
    },
17494
 
 
17495
 
    'nth-child': function(node, expr) {
17496
 
        return Y.Selector._getNth(node, expr);
17497
 
    },
17498
 
 
17499
 
    'nth-last-child': function(node, expr) {
17500
 
        return Y.Selector._getNth(node, expr, null, true);
17501
 
    },
17502
 
 
17503
 
    'nth-of-type': function(node, expr) {
17504
 
        return Y.Selector._getNth(node, expr, node.tagName);
17505
 
    },
17506
 
     
17507
 
    'nth-last-of-type': function(node, expr) {
17508
 
        return Y.Selector._getNth(node, expr, node.tagName, true);
17509
 
    },
17510
 
     
17511
 
    'last-child': function(node) {
17512
 
        var children = Y.Selector._children(node.parentNode);
17513
 
        return children[children.length - 1] === node;
17514
 
    },
17515
 
 
17516
 
    'first-of-type': function(node) {
17517
 
        return Y.Selector._children(node.parentNode, node.tagName)[0] === node;
17518
 
    },
17519
 
     
17520
 
    'last-of-type': function(node) {
17521
 
        var children = Y.Selector._children(node.parentNode, node.tagName);
17522
 
        return children[children.length - 1] === node;
17523
 
    },
17524
 
     
17525
 
    'only-child': function(node) {
17526
 
        var children = Y.Selector._children(node.parentNode);
17527
 
        return children.length === 1 && children[0] === node;
17528
 
    },
17529
 
 
17530
 
    'only-of-type': function(node) {
17531
 
        var children = Y.Selector._children(node.parentNode, node.tagName);
17532
 
        return children.length === 1 && children[0] === node;
17533
 
    },
17534
 
 
17535
 
    'empty': function(node) {
17536
 
        return node.childNodes.length === 0;
17537
 
    },
17538
 
 
17539
 
    'not': function(node, expr) {
17540
 
        return !Y.Selector.test(node, expr);
17541
 
    },
17542
 
 
17543
 
    'contains': function(node, expr) {
17544
 
        var text = node.innerText || node.textContent || '';
17545
 
        return text.indexOf(expr) > -1;
17546
 
    },
17547
 
 
17548
 
    'checked': function(node) {
17549
 
        return (node.checked === true || node.selected === true);
17550
 
    },
17551
 
 
17552
 
    enabled: function(node) {
17553
 
        return (node.disabled !== undefined && !node.disabled);
17554
 
    },
17555
 
 
17556
 
    disabled: function(node) {
17557
 
        return (node.disabled);
17558
 
    }
17559
 
});
17560
 
 
17561
 
Y.mix(Y.Selector.operators, {
17562
 
    '^=': '^{val}', // Match starts with value
17563
 
    '$=': '{val}$', // Match ends with value
17564
 
    '*=': '{val}' // Match contains value as substring 
17565
 
});
17566
 
 
17567
 
Y.Selector.combinators['~'] = {
17568
 
    axis: 'previousSibling'
17569
 
};
17570
 
 
17571
 
 
17572
 
}, '3.4.1' ,{requires:['selector-native', 'selector-css2']});
17573
 
YUI.add('yui-log', function(Y) {
17574
 
 
17575
 
/**
17576
 
 * Provides console log capability and exposes a custom event for
17577
 
 * console implementations. This module is a `core` YUI module, <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
17578
 
 *
17579
 
 * @module yui
17580
 
 * @submodule yui-log
17581
 
 */
17582
 
 
17583
 
var INSTANCE = Y,
17584
 
    LOGEVENT = 'yui:log',
17585
 
    UNDEFINED = 'undefined',
17586
 
    LEVELS = { debug: 1,
17587
 
               info: 1,
17588
 
               warn: 1,
17589
 
               error: 1 };
17590
 
 
17591
 
/**
17592
 
 * If the 'debug' config is true, a 'yui:log' event will be
17593
 
 * dispatched, which the Console widget and anything else
17594
 
 * can consume.  If the 'useBrowserConsole' config is true, it will
17595
 
 * write to the browser console if available.  YUI-specific log
17596
 
 * messages will only be present in the -debug versions of the
17597
 
 * JS files.  The build system is supposed to remove log statements
17598
 
 * from the raw and minified versions of the files.
17599
 
 *
17600
 
 * @method log
17601
 
 * @for YUI
17602
 
 * @param  {String}  msg  The message to log.
17603
 
 * @param  {String}  cat  The log category for the message.  Default
17604
 
 *                        categories are "info", "warn", "error", time".
17605
 
 *                        Custom categories can be used as well. (opt).
17606
 
 * @param  {String}  src  The source of the the message (opt).
17607
 
 * @param  {boolean} silent If true, the log event won't fire.
17608
 
 * @return {YUI}      YUI instance.
17609
 
 */
17610
 
INSTANCE.log = function(msg, cat, src, silent) {
17611
 
    var bail, excl, incl, m, f,
17612
 
        Y = INSTANCE,
17613
 
        c = Y.config,
17614
 
        publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
17615
 
    // suppress log message if the config is off or the event stack
17616
 
    // or the event call stack contains a consumer of the yui:log event
17617
 
    if (c.debug) {
17618
 
        // apply source filters
17619
 
        if (src) {
17620
 
            excl = c.logExclude;
17621
 
            incl = c.logInclude;
17622
 
            if (incl && !(src in incl)) {
17623
 
                bail = 1;
17624
 
            } else if (incl && (src in incl)) {
17625
 
                bail = !incl[src];
17626
 
            } else if (excl && (src in excl)) {
17627
 
                bail = excl[src];
17628
 
            }
17629
 
        }
17630
 
        if (!bail) {
17631
 
            if (c.useBrowserConsole) {
17632
 
                m = (src) ? src + ': ' + msg : msg;
17633
 
                if (Y.Lang.isFunction(c.logFn)) {
17634
 
                    c.logFn.call(Y, msg, cat, src);
17635
 
                } else if (typeof console != UNDEFINED && console.log) {
17636
 
                    f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
17637
 
                    console[f](m);
17638
 
                } else if (typeof opera != UNDEFINED) {
17639
 
                    opera.postError(m);
17640
 
                }
17641
 
            }
17642
 
 
17643
 
            if (publisher && !silent) {
17644
 
 
17645
 
                if (publisher == Y && (!publisher.getEvent(LOGEVENT))) {
17646
 
                    publisher.publish(LOGEVENT, {
17647
 
                        broadcast: 2
17648
 
                    });
17649
 
                }
17650
 
 
17651
 
                publisher.fire(LOGEVENT, {
17652
 
                    msg: msg,
17653
 
                    cat: cat,
17654
 
                    src: src
17655
 
                });
17656
 
            }
17657
 
        }
17658
 
    }
17659
 
 
17660
 
    return Y;
17661
 
};
17662
 
 
17663
 
/**
17664
 
 * Write a system message.  This message will be preserved in the
17665
 
 * minified and raw versions of the YUI files, unlike log statements.
17666
 
 * @method message
17667
 
 * @for YUI
17668
 
 * @param  {String}  msg  The message to log.
17669
 
 * @param  {String}  cat  The log category for the message.  Default
17670
 
 *                        categories are "info", "warn", "error", time".
17671
 
 *                        Custom categories can be used as well. (opt).
17672
 
 * @param  {String}  src  The source of the the message (opt).
17673
 
 * @param  {boolean} silent If true, the log event won't fire.
17674
 
 * @return {YUI}      YUI instance.
17675
 
 */
17676
 
INSTANCE.message = function() {
17677
 
    return INSTANCE.log.apply(INSTANCE, arguments);
17678
 
};
17679
 
 
17680
 
 
17681
 
}, '3.4.1' ,{requires:['yui-base']});
17682
 
YUI.add('dump', function(Y) {
17683
 
 
17684
 
/**
17685
 
 * Returns a simple string representation of the object or array.
17686
 
 * Other types of objects will be returned unprocessed.  Arrays
17687
 
 * are expected to be indexed.  Use object notation for
17688
 
 * associative arrays.
17689
 
 *
17690
 
 * If included, the dump method is added to the YUI instance.
17691
 
 *
17692
 
 * @module dump
17693
 
 */
17694
 
 
17695
 
    var L = Y.Lang,
17696
 
        OBJ = '{...}',
17697
 
        FUN = 'f(){...}',
17698
 
        COMMA = ', ',
17699
 
        ARROW = ' => ',
17700
 
 
17701
 
    /**
17702
 
     * Returns a simple string representation of the object or array.
17703
 
     * Other types of objects will be returned unprocessed.  Arrays
17704
 
     * are expected to be indexed.
17705
 
     *
17706
 
     * @method dump
17707
 
     * @param {Object} o The object to dump.
17708
 
     * @param {Number} d How deep to recurse child objects, default 3.
17709
 
     * @return {String} the dump result.
17710
 
     * @for YUI
17711
 
     */
17712
 
    dump = function(o, d) {
17713
 
        var i, len, s = [], type = L.type(o);
17714
 
 
17715
 
        // Cast non-objects to string
17716
 
        // Skip dates because the std toString is what we want
17717
 
        // Skip HTMLElement-like objects because trying to dump
17718
 
        // an element will cause an unhandled exception in FF 2.x
17719
 
        if (!L.isObject(o)) {
17720
 
            return o + '';
17721
 
        } else if (type == 'date') {
17722
 
            return o;
17723
 
        } else if (o.nodeType && o.tagName) {
17724
 
            return o.tagName + '#' + o.id;
17725
 
        } else if (o.document && o.navigator) {
17726
 
            return 'window';
17727
 
        } else if (o.location && o.body) {
17728
 
            return 'document';
17729
 
        } else if (type == 'function') {
17730
 
            return FUN;
17731
 
        }
17732
 
 
17733
 
        // dig into child objects the depth specifed. Default 3
17734
 
        d = (L.isNumber(d)) ? d : 3;
17735
 
 
17736
 
        // arrays [1, 2, 3]
17737
 
        if (type == 'array') {
17738
 
            s.push('[');
17739
 
            for (i = 0, len = o.length; i < len; i = i + 1) {
17740
 
                if (L.isObject(o[i])) {
17741
 
                    s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
17742
 
                } else {
17743
 
                    s.push(o[i]);
17744
 
                }
17745
 
                s.push(COMMA);
17746
 
            }
17747
 
            if (s.length > 1) {
17748
 
                s.pop();
17749
 
            }
17750
 
            s.push(']');
17751
 
        // regexp /foo/
17752
 
        } else if (type == 'regexp') {
17753
 
            s.push(o.toString());
17754
 
        // objects {k1 => v1, k2 => v2}
17755
 
        } else {
17756
 
            s.push('{');
17757
 
            for (i in o) {
17758
 
                if (o.hasOwnProperty(i)) {
17759
 
                    try {
17760
 
                        s.push(i + ARROW);
17761
 
                        if (L.isObject(o[i])) {
17762
 
                            s.push((d > 0) ? L.dump(o[i], d - 1) : OBJ);
17763
 
                        } else {
17764
 
                            s.push(o[i]);
17765
 
                        }
17766
 
                        s.push(COMMA);
17767
 
                    } catch (e) {
17768
 
                        s.push('Error: ' + e.message);
17769
 
                    }
17770
 
                }
17771
 
            }
17772
 
            if (s.length > 1) {
17773
 
                s.pop();
17774
 
            }
17775
 
            s.push('}');
17776
 
        }
17777
 
 
17778
 
        return s.join('');
17779
 
    };
17780
 
 
17781
 
    Y.dump = dump;
17782
 
    L.dump = dump;
17783
 
 
17784
 
 
17785
 
 
17786
 
}, '3.4.1' );
17787
 
YUI.add('transition-timer', function(Y) {
17788
 
 
17789
 
/*
17790
 
* The Transition Utility provides an API for creating advanced transitions.
17791
 
* @module transition
17792
 
*/
17793
 
 
17794
 
/*
17795
 
* Provides the base Transition class, for animating numeric properties.
17796
 
*
17797
 
* @module transition
17798
 
* @submodule transition-timer
17799
 
*/
17800
 
 
17801
 
 
17802
 
var Transition = Y.Transition;
17803
 
 
17804
 
Y.mix(Transition.prototype, {
17805
 
    _start: function() {
17806
 
        if (Transition.useNative) {
17807
 
            this._runNative();
17808
 
        } else {
17809
 
            this._runTimer();
17810
 
        }
17811
 
    },
17812
 
 
17813
 
    _runTimer: function() {
17814
 
        var anim = this;
17815
 
        anim._initAttrs();
17816
 
 
17817
 
        Transition._running[Y.stamp(anim)] = anim;
17818
 
        anim._startTime = new Date();
17819
 
        Transition._startTimer();
17820
 
    },
17821
 
 
17822
 
    _endTimer: function() {
17823
 
        var anim = this;
17824
 
        delete Transition._running[Y.stamp(anim)];
17825
 
        anim._startTime = null;
17826
 
    },
17827
 
 
17828
 
    _runFrame: function() {
17829
 
        var t = new Date() - this._startTime;
17830
 
        this._runAttrs(t);
17831
 
    },
17832
 
 
17833
 
    _runAttrs: function(time) {
17834
 
        var anim = this,
17835
 
            node = anim._node,
17836
 
            config = anim._config,
17837
 
            uid = Y.stamp(node),
17838
 
            attrs = Transition._nodeAttrs[uid],
17839
 
            customAttr = Transition.behaviors,
17840
 
            done = false,
17841
 
            allDone = false,
17842
 
            data,
17843
 
            name,
17844
 
            attribute,
17845
 
            setter,
17846
 
            elapsed,
17847
 
            delay,
17848
 
            d,
17849
 
            t,
17850
 
            i;
17851
 
 
17852
 
        for (name in attrs) {
17853
 
            if ((attribute = attrs[name]) && attribute.transition === anim) {
17854
 
                d = attribute.duration;
17855
 
                delay = attribute.delay;
17856
 
                elapsed = (time - delay) / 1000;
17857
 
                t = time;
17858
 
                data = {
17859
 
                    type: 'propertyEnd',
17860
 
                    propertyName: name,
17861
 
                    config: config,
17862
 
                    elapsedTime: elapsed
17863
 
                };
17864
 
 
17865
 
                setter = (i in customAttr && 'set' in customAttr[i]) ?
17866
 
                        customAttr[i].set : Transition.DEFAULT_SETTER;
17867
 
 
17868
 
                done = (t >= d);
17869
 
 
17870
 
                if (t > d) {
17871
 
                    t = d;
17872
 
                }
17873
 
 
17874
 
                if (!delay || time >= delay) {
17875
 
                    setter(anim, name, attribute.from, attribute.to, t - delay, d - delay,
17876
 
                        attribute.easing, attribute.unit); 
17877
 
 
17878
 
                    if (done) {
17879
 
                        delete attrs[name];
17880
 
                        anim._count--;
17881
 
 
17882
 
                        if (config[name] && config[name].on && config[name].on.end) {
17883
 
                            config[name].on.end.call(Y.one(node), data);
17884
 
                        }
17885
 
 
17886
 
                        //node.fire('transition:propertyEnd', data);
17887
 
 
17888
 
                        if (!allDone && anim._count <= 0) {
17889
 
                            allDone = true;
17890
 
                            anim._end(elapsed);
17891
 
                            anim._endTimer();
17892
 
                        }
17893
 
                    }
17894
 
                }
17895
 
 
17896
 
            }
17897
 
        }
17898
 
    },
17899
 
 
17900
 
    _initAttrs: function() {
17901
 
        var anim = this,
17902
 
            customAttr = Transition.behaviors,
17903
 
            uid = Y.stamp(anim._node),
17904
 
            attrs = Transition._nodeAttrs[uid],
17905
 
            attribute,
17906
 
            duration,
17907
 
            delay,
17908
 
            easing,
17909
 
            val,
17910
 
            name,
17911
 
            mTo,
17912
 
            mFrom,
17913
 
            unit, begin, end;
17914
 
 
17915
 
        for (name in attrs) {
17916
 
            if ((attribute = attrs[name]) && attribute.transition === anim) {
17917
 
                duration = attribute.duration * 1000;
17918
 
                delay = attribute.delay * 1000;
17919
 
                easing = attribute.easing;
17920
 
                val = attribute.value;
17921
 
 
17922
 
                // only allow supported properties
17923
 
                if (name in anim._node.style || name in Y.DOM.CUSTOM_STYLES) {
17924
 
                    begin = (name in customAttr && 'get' in customAttr[name])  ?
17925
 
                            customAttr[name].get(anim, name) : Transition.DEFAULT_GETTER(anim, name);
17926
 
 
17927
 
                    mFrom = Transition.RE_UNITS.exec(begin);
17928
 
                    mTo = Transition.RE_UNITS.exec(val);
17929
 
 
17930
 
                    begin = mFrom ? mFrom[1] : begin;
17931
 
                    end = mTo ? mTo[1] : val;
17932
 
                    unit = mTo ? mTo[2] : mFrom ?  mFrom[2] : ''; // one might be zero TODO: mixed units
17933
 
 
17934
 
                    if (!unit && Transition.RE_DEFAULT_UNIT.test(name)) {
17935
 
                        unit = Transition.DEFAULT_UNIT;
17936
 
                    }
17937
 
 
17938
 
                    if (typeof easing === 'string') {
17939
 
                        if (easing.indexOf('cubic-bezier') > -1) {
17940
 
                            easing = easing.substring(13, easing.length - 1).split(',');
17941
 
                        } else if (Transition.easings[easing]) {
17942
 
                            easing = Transition.easings[easing];
17943
 
                        }
17944
 
                    }
17945
 
 
17946
 
                    attribute.from = Number(begin);
17947
 
                    attribute.to = Number(end);
17948
 
                    attribute.unit = unit;
17949
 
                    attribute.easing = easing;
17950
 
                    attribute.duration = duration + delay;
17951
 
                    attribute.delay = delay;
17952
 
                } else {
17953
 
                    delete attrs[name];
17954
 
                    anim._count--;
17955
 
                }
17956
 
            }
17957
 
        }
17958
 
    },
17959
 
 
17960
 
    destroy: function() {
17961
 
        this.detachAll();
17962
 
        this._node = null;
17963
 
    }
17964
 
}, true);
17965
 
 
17966
 
Y.mix(Y.Transition, {
17967
 
    _runtimeAttrs: {},
17968
 
    /*
17969
 
     * Regex of properties that should use the default unit.
17970
 
     *
17971
 
     * @property RE_DEFAULT_UNIT
17972
 
     * @static
17973
 
     */
17974
 
    RE_DEFAULT_UNIT: /^width|height|top|right|bottom|left|margin.*|padding.*|border.*$/i,
17975
 
 
17976
 
    /*
17977
 
     * The default unit to use with properties that pass the RE_DEFAULT_UNIT test.
17978
 
     *
17979
 
     * @property DEFAULT_UNIT
17980
 
     * @static
17981
 
     */
17982
 
    DEFAULT_UNIT: 'px',
17983
 
 
17984
 
    /*
17985
 
     * Time in milliseconds passed to setInterval for frame processing 
17986
 
     *
17987
 
     * @property intervalTime
17988
 
     * @default 20
17989
 
     * @static
17990
 
     */
17991
 
    intervalTime: 20,
17992
 
 
17993
 
    /*
17994
 
     * Bucket for custom getters and setters
17995
 
     *
17996
 
     * @property behaviors
17997
 
     * @static
17998
 
     */
17999
 
    behaviors: {
18000
 
        left: {
18001
 
            get: function(anim, attr) {
18002
 
                return Y.DOM._getAttrOffset(anim._node, attr);
18003
 
            }
18004
 
        }
18005
 
    },
18006
 
 
18007
 
    /*
18008
 
     * The default setter to use when setting object properties.
18009
 
     *
18010
 
     * @property DEFAULT_SETTER
18011
 
     * @static
18012
 
     */
18013
 
    DEFAULT_SETTER: function(anim, att, from, to, elapsed, duration, fn, unit) {
18014
 
        from = Number(from);
18015
 
        to = Number(to);
18016
 
 
18017
 
        var node = anim._node,
18018
 
            val = Transition.cubicBezier(fn, elapsed / duration);
18019
 
 
18020
 
        val = from + val[0] * (to - from);
18021
 
 
18022
 
        if (node) {
18023
 
            if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
18024
 
                unit = unit || '';
18025
 
                Y.DOM.setStyle(node, att, val + unit);
18026
 
            }
18027
 
        } else {
18028
 
            anim._end();
18029
 
        }
18030
 
    },
18031
 
 
18032
 
    /*
18033
 
     * The default getter to use when getting object properties.
18034
 
     *
18035
 
     * @property DEFAULT_GETTER
18036
 
     * @static
18037
 
     */
18038
 
    DEFAULT_GETTER: function(anim, att) {
18039
 
        var node = anim._node,
18040
 
            val = '';
18041
 
 
18042
 
        if (att in node.style || att in Y.DOM.CUSTOM_STYLES) {
18043
 
            val = Y.DOM.getComputedStyle(node, att);
18044
 
        }
18045
 
 
18046
 
        return val;
18047
 
    },
18048
 
 
18049
 
    _startTimer: function() {
18050
 
        if (!Transition._timer) {
18051
 
            Transition._timer = setInterval(Transition._runFrame, Transition.intervalTime);
18052
 
        }
18053
 
    },
18054
 
 
18055
 
    _stopTimer: function() {
18056
 
        clearInterval(Transition._timer);
18057
 
        Transition._timer = null;
18058
 
    },
18059
 
 
18060
 
    /*
18061
 
     * Called per Interval to handle each animation frame.
18062
 
     * @method _runFrame
18063
 
     * @private
18064
 
     * @static
18065
 
     */    
18066
 
    _runFrame: function() {
18067
 
        var done = true,
18068
 
            anim;
18069
 
        for (anim in Transition._running) {
18070
 
            if (Transition._running[anim]._runFrame) {
18071
 
                done = false;
18072
 
                Transition._running[anim]._runFrame();
18073
 
            }
18074
 
        }
18075
 
 
18076
 
        if (done) {
18077
 
            Transition._stopTimer();
18078
 
        }
18079
 
    },
18080
 
 
18081
 
    cubicBezier: function(p, t) {
18082
 
        var x0 = 0,
18083
 
            y0 = 0,
18084
 
            x1 = p[0],
18085
 
            y1 = p[1],
18086
 
            x2 = p[2],
18087
 
            y2 = p[3],
18088
 
            x3 = 1,
18089
 
            y3 = 0,
18090
 
 
18091
 
            A = x3 - 3 * x2 + 3 * x1 - x0,
18092
 
            B = 3 * x2 - 6 * x1 + 3 * x0,
18093
 
            C = 3 * x1 - 3 * x0,
18094
 
            D = x0,
18095
 
            E = y3 - 3 * y2 + 3 * y1 - y0,
18096
 
            F = 3 * y2 - 6 * y1 + 3 * y0,
18097
 
            G = 3 * y1 - 3 * y0,
18098
 
            H = y0,
18099
 
 
18100
 
            x = (((A*t) + B)*t + C)*t + D,
18101
 
            y = (((E*t) + F)*t + G)*t + H;
18102
 
 
18103
 
        return [x, y];
18104
 
    },
18105
 
 
18106
 
    easings: {
18107
 
        ease: [0.25, 0, 1, 0.25],
18108
 
        linear: [0, 0, 1, 1],
18109
 
        'ease-in': [0.42, 0, 1, 1],
18110
 
        'ease-out': [0, 0, 0.58, 1],
18111
 
        'ease-in-out': [0.42, 0, 0.58, 1]
18112
 
    },
18113
 
 
18114
 
    _running: {},
18115
 
    _timer: null,
18116
 
 
18117
 
    RE_UNITS: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/
18118
 
}, true); 
18119
 
 
18120
 
Transition.behaviors.top = Transition.behaviors.bottom = Transition.behaviors.right = Transition.behaviors.left;
18121
 
 
18122
 
Y.Transition = Transition;
18123
 
 
18124
 
 
18125
 
}, '3.4.1' ,{requires:['transition']});
18126
 
YUI.add('simpleyui', function(Y) {
18127
 
 
18128
 
// empty
18129
 
 
18130
 
 
18131
 
 
18132
 
}, '3.4.1' ,{use:['yui','oop','dom','event-custom-base','event-base','pluginhost','node','event-delegate','io-base','json-parse','transition','selector-css3','dom-style-ie','querystring-stringify-simple']});
18133
 
var Y = YUI().use('*');