PageSourceSearch

https://marketplaceportal.com/combo?browserId=other&minifierType=j…/aui/widget-skin/widget-skin.js

js marketplaceportal.com collected 2026-10-09 16:57:40 UTC 402,019 bytes, 12,816 lines download raw bytes

1YUI.add('event-key', function (Y, NAME) {
2
3/**
4 * Functionality to listen for one or more specific key combinations.
5 * @module event
6 * @submodule event-key
7 */
8
9var ALT      = "+alt",
10    CTRL     = "+ctrl",
11    META     = "+meta",
12    SHIFT    = "+shift",
13
14    trim     = Y.Lang.trim,
15
16    eventDef = {
17        KEY_MAP: {
18            enter    : 13,
19            space    : 32,
20            esc      : 27,
21            backspace: 8,
22            tab      : 9,
23            pageup   : 33,
24            pagedown : 34
25        },
26
27        _typeRE: /^(up|down|press):/,
28        _keysRE: /^(?:up|down|press):|\+(alt|ctrl|meta|shift)/g,
29
30        processArgs: function (args) {
31            var spec = args.splice(3,1)[0],
32                mods = Y.Array.hash(spec.match(/\+(?:alt|ctrl|meta|shift)\b/g) || []),
33                config = {
34                    type: this._typeRE.test(spec) ? RegExp.$1 : null,
35                    mods: mods,
36                    keys: null
37                },
38                // strip type and modifiers from spec, leaving only keyCodes
39                bits = spec.replace(this._keysRE, ''),
40                chr, uc, lc, i;
41
42            if (bits) {
43                bits = bits.split(',');
44
45                config.keys = {};
46
47                // FIXME: need to support '65,esc' => keypress, keydown
48                for (i = bits.length - 1; i >= 0; --i) {
49                    chr = trim(bits[i]);
50
51                    // catch sloppy filters, trailing commas, etc 'a,,'
52                    if (!chr) {
53                        continue;
54                    }
55
56                    // non-numerics are single characters or key names
57                    if (+chr == chr) {
58                        config.keys[chr] = mods;
59                    } else {
60                        lc = chr.toLowerCase();
61
62                        if (this.KEY_MAP[lc]) {
63                            config.keys[this.KEY_MAP[lc]] = mods;
64                            // FIXME: '65,enter' defaults keydown for both
65                            if (!config.type) {
66                                config.type = "down"; // safest
67                            }
68                        } else {
69                            // FIXME: Character mapping only works for keypress
70                            // events. Otherwise, it uses String.fromCharCode()
71                            // from the keyCode, which is wrong.
72                            chr = chr.charAt(0);
73                            uc  = chr.toUpperCase();
74
75                            if (mods["+shift"]) {
76                                chr = uc;
77                            }
78
79                            // FIXME: stupid assumption that
80                            // the keycode of the lower case == the
81                            // charCode of the upper case
82                            // a (key:65,char:97), A (key:65,char:65)
83                            config.keys[chr.charCodeAt(0)] =
84                                (chr === uc) ?
85                                    // upper case chars get +shift free
86                                    Y.merge(mods, { "+shift": true }) :
87                                    mods;
88                        }
89                    }
90                }
91            }
92
93            if (!config.type) {
94                config.type = "press";
95            }
96
97            return config;
98        },
99
100        on: function (node, sub, notifier, filter) {
101            var spec   = sub._extra,
102                type   = "key" + spec.type,
103                keys   = spec.keys,
104                method = (filter) ? "delegate" : "on";
105
106            // Note: without specifying any keyCodes, this becomes a
107            // horribly inefficient alias for 'keydown' (et al), but I
108            // can't abort this subscription for a simple
109            // Y.on('keypress', ...);
110            // Please use keyCodes or just subscribe directly to keydown,
111            // keyup, or keypress
112            sub._detach = node[method](type, function (e) {
113                var key = keys ? keys[e.which] : spec.mods;
114
115                if (key &&
116                    (!key[ALT]   || (key[ALT]   && e.altKey)) &&
117                    (!key[CTRL]  || (key[CTRL]  && e.ctrlKey)) &&
118                    (!key[META]  || (key[META]  && e.metaKey)) &&
119                    (!key[SHIFT] || (key[SHIFT] && e.shiftKey)))
120                {
121                    notifier.fire(e);
122                }
123            }, filter);
124        },
125
126        detach: function (node, sub, notifier) {
127            sub._detach.detach();
128        }
129    };
130
131eventDef.delegate = eventDef.on;
132eventDef.detachDelegate = eventDef.detach;
133
134/**
135 * <p>Add a key listener.  The listener will only be notified if the
136 * keystroke detected meets the supplied specification.  The
137 * specification is a string that is defined as:</p>
138 *
139 * <dl>
140 *   <dt>spec</dt>
141 *   <dd><code>[{type}:]{code}[,{code}]*</code></dd>
142 *   <dt>type</dt>
143 *   <dd><code>"down", "up", or "press"</code></dd>
144 *   <dt>code</dt>
145 *   <dd><code>{keyCode|character|keyName}[+{modifier}]*</code></dd>
146 *   <dt>modifier</dt>
147 *   <dd><code>"shift", "ctrl", "alt", or "meta"</code></dd>
148 *   <dt>keyName</dt>
149 *   <dd><code>"enter", "space", "backspace", "esc", "tab", "pageup", or "pagedown"</code></dd>
150 * </dl>
151 *
152 * <p>Examples:</p>
153 * <ul>
154 *   <li><code>Y.on("key", callback, "press:12,65+shift+ctrl", "#my-input");</code></li>
155 *   <li><code>Y.delegate("key", preventSubmit, "#forms", "enter", "input[type=text]");</code></li>
156 *   <li><code>Y.one("doc").on("key", viNav, "j,k,l,;");</code></li>
157 * </ul>
158 *
159 * @event key
160 * @for YUI
161 * @param type {string} 'key'
162 * @param fn {function} the function to execute
163 * @param id {string|HTMLElement|collection}
163 the element(s) to bind
164 * @param spec {string} the keyCode and modifier specification
165 * @param o optional context object
166 * @param args 0..n additional arguments to provide to the listener.
167 * @return {Event.Handle} the detach handle
168 */
169Y.Event.define('key', eventDef, true);
170
171
172}, 'patched-v3.18.3', {"requires": ["event-synthetic"]});
173
174YUI.add('event-mouseenter', function (Y, NAME) {
175
176/**
177 * <p>Adds subscription and delegation support for mouseenter and mouseleave
178 * events.  Unlike mouseover and mouseout, these events aren't fired from child
179 * elements of a subscribed node.</p>
180 *
181 * <p>This avoids receiving three mouseover notifications from a setup like</p>
182 *
183 * <pre><code>div#container > p > a[href]</code></pre>
184 *
185 * <p>where</p>
186 *
187 * <pre><code>Y.one('#container').on('mouseover', callback)</code></pre>
188 *
189 * <p>When the mouse moves over the link, one mouseover event is fired from
190 * #container, then when the mouse moves over the p, another mouseover event is
191 * fired and bubbles to #container, causing a second notification, and finally
192 * when the mouse moves over the link, a third mouseover event is fired and
193 * bubbles to #container for a third notification.</p>
194 *
195 * <p>By contrast, using mouseenter instead of mouseover, the callback would be
196 * executed only once when the mouse moves over #container.</p>
197 *
198 * @module event
199 * @submodule event-mouseenter
200 */
201
202var domEventProxies = Y.Env.evt.dom_wrappers,
203    contains = Y.DOM.contains,
204    toArray = Y.Array,
205    noop = function () {},
206
207    config = {
208        proxyType: "mouseover",
209        relProperty: "fromElement",
210
211        _notify: function (e, property, notifier) {
212            var el = this._node,
213                related = e.relatedTarget || e[property];
214
215            if (el !== related && !contains(el, related)) {
216                notifier.fire(new Y.DOMEventFacade(e, el,
217                    domEventProxies['event:' + Y.stamp(el) + e.type]));
218            }
219        },
220
221        on: function (node, sub, notifier) {
222            var el = Y.Node.getDOMNode(node),
223                args = [
224                    this.proxyType,
225                    this._notify,
226                    el,
227                    null,
228                    this.relProperty,
229                    notifier];
230
231            sub.handle = Y.Event._attach(args, { facade: false });
232            // node.on(this.proxyType, notify, null, notifier);
233        },
234
235        detach: function (node, sub) {
236            sub.handle.detach();
237        },
238
239        delegate: function (node, sub, notifier, filter) {
240            var el = Y.Node.getDOMNode(node),
241                args = [
242                    this.proxyType,
243                    noop,
244                    el,
245                    null,
246                    notifier
247                ];
248
249            sub.handle = Y.Event._attach(args, { facade: false });
250            sub.handle.sub.filter = filter;
251            sub.handle.sub.relProperty = this.relProperty;
252            sub.handle.sub._notify = this._filterNotify;
253        },
254
255        _filterNotify: function (thisObj, args, ce) {
256            args = args.slice();
257            if (this.args) {
258                args.push.apply(args, this.args);
259            }
260
261            var currentTarget = Y.delegate._applyFilter(this.filter, args, ce),
262                related = args[0].relatedTarget || args[0][this.relProperty],
263                e, i, len, ret, ct;
264
265            if (currentTarget) {
266                currentTarget = toArray(currentTarget);
267
268                for (i = 0, len = currentTarget.length && (!e || !e.stopped); i < len; ++i) {
269                    ct = currentTarget[0];
270                    if (!contains(ct, related)) {
271                        if (!e) {
272                            e = new Y.DOMEventFacade(args[0], ct, ce);
273                            e.container = Y.one(ce.el);
274                        }
275                        e.currentTarget = Y.one(ct);
276
277                        // TODO: where is notifier? args? this.notifier?
278                        ret = args[1].fire(e);
279
280                        if (ret === false) {
281                            break;
282                        }
283                    }
284                }
285            }
286
287            return ret;
288        },
289
290        detachDelegate: function (node, sub) {
291            sub.handle.detach();
292        }
293    };
294
295Y.Event.define("mouseenter", config, true);
296Y.Event.define("mouseleave", Y.merge(config, {
297    proxyType: "mouseout",
298    relProperty: "toElement"
299}), true);
300
301
302}, 'patched-v3.18.3', {"requires": ["event-synthetic"]});
303
304YUI.add('event-mousewheel', function (Y, NAME) {
305
306/**
307 * Adds mousewheel event support
308 * @module event
309 * @submodule event-mousewheel
310 */
311var DOM_MOUSE_SCROLL = 'DOMMouseScroll',
312    fixArgs = function(args) {
313        var a = Y.Array(args, 0, true), target;
314        if (Y.UA.gecko) {
315            a[0] = DOM_MOUSE_SCROLL;
316            target = Y.config.win;
317        } else {
318            target = Y.config.doc;
319        }
320
321        if (a.length < 3) {
322            a[2] = target;
323        } else {
324            a.splice(2, 0, target);
325        }
326
327        return a;
328    };
329
330/**
331 * Mousewheel event.  This listener is automatically attached to the
332 * correct target, so one should not be supplied.  Mouse wheel
333 * direction and velocity is stored in the 'wheelDelta' field.
334 * @event mousewheel
335 * @param type {string} 'mousewheel'
336 * @param fn {function} the callback to execute
337 * @param context optional context object
338 * @param args 0..n additional arguments to provide to the listener.
339 * @return {EventHandle} the detach handle
340 * @for YUI
341 */
342Y.Env.evt.plugins.mousewheel = {
343    on: function() {
344        return Y.Event._attach(fixArgs(arguments));
345    },
346
347    detach: function() {
348        return Y.Event.detach.apply(Y.Event, fixArgs(arguments));
349    }
350};
351
352
353}, 'patched-v3.18.3', {"requires": ["node-base"]});
354
355YUI.add('event-outside', function (Y, NAME) {
356
357/**
358 * Outside events are synthetic DOM events that fire when a corresponding native
359 * or synthetic DOM event occurs outside a bound element.
360 *
361 * The following outside events are pre-defined by this module:
362 * <ul>
363 *   <li>blur</li>
364 *   <li>change</li>
365 *   <li>click</li>
366 *   <li>dblclick</li>
367 *   <li>focus</li>
368 *   <li>keydown</li>
369 *   <li>keypress</li>
370 *   <li>keyup</li>
371 *   <li>mousedown</li>
372 *   <li>mousemove</li>
373 *   <li>mouseout</li>
374 *   <li>mouseover</li>
375 *   <li>mouseup</li>
376 *   <li>select</li>
377 *   <li>submit</li>
378 * </ul>
379 *
380 * Define new outside events with
381 * <code>Y.Event.defineOutside(eventType);</code>.
382 * By default, the created synthetic event name will be the name of the event
383 * with "outside" appended (e.g. "click" becomes "clickoutside"). If you want
384 * a different name for the created Event, pass it as a second argument like so:
385 * <code>Y.Event.defineOutside(eventType, "yonderclick")</code>.
386 *
387 * This module was contributed by Brett Stimmerman, promoted from his
388 * gallery-outside-events module at
389 * http://yuilibrary.com/gallery/show/outside-events
390 *
391 * @module event
392 * @submodule event-outside
393 * @author brettstimmerman
394 * @since 3.4.0
395 */
396
397// Outside events are pre-defined for each of these native DOM events
398var nativeEvents = [
399        'blur', 'change', 'click', 'dblclick', 'focus', 'keydown', 'ke
399ypress',
400        'keyup', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup',
401        'select', 'submit'
402    ];
403
404/**
405 * Defines a new outside event to correspond with the given DOM event.
406 *
407 * By default, the created synthetic event name will be the name of the event
408 * with "outside" appended (e.g. "click" becomes "clickoutside"). If you want
409 * a different name for the created Event, pass it as a second argument like so:
410 * <code>Y.Event.defineOutside(eventType, "yonderclick")</code>.
411 *
412 * @method defineOutside
413 * @param {String} event DOM event
414 * @param {String} name (optional) custom outside event name
415 * @static
416 * @for Event
417 */
418Y.Event.defineOutside = function (event, name) {
419    name = name || (event + 'outside');
420
421    var config = {
422
423        on: function (node, sub, notifier) {
424            sub.handle = Y.one('doc').on(event, function(e) {
425                if (this.isOutside(node, e.target)) {
426                    e.currentTarget = node;
427                    notifier.fire(e);
428                }
429            }, this);
430        },
431
432        detach: function (node, sub, notifier) {
433            sub.handle.detach();
434        },
435
436        delegate: function (node, sub, notifier, filter) {
437            sub.handle = Y.one('doc').delegate(event, function (e) {
438                if (this.isOutside(node, e.target)) {
439                    notifier.fire(e);
440                }
441            }, filter, this);
442        },
443
444        isOutside: function (node, target) {
445            return target !== node && !target.ancestor(function (p) {
446                    return p === node;
447                });
448        }
449    };
450    config.detachDelegate = config.detach;
451
452    Y.Event.define(name, config);
453};
454
455// Define outside events for some common native DOM events
456Y.Array.each(nativeEvents, function (event) {
457    Y.Event.defineOutside(event);
458});
459
460
461}, 'patched-v3.18.3', {"requires": ["event-synthetic"]});
462
463YUI.add('event-resize', function (Y, NAME) {
464
465/**
466 * Adds a window resize event that has its behavior normalized to fire at the
467 * end of the resize rather than constantly during the resize.
468 * @module event
469 * @submodule event-resize
470 */
471
472
473/**
474 * Old firefox fires the window resize event once when the resize action
475 * finishes, other browsers fire the event periodically during the
476 * resize.  This code uses timeout logic to simulate the Firefox
477 * behavior in other browsers.
478 * @event windowresize
479 * @for YUI
480 */
481Y.Event.define('windowresize', {
482
483    on: (Y.UA.gecko && Y.UA.gecko < 1.91) ?
484        function (node, sub, notifier) {
485            sub._handle = Y.Event.attach('resize', function (e) {
486                notifier.fire(e);
487            });
488        } :
489        function (node, sub, notifier) {
490            // interval bumped from 40 to 100ms as of 3.4.1
491            var delay = Y.config.windowResizeDelay || 100;
492
493            sub._handle = Y.Event.attach('resize', function (e) {
494                if (sub._timer) {
495                    sub._timer.cancel();
496                }
497
498                sub._timer = Y.later(delay, Y, function () {
499                    notifier.fire(e);
500                });
501            });
502        },
503
504    detach: function (node, sub) {
505        if (sub._timer) {
506            sub._timer.cancel();
507        }
508        sub._handle.detach();
509    }
510    // delegate methods not defined because this only works for window
511    // subscriptions, so...yeah.
512});
513
514
515}, 'patched-v3.18.3', {"requires": ["node-base", "event-synthetic"]});
516
517YUI.add('event-simulate', function (Y, NAME) {
518
519(function() {
520/**
521 * Simulate user interaction by generating native DOM events.
522 *
523 * @module event-simulate
524 * @requires event
525 */
526
527//shortcuts
528var L   = Y.Lang,
529    win = Y.config.win,
530    isFunction  = L.isFunction,
531    isString    = L.isString,
532    isBoolean   = L.isBoolean,
533    isObject    = L.isObject,
534    isNumber    = L.isNumber,
535
536    //mouse events supported
537    mouseEvents = {
538        click:      1,
539        dblclick:   1,
540        mouseover:  1,
541        mouseout:   1,
542        mousedown:  1,
543        mouseup:    1,
544        mousemove:  1,
545        contextmenu:1
546    },
547
548    pointerEvents = (win && win.PointerEvent) ? {
549        pointerover:  1,
550        pointerout:   1,
551        pointerdown:  1,
552        pointerup:    1,
553        pointermove:  1
554    } : {
555        MSPointerOver:  1,
556        MSPointerOut:   1,
557        MSPointerDown:  1,
558        MSPointerUp:    1,
559        MSPointerMove:  1
560    },
561
562    //key events supported
563    keyEvents   = {
564        keydown:    1,
565        keyup:      1,
566        keypress:   1
567    },
568
569    //HTML events supported
570    uiEvents  = {
571        submit:     1,
572        blur:       1,
573        change:     1,
574        focus:      1,
575        resize:     1,
576        scroll:     1,
577        select:     1
578    },
579
580    //events that bubble by default
581    bubbleEvents = {
582        scroll:     1,
583        resize:     1,
584        reset:      1,
585        submit:     1,
586        change:     1,
587        select:     1,
588        error:      1,
589        abort:      1
590    },
591
592    //touch events supported
593    touchEvents = {
594        touchstart: 1,
595        touchmove: 1,
596        touchend: 1,
597        touchcancel: 1
598    },
599
600    gestureEvents = {
601        gesturestart: 1,
602        gesturechange: 1,
603        gestureend: 1
604    };
605
606//all key, mouse and touch events bubble
607Y.mix(bubbleEvents, mouseEvents);
608Y.mix(bubbleEvents, keyEvents);
609Y.mix(bubbleEvents, touchEvents);
610
611/*
612 * Note: Intentionally not for YUIDoc generation.
613 * Simulates a key event using the given event information to populate
614 * the generated event object. This method does browser-equalizing
615 * calculations to account for differences in the DOM and IE event models
616 * as well as different browser quirks. Note: keydown causes Safari 2.x to
617 * crash.
618 * @method simulateKeyEvent
619 * @private
620 * @static
621 * @param {HTMLElement} target The target of the given event.
622 * @param {String} type The type of event to fire. This can be any one of
623 *      the following: keyup, keydown, and keypress.
624 * @param {Boolean} [bubbles=true] Indicates if the event can be
625 *      bubbled up. DOM Level 3 specifies that all key events bubble by
626 *      default.
627 * @param {Boolean} [cancelable=true] Indicates if the event can be
628 *      canceled using preventDefault(). DOM Level 3 specifies that all
629 *      key events can be cancelled.
630 * @param {Window} [view=window] The view containing the target. This is
631 *      typically the window object.
632 * @param {Boolean} [ctrlKey=false] Indicates if one of the CTRL keys
633 *      is pressed while the event is firing.
634 * @param {Boolean} [altKey=false] Indicates if one of the ALT keys
635 *      is pressed while the event is firing.
636 * @param {Boolean} [shiftKey=false] Indicates if one of the SHIFT keys
637 *      is pressed while the event is firing.
638 * @param {Boolean} [metaKey=false] Indicates if one of the META keys
639 *      is pressed while the event is firing.
640 * @param {Number} [keyCode=0] The code for the key that is in use.
641 * @param {Number} [charCode=0] The Unicode code for the character
642 *      associated with the key being used.
643 */
644function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/,
645                             bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
646                             view /*:Window*/,
647                             ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,
648                             shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,
649                             keyCode /*:int*/,        charCode /*:int*/) /*:Void*/
650{
651    //check target
652    if (!target){
653        Y.error("simulateKeyEvent(): Invalid target.");
654    }
655
656    //check event type
657    if (isString(type)){
658        type = type.toLowerCase();
659        switch(type){
660            case "textevent": //DOM Level 3
661                type = "keypress";
662                break;
663            case "keyup":
664            case "keydown":
665            case "keypress":
666                break;
667            default:
668                Y.error("simulateKeyEvent(): Event type '" + type + "' not supported.");
669        }
670    } else {
671        Y.error("simulateKeyEvent(): Event type must be a string.");
672    }
673
674    //setup default values
675    if (!isBoolean(bubbles)){
676        bubbles = true; //all key events bubble
677    }
678    if (!isBoolean(cancelable)){
679        cancelable = true; //all key events can be cancelled
680    }
681    if (!isObject(view)){
682        view = Y.config.win; //view is typically window
683    }
684    if (!isBoolean(ctrlKey)){
685        ctrlKey = false;
686    }
687    if (!isBoolean(altKey)){
688        altKey = false;
689    }
690    if (!isBoolean(shiftKey)){
691        shiftKey = false;
692    }
693    if (!isBoolean(metaKey)){
694        metaKey = false;
695    }
696    if (!isNumber(keyCode)){
697        keyCode = 0;
698    }
699    if (!isNumber(charCode)){
700        charCode = 0;
701    }
702
703    //try to create a mouse event
704    var customEvent /*:MouseEvent*/ = null;
705
706    //check for DOM-compliant browsers first
707    if (isFunction(Y.config.doc.createEvent)){
708
709        try {
710
711            //try to create key event
712            customEvent = Y.config.doc.createEvent("KeyEvents");
713
714            /*
715             * Interesting problem: Firefox implemented a non-standard
716             * version of initKeyEvent() based on DOM Level 2 specs.
717             * Key event was removed from DOM Level 2 and re-introduced
718             * in DOM Level 3 with a different interface. Firefox is the
719             * only browser with any implementation of Key Events, so for
720             * now, assume it's Firefox if the above line doesn't error.
721             */
722            // @TODO: Decipher between Firefox's implementation and a correct one.
723            customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,
724                altKey, shiftKey, metaKey, keyCode, charCode);
725
726        } catch (ex /*:Error*/){
727
728            /*
729             * If it got here, that means key events aren't officially supported.
730             * Safari/WebKit is a real problem now. WebKit 522 won't let you
731             * set keyCode, charCode, or other properties if you use a
732             * UIEvent, so we first must try to create a generic event. The
733             * fun part is that this will throw an error on Safari 2.x. The
734             * end result is that we need another try...catch statement just to
735             * deal with this mess.
736             */
737            try {
738
739                //try to create generic event - will fail in Safari 2.x
740                customEvent = Y.config.doc.createEvent("Events");
741
742            } catch (uierror /*:Error*/){
743
744                //the above failed, so create a UIEvent for Safari 2.x
745                customEvent = Y.config.doc.createEvent("UIEvents");
746
747            } finally {
748
749                customEvent.initEvent(type, bubbles, cancelable);
750
751                //initialize
752                customEvent.view = view;
753                customEvent.altKey = altKey;
754                customEvent.ctrlKey = ctrlKey;
755                customEvent.shiftKey = shiftKey;
756                customEvent.metaKey = metaKey;
757                customEvent.keyCode = keyCode;
758                customEvent.charCode = charCode;
759
760            }
761
762        }
763
764        //fire the event
765        target.dispatchEvent(customEvent);
766
767    } else if (isObject(Y.config.doc.createEventObject)){ //IE
768
769        //create an IE event object
770        customEvent = Y.config.doc.createEventObject();
771
772        //assign available properties
773        customEvent.bubbles = bubbles;
774        customEvent.cancelable = cancelable;
775        customEvent.view = view;
776        customEvent.ctrlKey = ctrlKey;
777        customEvent.altKey = altKey;
778        customEvent.shiftKey = shiftKey;
779        customEvent.metaKey = metaKey;
780
781        /*
782         * IE doesn't support charCode explicitly. CharCode should
783         * take precedence over any keyCode value for accurate
784         * representation.
785         */
786        customEvent.keyCode = (charCode > 0) ? charCode : keyCode;
787
788        //fire the event
789        target.fireEvent("on" + type, customEvent);
790
791    } else {
792        Y.error("simulateKeyEvent(): No event simulation framework present.");
793    }
794}
795
796/*
797 * Note: Intentionally not for YUIDoc generation.
798 * Simulates a mouse event using the given event information to populate
799 * the generated event object. This method does browser-equalizing
800 * calculations to account for differences in the DOM and IE event models
801 * as well as different browser quirks.
802 * @method simulateMouseEvent
803 * @private
804 * @static
805 * @param {HTMLElement} target The target of the given event.
806 * @param {String} type The type of event to fire. This can be any one of
807 *      the following: click, dblclick, mousedown, mouseup, mouseout,
808 *      mouseover, and mousemove.
809 * @param {Boolean} bubbles (Optional) Indicates if the event can be
810 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
811 *      default. The default is true.
812 * @param {Boolean} cancelable (Optional) Indicates if the event can be
813 *      canceled using preventDefault(). DOM Level 2 specifies that all
814 *      mouse events except mousemove can be cancelled. The default
815 *      is true for all events except mousemove, for which the default
816 *      is false.
817 * @param {Window} view (Optional) The view containing the target. This is
818 *      typically the window object. The default is window.
819 * @param {Number} detail (Optional) The number of times the mouse button has
820 *      been used. The default value is 1.
821 * @param {Number} screenX (Optional) The x-coordinate on the screen at which
822 *      point the event occured. The default is 0.
823 * @param {Number} screenY (Optional) The y-coordinate on the screen at which
824 *      point the event occured. The default is 0.
825 * @param {Number} clientX (Optional) The x-coordinate on the client at which
826 *      point the event occured. The default is 0.
827 * @param {Number} clientY (Optional) The y-coordinate on the client at which
828 *      point the event occured. The default is 0.
829 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
830 *      is pressed while the event is firing. The default is false.
831 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
832 *      is pressed while the event is firing. The default is false.
833 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
834 *      is pressed while the event is firing. The default is false.
835 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
836 *      is pressed while the event is firing. The default is false.
837 * @param {Number} button (Optional) The button being pressed while the event
838 *      is executing. The value should be 0 for the primary mouse button
839 *      (typically the left button), 1 for the terciary mouse button
840 *      (typically the middle button), and 2 for the secondary mouse button
841 *      (typically the right button). The default is 0.
842 * @param {HTMLElement} relatedTarget (Optional) For mouseout events,
843 *      this is the element that the mouse has moved to. For mouseover
844 *      events, this is the element that the mouse has moved from. This
845 *      argument is ignored for all other events. The default is null.
846 */
847function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/,
848                               bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
849                               view /*:Window*/,        detail /*:int*/,
850                               screenX /*:int*/,        screenY /*:int*/,
851                               clientX /*:int*/,        clientY /*:int*/,
852                               ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,
853                               shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,
854                               button /*:int*/,         relatedTarget /*:HTMLElement*/) /*:Void*/
855{
856    //check target
857    if (!target){
858        Y.error("simulateMouseEvent(): Invalid target.");
859    }
860
861
862    if (isString(type)){
863
864        //make sure it's a supported mouse event or an msPointerEvent.
865        if (!mouseEvents[type.toLowerCase()] && !pointerEvents[type]){
866            Y.error("simulateMouseEvent(): Event type '" + type + "' not supported.");
867        }
868    }
869    else {
870        Y.error("simulateMouseEvent(): Event type must be a string.");
871    }
872
873    //setup default values
874    if (!isBoolean(bubbles)){
875        bubbles = true; //all mouse events bubble
876    }
877    if (!isBoolean(cancelable)){
878        cancelable = (type !== "mousemove"); //mousemove is the only one that can't be cancelled
879    }
880    if (!isObject(view)){
881        view = Y.config.win; //view is typically window
882    }
883    if (!isNumber(detail)){
884        detail = 1;  //number of mouse clicks must be at least one
885    }
886    if (!isNumber(screenX)){
887        screenX = 0;
888    }
889    if (!isNumber(screenY)){
890        screenY = 0;
891    }
892    if (!isNumber(clientX)){
893        clientX = 0;
894    }
895    if (!isNumber(clientY)){
896        clientY = 0;
897    }
898    if (!isBoolean(ctrlKey)){
899        ctrlKey = false;
900    }
901    if (!isBoolean(altKey)){
902        altKey = false;
903    }
904    if (!isBoolean(shiftKey)){
905        shiftKey = false;
906    }
907    if (!isBoolean(metaKey)){
908        metaKey = false;
909    }
910    if (!isNumber(button)){
911        button = 0;
912    }
913
914    relatedTarget = relatedTarget || null;
915
916    //try to create a mouse event
917    var customEvent /*:MouseEvent*/ = null;
918
919    //check for DOM-compliant browsers first
920    if (isFunction(Y.config.doc.createEvent)){
921
922        customEvent = Y.config.doc.createEvent("MouseEvents");
923
924        //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()
925        if (customEvent.initMouseEvent){
926            customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
927                                 screenX, screenY, clientX, clientY,
928                                 ctrlKey, altKey, shiftKey, metaKey,
929                                 button, relatedTarget);
930        } else { //Safari
931
932            //the closest thing available in Safari 2.x is UIEvents
933            customEvent = Y.config.doc.createEvent("UIEvents");
934            customEvent.initEvent(type, bubbles, cancelable);
935            customEvent.view = view;
936            customEvent.detail = detail;
937            customEvent.screenX = screenX;
938            customEvent.screenY = screenY;
939            customEvent.clientX = clientX;
940            customEvent.clientY = clientY;
941            customEvent.ctrlKey = ctrlKey;
942            customEvent.altKey = altKey;
943            customEvent.metaKey = metaKey;
944            customEvent.shiftKey = shiftKey;
945            customEvent.button = button;
946            customEvent.relatedTarget = relatedTarget;
947        }
948
949        /*
950         * Check to see if relatedTarget has been assigned. Firefox
951         * versions less than 2.0 don't allow it to be assigned via
952         * initMouseEvent() and the property is readonly after event
953         * creation, so in order to keep YAHOO.util.getRelatedTarget()
954         * working, assign to the IE proprietary toElement property
955         * for mouseout event and fromElement property for mouseover
956         * event.
957         */
958        if (relatedTarget && !customEvent.relatedTarget){
959            if (type === "mouseout"){
960                customEvent.toElement = relatedTarget;
961            } else if (type === "mouseover"){
962                customEvent.fromElement = relatedTarget;
963            }
964        }
965
966        //fire the event
967        target.dispatchEvent(customEvent);
968
969    } else if (isObject(Y.config.doc.createEventObject)){ //IE
970
971        //create an IE event object
972        customEvent = Y.config.doc.createEventObject();
973
974        //assign available properties
975        customEvent.bubbles = bubbles;
976        customEvent.cancelable = cancelable;
977        customEvent.view = view;
978        customEvent.detail = detail;
979        customEvent.screenX = screenX;
980        customEvent.screenY = screenY;
981        customEvent.clientX = clientX;
982        customEvent.clientY = clientY;
983        customEvent.ctrlKey = ctrlKey;
984        customEvent.altKey = altKey;
985        customEvent.metaKey = metaKey;
986        customEvent.shiftKey = shiftKey;
987
988        //fix button property for IE's wacky implementation
989        switch(button){
990            case 0:
991                customEvent.button = 1;
992                break;
993            case 1:
994                customEvent.button = 4;
995                break;
996            case 2:
997                //leave as is
998                break;
999            default:
1000                customEvent.button = 0;
1001        }
1002
1003        /*
1004         * Have to use relatedTarget because IE won't allow assignment
1005         * to toElement or fromElement on generic events. This keeps
1006         * YAHOO.util.customEvent.getRelatedTarget() functional.
1007         */
1008        customEvent.relatedTarget = relatedTarget;
1009
1010        //fire the event
1011        target.fireEvent("on" + type, customEvent);
1012
1013    } else {
1014        Y.error("simulateMouseEvent(): No event simulation framework present.");
1015    }
1016}
1017
1018/*
1019 * Note: Intentionally not for YUIDoc generation.
1020 * Simulates a UI event using the given event information to populate
1021 * the generated event object. This method does browser-equalizing
1022 * calculations to account for differences in the DOM and IE event models
1023 * as well as different browser quirks.
1024 * @method simulateHTMLEvent
1025 * @private
1026 * @static
1027 * @param {HTMLElement} target The target of the given event.
1028 * @param {String} type The type of event to fire. This can be any one of
1029 *      the following: click, dblclick, mousedown, mouseup, mouseout,
1030 *      mouseover, and mousemove.
1031 * @param {Boolean} bubbles (Optional) Indicates if the event can be
1032 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
1033 *      default. The default is true.
1034 * @param {Boolean} cancelable (Optional) Indicates if the event can be
1035 *      canceled using preventDefault(). DOM Level 2 specifies that all
1036 *      mouse events except mousemove can be cancelled. The default
1037 *      is true for all events except mousemove, for which the default
1038 *      is false.
1039 * @param {Window} view (Optional) The view containing the target. This is
1040 *      typically the window object. The default is window.
1041 * @param {Number} detail (Optional) The number of times the mouse button has
1042 *      been used. The default value is 1.
1043 */
1044function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/,
1045                               bubbles /*:Boolean*/,  cancelable /*:Boolean*/,
1046                               view /*:Window*/,        detail /*:int*/) /*:Void*/
1047{
1048
1049    //check target
1050    if (!target){
1051        Y.error("simulateUIEvent(): Invalid target.");
1052    }
1053
1054    //check event type
1055    if (isString(type)){
1056        type = type.toLowerCase();
1057
1058        //make sure it's a supported mouse event
1059        if (!uiEvents[type]){
1060            Y.error("simulateUIEvent(): Event type '" + type + "' not supported.");
1061        }
1062    } else {
1063        Y.error("simulateUIEvent(): Event type must be a string.");
1064    }
1065
1066    //try to create a mouse event
1067    var customEvent = null;
1068
1069
1070    //setup default values
1071    if (!isBoolean(bubbles)){
1072        bubbles = (type in bubbleEvents);  //not all events bubble
1073    }
1074    if (!isBoolean(cancelable)){
1075        cancelable = (type === "submit"); //submit is the only one that can be cancelled
1076    }
1077    if (!isObject(view)){
1078        view = Y.config.win; //view is typically window
1079    }
1080    if (!isNumber(detail)){
1081        detail = 1;  //usually not used but defaulted to this
1082    }
1083
1084    //check for DOM-compliant browsers first
1085    if (isFunction(Y.config.doc.createEvent)){
1086
1087        //just a generic UI Event object is needed
1088        customEvent = Y.config.doc.createEvent("UIEvents");
1089        customEvent.initUIEvent(type, bubbles, cancelable, view, detail);
1090
1091        //fire the event
1092        target.dispatchEvent(customEvent);
1093
1094    } else if (isObject(Y.config.doc.createEventObject)){ //IE
1095
1096        //create an IE event object
1097        customEvent = Y.config.doc.createEventObject();
1098
1099        //assign available properties
1100        customEvent.bubbles = bubbles;
1101        customEvent.cancelable = cancelable;
1102        customEvent.view = view;
1103        customEvent.detail = detail;
1104
1105        //fire the event
1106        target.fireEvent("on" + type, customEvent);
1107
1108    } else {
1109        Y.error("simulateUIEvent(): No event simulation framework present.");
1110    }
1111}
1112
1113/*
1114 * (iOS only) This is for creating native DOM gesture events which only iOS
1115 * v2.0+ is supporting.
1116 *
1117 * @method simulateGestureEvent
1118 * @private
1119 * @param {HTMLElement} target The target of the given event.
1120 * @param {String} type The type of event to fire. This can be any one of
1121 *      the following: touchstart, touchmove, touchend, touchcancel.
1122 * @param {Boolean} bubbles (Optional) Indicates if the event can be
1123 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
1124 *      default. The default is true.
1125 * @param {Boolean} cancelable (Optional) Indicates if the event can be
1126 *      canceled using preventDefault(). DOM Level 2 specifies that all
1127 *      touch events except touchcancel can be cancelled. The default
1128 *      is true for all events except touchcancel, for which the default
1129 *      is false.
1130 * @param {Window} view (Optional) The view containing the target. This is
1131 *      typically the window object. The default is window.
1132 * @param {Number} detail (Optional) Specifies some detail information about
1133 *      the event depending on the type of event.
1134 * @param {Number} screenX (Optional) The x-coordinate on the screen at which
1135 *      point the event occured. The default is 0.
1136 * @param {Number} screenY (Optional) The y-coordinate on the screen at which
1137 *      point the event occured. The default is 0.
1138 * @param {Number} clientX (Optional) The x-coordinate on the client at which
1139 *      point the event occured. The default is 0.
1140 * @param {Number} clientY (Optional) The y-coordinate on the client at which
1141 *      point the event occured. The default is 0.
1142 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
1143 *      is pressed while the event is firing. The default is false.
1144 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
1145 *      is pressed while the event is firing. The default is false.
1146 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
1147 *      is pressed while the event is firing. The default is false.
1148 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
1149 *      is pressed while the event is firing. The default is false.
1150 * @param {Number} scale (iOS v2+ only) The distance between two fingers
1151 *      since the start of an event as a multiplier of the initial distance.
1152 *      The default value is 1.0.
1153 * @param {Number} rotation (iOS v2+ only) The delta rotation since the start
1154 *      of an event, in degrees, where clockwise is positive and
1155 *      counter-clockwise is negative. The default value is 0.0.
1156 */
1157function simulateGestureEvent(target, type,
1158    bubbles,            // boolean
1159    cancelable,         // boolean
1160    view,               // DOMWindow
1161    detail,             // long
1162    screenX, screenY,   // long
1163    clientX, clientY,   // long
1164    ctrlKey, altKey, shiftKey, metaKey, // boolean
1165    scale,              // float
1166    rotation            // float
1167) {
1168    var customEvent;
1169
1170    if(!Y.UA.ios || Y.UA.ios<2.0) {
1171        Y.error("simulateGestureEvent(): Native gesture DOM eventframe is not available in this platform.");
1172    }
1173
1174    // check taget
1175    if (!target){
1176        Y.error("simulateGestureEvent(): Invalid target.");
1177    }
1178
1179    //check event type
1180    if (Y.Lang.isString(type)) {
1181        type = type.toLowerCase();
1182
1183        //make sure it's a supported touch event
1184        if (!gestureEvents[type]){
1185            Y.error("simulateTouchEvent(): Event type '" + type + "' not supported.");
1186        }
1187    } else {
1188        Y.error("simulateGestureEvent(): Event type must be a string.");
1189    }
1190
1191    // setup default values
1192    if (!Y.Lang.isBoolean(bubbles)) { bubbles = true; } // bubble by default
1193    if (!Y.Lang.isBoolean(cancelable)) { cancelable = true; }
1194    if (!Y.Lang.isObject(view))     { view = Y.config.win; }
1195    if (!Y.Lang.isNumber(detail))   { detail = 2; }     // usually not used.
1196    if (!Y.Lang.isNumber(screenX))  { screenX = 0; }
1197    if (!Y.Lang.isNumber(screenY))  { screenY = 0; }
1198    if (!Y.Lang.isNumber(clientX))  { clientX = 0; }
1199    if (!Y.Lang.isNumber(clientY))  { clientY = 0; }
1200    if (!Y.Lang.isBoolean(ctrlKey)) { ctrlKey = false; }
1201    if (!Y.Lang.isBoolean(altKey))  { altKey = false; }
1202    if (!Y.Lang.isBoolean(shiftKey)){ shiftKey = false; }
1203    if (!Y.Lang.isBoolean(metaKey)) { metaKey = false; }
1204
1205    if (!Y.Lang.isNumber(scale)){ scale = 1.0; }
1206    if (!Y.Lang.isNumber(rotation)){ rotation = 0.0; }
1207
1208    customEvent = Y.config.doc.createEvent("GestureEvent");
1209
1210    customEvent.initGestureEvent(type, bubbles, cancelable, view, detail,
1211        screenX, screenY, clientX, clientY,
1212        ctrlKey, altKey, shiftKey, metaKey,
1213        target, scale, rotation);
1214
1215    target.dispatchEvent(customEvent);
1216}
1217
1218
1219/*
1220 * @method simulateTouchEvent
1221 * @private
1222 * @param {HTMLElement} target The target of the given event.
1223 * @param {String} type The type of event to fire. This can be any one of
1224 *      the following: touchstart, touchmove, touchend, touchcancel.
1225 * @param {Boolean} bubbles (Optional) Indicates if the event can be
1226 *      bubbled up. DOM Level 2 specifies that all mouse events bubble by
1227 *      default. The default is true.
1228 * @param {Boolean} cancelable (Optional) Indicates if the event can be
1229 *      canceled using preventDefault(). DOM Level 2 specifies that all
1230 *      touch events except touchcancel can be cancelled. The default
1231 *      is true for all events except touchcancel, for which the default
1232 *      is false.
1233 * @param {Window} view (Optional) The view containing the target. This is
1234 *      typically the window object. The default is window.
1235 * @param {Number} detail (Optional) Specifies some detail information about
1236 *      the event depending on the type of event.
1237 * @param {Number} screenX (Optional) The x-coordinate on the screen at which
1238 *      point the event occured. The default is 0.
1239 * @param {Number} screenY (Optional) The y-coordinate on the screen at which
1240 *      point the event occured. The default is 0.
1241 * @param {Number} clientX (Optional) The x-coordinate on the client at which
1242 *      point the event occured. The default is 0.
1243 * @param {Number} clientY (Optional) The y-coordinate on the client at which
1244 *      point the event occured. The default is 0.
1245 * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys
1246 *      is pressed while the event is firing. The default is false.
1247 * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys
1248 *      is pressed while the event is firing. The default is false.
1249 * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys
1250 *      is pressed while the event is firing. The default is false.
1251 * @param {Boolean} metaKey (Optional) Indicates if one of the META keys
1252 *      is pressed while the event is firing. The default is false.
1253 * @param {TouchList} touches A collection of Touch objects representing
1254 *      all touches associated with this event.
1255 * @param {TouchList}
1255 targetTouches A collection of Touch objects
1256 *      representing all touches associated with this target.
1257 * @param {TouchList} changedTouches A collection of Touch objects
1258 *      representing all touches that changed in this event.
1259 * @param {Number} scale (iOS v2+ only) The distance between two fingers
1260 *      since the start of an event as a multiplier of the initial distance.
1261 *      The default value is 1.0.
1262 * @param {Number} rotation (iOS v2+ only) The delta rotation since the start
1263 *      of an event, in degrees, where clockwise is positive and
1264 *      counter-clockwise is negative. The default value is 0.0.
1265 */
1266function simulateTouchEvent(target, type,
1267    bubbles,            // boolean
1268    cancelable,         // boolean
1269    view,               // DOMWindow
1270    detail,             // long
1271    screenX, screenY,   // long
1272    clientX, clientY,   // long
1273    ctrlKey, altKey, shiftKey, metaKey, // boolean
1274    touches,            // TouchList
1275    targetTouches,      // TouchList
1276    changedTouches,     // TouchList
1277    scale,              // float
1278    rotation            // float
1279) {
1280
1281    var customEvent;
1282
1283    // check taget
1284    if (!target){
1285        Y.error("simulateTouchEvent(): Invalid target.");
1286    }
1287
1288    //check event type
1289    if (Y.Lang.isString(type)) {
1290        type = type.toLowerCase();
1291
1292        //make sure it's a supported touch event
1293        if (!touchEvents[type]){
1294            Y.error("simulateTouchEvent(): Event type '" + type + "' not supported.");
1295        }
1296    } else {
1297        Y.error("simulateTouchEvent(): Event type must be a string.");
1298    }
1299
1300    // note that the caller is responsible to pass appropriate touch objects.
1301    // check touch objects
1302    // Android(even 4.0) doesn't define TouchList yet
1303    /*if(type === 'touchstart' || type === 'touchmove') {
1304        if(!touches instanceof TouchList) {
1305            Y.error('simulateTouchEvent(): Invalid touches. It must be a TouchList');
1306        } else {
1307            if(touches.length === 0) {
1308                Y.error('simulateTouchEvent(): No touch object found.');
1309            }
1310        }
1311    } else if(type === 'touchend') {
1312        if(!changedTouches instanceof TouchList) {
1313            Y.error('simulateTouchEvent(): Invalid touches. It must be a TouchList');
1314        } else {
1315            if(changedTouches.length === 0) {
1316                Y.error('simulateTouchEvent(): No touch object found.');
1317            }
1318        }
1319    }*/
1320
1321    if(type === 'touchstart' || type === 'touchmove') {
1322        if(touches.length === 0) {
1323            Y.error('simulateTouchEvent(): No touch object in touches');
1324        }
1325    } else if(type === 'touchend') {
1326        if(changedTouches.length === 0) {
1327            Y.error('simulateTouchEvent(): No touch object in changedTouches');
1328        }
1329    }
1330
1331    // setup default values
1332    if (!Y.Lang.isBoolean(bubbles)) { bubbles = true; } // bubble by default.
1333    if (!Y.Lang.isBoolean(cancelable)) {
1334        cancelable = (type !== "touchcancel"); // touchcancel is not cancelled
1335    }
1336    if (!Y.Lang.isObject(view))     { view = Y.config.win; }
1337    if (!Y.Lang.isNumber(detail))   { detail = 1; } // usually not used. defaulted to # of touch objects.
1338    if (!Y.Lang.isNumber(screenX))  { screenX = 0; }
1339    if (!Y.Lang.isNumber(screenY))  { screenY = 0; }
1340    if (!Y.Lang.isNumber(clientX))  { clientX = 0; }
1341    if (!Y.Lang.isNumber(clientY))  { clientY = 0; }
1342    if (!Y.Lang.isBoolean(ctrlKey)) { ctrlKey = false; }
1343    if (!Y.Lang.isBoolean(altKey))  { altKey = false; }
1344    if (!Y.Lang.isBoolean(shiftKey)){ shiftKey = false; }
1345    if (!Y.Lang.isBoolean(metaKey)) { metaKey = false; }
1346    if (!Y.Lang.isNumber(scale))    { scale = 1.0; }
1347    if (!Y.Lang.isNumber(rotation)) { rotation = 0.0; }
1348
1349
1350    //check for DOM-compliant browsers first
1351    if (Y.Lang.isFunction(Y.config.doc.createEvent)) {
1352        if (Y.UA.android) {
1353            /*
1354                * Couldn't find android start version that supports touch event.
1355                * Assumed supported(btw APIs broken till icecream sandwitch)
1356                * from the beginning.
1357            */
1358            if(Y.UA.android < 4.0) {
1359                /*
1360                    * Touch APIs are broken in androids older than 4.0. We will use
1361                    * simulated touch apis for these versions.
1362                    * App developer still can listen for touch events. This events
1363                    * will be dispatched with touch event types.
1364                    *
1365                    * (Note) Used target for the relatedTarget. Need to verify if
1366                    * it has a side effect.
1367                */
1368                customEvent = Y.config.doc.createEvent("MouseEvents");
1369                customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,
1370                    screenX, screenY, clientX, clientY,
1371                    ctrlKey, altKey, shiftKey, metaKey,
1372                    0, target);
1373
1374                customEvent.touches = touches;
1375                customEvent.targetTouches = targetTouches;
1376                customEvent.changedTouches = changedTouches;
1377            } else {
1378                customEvent = Y.config.doc.createEvent("TouchEvent");
1379
1380                // Andoroid isn't compliant W3C initTouchEvent method signature.
1381                customEvent.initTouchEvent(touches, targetTouches, changedTouches,
1382                    type, view,
1383                    screenX, screenY, clientX, clientY,
1384                    ctrlKey, altKey, shiftKey, metaKey);
1385            }
1386        } else if (Y.UA.ios) {
1387            if(Y.UA.ios >= 2.0) {
1388                customEvent = Y.config.doc.createEvent("TouchEvent");
1389
1390                // Available iOS 2.0 and later
1391                customEvent.initTouchEvent(type, bubbles, cancelable, view, detail,
1392                    screenX, screenY, clientX, clientY,
1393                    ctrlKey, altKey, shiftKey, metaKey,
1394                    touches, targetTouches, changedTouches,
1395                    scale, rotation);
1396            } else {
1397                Y.error('simulateTouchEvent(): No touch event simulation framework present for iOS, '+Y.UA.ios+'.');
1398            }
1399        } else {
1400            Y.error('simulateTouchEvent(): Not supported agent yet, '+Y.UA.userAgent);
1401        }
1402
1403        //fire the event
1404        target.dispatchEvent(customEvent);
1405    //} else if (Y.Lang.isObject(doc.createEventObject)){ // Windows Mobile/IE, support later
1406    } else {
1407        Y.error('simulateTouchEvent(): No event simulation framework present.');
1408    }
1409}
1410
1411/**
1412 * Simulates the event or gesture with the given name on a target.
1413 * @param {HTMLElement} target The DOM element that's the target of the event.
1414 * @param {String} type The type of event or name of the supported gesture to simulate
1415 *      (i.e., "click", "doubletap", "flick").
1416 * @param {Object} options (Optional) Extra options to copy onto the event object.
1417 *      For gestures, options are used to refine the gesture behavior.
1418 * @for Event
1419 * @method simulate
1420 * @static
1421 */
1422Y.Event.simulate = function(target, type, options){
1423
1424    options = options || {};
1425
1426    if (mouseEvents[type] || pointerEvents[type]){
1427        simulateMouseEvent(target, type, options.bubbles,
1428            options.cancelable, options.view, options.detail, options.screenX,
1429            options.screenY, options.clientX, options.clientY, options.ctrlKey,
1430            options.altKey, options.shiftKey, options.metaKey, options.button,
1431            options.relatedTarget);
1432    } else if (keyEvents[type]){
1433        simulateKeyEvent(target, type, options.bubbles,
1434            options.cancelable, options.view, options.ctrlKey,
1435            options.altKey, options.shiftKey, options.metaKey,
1436            options.keyCode, options.charCode);
1437    } else if (uiEvents[type]){
1438        simulateUIEvent(target, type, options.bubbles,
1439            options.cancelable, options.view, options.detail);
1440
1441    // touch low-level event simulation
1442    } else if (touchEvents[type]) {
1443        if((Y.config.win && ("ontouchstart" in Y.config.win)) && !(Y.UA.phantomjs) && !(Y.UA.chrome && Y.UA.chrome < 6)) {
1444            simulateTouchEvent(target, type,
1445                options.bubbles, options.cancelable, options.view, options.detail,
1446                options.screenX, options.screenY, options.clientX, options.clientY,
1447                options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
1448                options.touches, options.targetTouches, options.changedTouches,
1449                options.scale, options.rotation);
1450        } else {
1451            Y.error("simulate(): Event '" + type + "' can't be simulated. Use gesture-simulate module instead.");
1452        }
1453
1454    // ios gesture low-level event simulation (iOS v2+ only)
1455    } else if(Y.UA.ios && Y.UA.ios >= 2.0 && gestureEvents[type]) {
1456        simulateGestureEvent(target, type,
1457            options.bubbles, options.cancelable, options.view, options.detail,
1458            options.screenX, options.screenY, options.clientX, options.clientY,
1459            options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
1460            options.scale, options.rotation);
1461
1462    // anything else
1463    } else {
1464        Y.error("simulate(): Event '" + type + "' can't be simulated.");
1465    }
1466};
1467
1468
1469})();
1470
1471
1472
1473}, 'patched-v3.18.3', {"requires": ["event-base"]});
1474
1475YUI.add('event-synthetic', function (Y, NAME) {
1476
1477/**
1478 * Define new DOM events that can be subscribed to from Nodes.
1479 *
1480 * @module event
1481 * @submodule event-synthetic
1482 */
1483var CustomEvent = Y.CustomEvent,
1484    DOMMap   = Y.Env.evt.dom_map,
1485    toArray  = Y.Array,
1486    YLang    = Y.Lang,
1487    isObject = YLang.isObject,
1488    isString = YLang.isString,
1489    isArray  = YLang.isArray,
1490    query    = Y.Selector.query,
1491    noop     = function () {};
1492
1493/**
1494 * <p>The triggering mechanism used by SyntheticEvents.</p>
1495 *
1496 * <p>Implementers should not instantiate these directly.  Use the Notifier
1497 * provided to the event's implemented <code>on(node, sub, notifier)</code> or
1498 * <code>delegate(node, sub, notifier, filter)</code> methods.</p>
1499 *
1500 * @class SyntheticEvent.Notifier
1501 * @constructor
1502 * @param handle {EventHandle} the detach handle for the subscription to an
1503 *              internal custom event used to execute the callback passed to
1504 *              on(..) or delegate(..)
1505 * @param emitFacade {Boolean} take steps to ensure the first arg received by
1506 *              the subscription callback is an event facade
1507 * @private
1508 * @since 3.2.0
1509 */
1510function Notifier(handle, emitFacade) {
1511    this.handle     = handle;
1512    this.emitFacade = emitFacade;
1513}
1514
1515/**
1516 * <p>Executes the subscription callback, passing the firing arguments as the
1517 * first parameters to that callback. For events that are configured with
1518 * emitFacade=true, it is common practice to pass the triggering DOMEventFacade
1519 * as the first parameter.  Barring a proper DOMEventFacade or EventFacade
1520 * (from a CustomEvent), a new EventFacade will be generated.  In that case, if
1521 * fire() is called with a simple object, it will be mixed into the facade.
1522 * Otherwise, the facade will be prepended to the callback parameters.</p>
1523 *
1524 * <p>For notifiers provided to delegate logic, the first argument should be an
1525 * object with a &quot;currentTarget&quot; property to identify what object to
1526 * default as 'this' in the callback.  Typically this is gleaned from the
1527 * DOMEventFacade or EventFacade, but if configured with emitFacade=false, an
1528 * object must be provided.  In that case, the object will be removed from the
1529 * callback parameters.</p>
1530 *
1531 * <p>Additional arguments passed during event subscription will be
1532 * automatically added after those passed to fire().</p>
1533 *
1534 * @method fire
1535 * @param {EventFacade|DOMEventFacade|any} e (see description)
1536 * @param {any[]} [arg*] additional arguments received by all subscriptions
1537 * @private
1538 */
1539Notifier.prototype.fire = function (e) {
1540    // first arg to delegate notifier should be an object with currentTarget
1541    var args     = toArray(arguments, 0, true),
1542        handle   = this.handle,
1543        ce       = handle.evt,
1544        sub      = handle.sub,
1545        thisObj  = sub.context,
1546        delegate = sub.filter,
1547        event    = e || {},
1548        ret;
1549
1550    if (this.emitFacade) {
1551        if (!e || !e.preventDefault) {
1552            event = ce._getFacade();
1553
1554            if (isObject(e) && !e.preventDefault) {
1555                Y.mix(event, e, true);
1556                args[0] = event;
1557            } else {
1558                args.unshift(event);
1559            }
1560        }
1561
1562        event.type    = ce.type;
1563        event.details = args.slice();
1564
1565        if (delegate) {
1566            event.container = ce.host;
1567        }
1568    } else if (delegate && isObject(e) && e.currentTarget) {
1569        args.shift();
1570    }
1571
1572    sub.context = thisObj || event.currentTarget || ce.host;
1573    ret = ce.fire.apply(ce, args);
1574
1575    // have to handle preventedFn and stoppedFn manually because
1576    // Notifier CustomEvents are forced to emitFacade=false
1577    if (e.prevented && ce.preventedFn) {
1578        ce.preventedFn.apply(ce, args);
1579    }
1580
1581    if (e.stopped && ce.stoppedFn) {
1582        ce.stoppedFn.apply(ce, args);
1583    }
1584
1585    sub.context = thisObj; // reset for future firing
1586
1587    // to capture callbacks that return false to stopPropagation.
1588    // Useful for delegate implementations
1589    return ret;
1590};
1591
1592/**
1593 * Manager object for synthetic event subscriptions to aggregate multiple synths on the
1594 * same node without colliding with actual DOM subscription entries in the global map of
1595 * DOM subscriptions.  Also facilitates proper cleanup on page unload.
1596 *
1597 * @class SynthRegistry
1598 * @constructor
1599 * @param el {HTMLElement} the DOM element
1600 * @param yuid {String} the yuid stamp for the element
1601 * @param key {String} the generated id token used to identify an event type +
1602 *                     element in the global DOM subscription map.
1603 * @private
1604 */
1605function SynthRegistry(el, yuid, key) {
1606    this.handles = [];
1607    this.el      = el;
1608    this.key     = key;
1609    this.domkey  = yuid;
1610}
1611
1612SynthRegistry.prototype = {
1613    constructor: SynthRegistry,
1614
1615    // A few object properties to fake the CustomEvent interface for page
1616    // unload cleanup.  DON'T TOUCH!
1617    type      : '_synth',
1618    fn        : noop,
1619    capture   : false,
1620
1621    /**
1622     * Adds a subscription from the Notifier registry.
1623     *
1624     * @method register
1625     * @param handle {EventHandle} the subscription
1626     * @since 3.4.0
1627     */
1628    register: function (handle) {
1629        handle.evt.registry = this;
1630        this.handles.push(handle);
1631    },
1632
1633    /**
1634     * Removes the subscription from the Notifier registry.
1635     *
1636     * @method _unregisterSub
1637     * @param sub {Subscription} the subscription
1638     * @since 3.4.0
1639     */
1640    unregister: function (sub) {
1641        var handles = this.handles,
1642            events = DOMMap[this.domkey],
1643            i;
1644
1645        for (i = handles.length - 1; i >= 0; --i) {
1646            if (handles[i].sub === sub) {
1647                handles.splice(i, 1);
1648                break;
1649            }
1650        }
1651
1652        // Clean up left over objects when there are no more subscribers.
1653        if (!handles.length) {
1654            delete events[this.key];
1655            if (!Y.Object.size(events)) {
1656                delete DOMMap[this.domkey];
1657            }
1658        }
1659    },
1660
1661    /**
1662     * Used by the event system's unload cleanup process.  When navigating
1663     * away from the page, the event system iterates the global map of element
1664     * subscriptions and detaches everything using detachAll().  Normally,
1665     * the map is populated with custom events, so this object needs to
1666     * at least support the detachAll method to duck type its way to
1667     * cleanliness.
1668     *
1669     * @method detachAll
1670     * @private
1671     * @since 3.4.0
1672     */
1673    detachAll : function () {
1674        var handles = this.handles,
1675            i = handles.length;
1676
1677        while (--i >= 0) {
1678            handles[i].detach();
1679        }
1680    }
1681};
1682
1683/**
1684 * <p>Wrapper class for the integration of new events into the YUI event
1685 * infrastructure.  Don't instantiate this object directly, use
1686 * <code>Y.Event.define(type, config)</code>.  See that method for details.</p>
1687 *
1688 * <p>Properties that MAY or SHOULD be specified in the configuration are noted
1689 * below and in the description of <code>Y.Event.define</code>.</p>
1690 *
1691 * @class SyntheticEvent
1692 * @constructor
1693 * @param cfg {Object} Implementation pieces and configuration
1694 * @since 3.1.0
1695 * @in event-synthetic
1696 */
1697function SyntheticEvent() {
1698    this._init.apply(this, arguments);
1699}
1700
1701Y.mix(SyntheticEvent, {
1702    Notifier: Notifier,
1703    SynthRegistry: SynthRegistry,
1704
1705    /**
1706     * Returns the array of subscription handles for a node for the given event
1707     * type.  Passing true as the third argument will create a registry entry
1708     * in the event system's DOM map to host the array if one doesn't yet exist.
1709     *
1710     * @method getRegistry
1711     * @param node {Node} the node
1712     * @param type {String} the event
1713     * @param create {Boolean} create a registration entry to host a new array
1714     *                  if one doesn't exist.
1715     * @return {Array}
1716     * @static
1717     * @protected
1718     * @since 3.2.0
1719     */
1720    getRegistry: function (node, type, create) {
1721        var el     = node._node,
1722            yuid   = Y.stamp(el),
1723            key    = 'event:' + yuid + type + '_synth',
1724            events = DOMMap[yuid];
1725
1726        if (create) {
1727            if (!events) {
1728                events = DOMMap[yuid] = {};
1729            }
1730            if (!events[key]) {
1731                events[key] = new SynthRegistry(el, yuid, key);
1732            }
1733        }
1734
1735        return (events && events[key]) || null;
1736    },
1737
1738    /**
1739     * Alternate <code>_delete()</code> method for the CustomEvent object
1740     * created to manage SyntheticEvent subscriptions.
1741     *
1742     * @method _deleteSub
1743     * @param sub {Subscription} the subscription to clean up
1744     * @private
1745     * @since 3.2.0
1746     */
1747    _deleteSub: function (sub) {
1748        if (sub && sub.fn) {
1749            var synth = this.eventDef,
1750                method = (sub.filter) ? 'detachDelegate' : 'detach';
1751
1752            this._subscribers = [];
1753
1754            if (CustomEvent.keepDeprecatedSubs) {
1755                this.subscribers = {};
1756            }
1757
1758            synth[method](sub.node, sub, this.notifier, sub.filter);
1759            this.registry.unregister(sub);
1760
1761            delete sub.fn;
1762            delete sub.node;
1763            delete sub.context;
1764        }
1765    },
1766
1767    prototype: {
1768        constructor: SyntheticEvent,
1769
1770        /**
1771         * Construction logic for the event.
1772         *
1773         * @method _init
1774         * @protected
1775         */
1776        _init: function () {
1777            var config = this.publishConfig || (this.publishConfig = {});
1778
1779            // The notification mechanism handles facade creation
1780            this.emitFacade = ('emitFacade' in config) ?
1781                                config.emitFacade :
1782                                true;
1783            config.emitFacade  = false;
1784        },
1785
1786        /**
1787         * <p>Implementers MAY provide this method definition.</p>
1788         *
1789         * <p>Implement this function if the event supports a different
1790         * subscription signature.  This function is used by both
1791         * <code>on()</code> and <code>delegate()</code>.  The second parameter
1792         * indicates that the event is being subscribed via
1793         * <code>delegate()</code>.</p>
1794         *
1795         * <p>Implementations must remove extra arguments from the args list
1796         * before returning.  The required args for <code>on()</code>
1797         * subscriptions are</p>
1798         * <pre><code>[type, callback, target, context, argN...]</code></pre>
1799         *
1800         * <p>The required args for <code>delegate()</code>
1801         * subscriptions are</p>
1802         *
1803         * <pre><code>[type, callback, target, filter, context, argN...]</code></pre>
1804         *
1805         * <p>The return value from this function will be stored on the
1806         * subscription in the '_extra' property for reference elsewhere.</p>
1807         *
1808         * @method processArgs
1809         * @param args {Array} parmeters passed to Y.on(..) or Y.delegate(..)
1810         * @param delegate {Boolean} true if the subscription is from Y.delegate
1811         * @return {any}
1812         */
1813        processArgs: noop,
1814
1815        /**
1816         * <p>Implementers MAY override this property.</p>
1817         *
1818         * <p>Whether to prevent multiple subscriptions to this event that are
1819         * classified as being the same.  By default, this means the subscribed
1820         * callback is the same function.  See the <code>subMatch</code>
1821         * method.  Setting this to true will impact performance for high volume
1822         * events.</p>
1823         *
1824         * @property preventDups
1825         * @type {Boolean}
1826         * @default false
1827         */
1828        //preventDups  : false,
1829
1830        /**
1831         * <p>Implementers SHOULD provide this method definition.</p>
1832         *
1833         * Implementation logic for subscriptions done via <code>node.on(type,
1834         * fn)</code> or <code>Y.on(type, fn, target)</code>.  This
1835         * function should set up the monitor(s) that will eventually fire the
1836         * event.  Typically this involves subscribing to at least one DOM
1837         * event.  It is recommended to store detach handles from any DOM
1838         * subscriptions to make for easy cleanup in the <code>detach</code>
1839         * method.  Typically these handles are added to the <code>sub</code>
1840         * object.  Also for SyntheticEvents that leverage a single DOM
1841         * subscription under the hood, it is recommended to pass the DOM event
1842         * object to <code>notifier.fire(e)</code>.  (The event name on the
1843         * object will be updated).
1844         *
1845         * @method on
1846         * @param node {Node} the node the subscription is being applied to
1847         * @param sub {Subscription} the object to track this subscription
1848         * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
1849         *              trigger the execution of the subscribers
1850         */
1851        on: noop,
1852
1853        /**
1854         * <p>Implementers SHOULD provide this method definition.</p>
1855         *
1856         * <p>Implementation logic for detaching subscriptions done via
1857         * <code>
1857node.on(type, fn)</code>.  This function should clean up any
1858         * subscriptions made in the <code>on()</code> phase.</p>
1859         *
1860         * @method detach
1861         * @param node {Node} the node the subscription was applied to
1862         * @param sub {Subscription} the object tracking this subscription
1863         * @param notifier {SyntheticEvent.Notifier} the Notifier used to
1864         *              trigger the execution of the subscribers
1865         */
1866        detach: noop,
1867
1868        /**
1869         * <p>Implementers SHOULD provide this method definition.</p>
1870         *
1871         * <p>Implementation logic for subscriptions done via
1872         * <code>node.delegate(type, fn, filter)</code> or
1873         * <code>Y.delegate(type, fn, container, filter)</code>.  Like with
1874         * <code>on()</code> above, this function should monitor the environment
1875         * for the event being fired, and trigger subscription execution by
1876         * calling <code>notifier.fire(e)</code>.</p>
1877         *
1878         * <p>This function receives a fourth argument, which is the filter
1879         * used to identify which Node's are of interest to the subscription.
1880         * The filter will be either a boolean function that accepts a target
1881         * Node for each hierarchy level as the event bubbles, or a selector
1882         * string.  To translate selector strings into filter functions, use
1883         * <code>Y.delegate.compileFilter(filter)</code>.</p>
1884         *
1885         * @method delegate
1886         * @param node {Node} the node the subscription is being applied to
1887         * @param sub {Subscription} the object to track this subscription
1888         * @param notifier {SyntheticEvent.Notifier} call notifier.fire(..) to
1889         *              trigger the execution of the subscribers
1890         * @param filter {String|Function} Selector string or function that
1891         *              accepts an event object and returns null, a Node, or an
1892         *              array of Nodes matching the criteria for processing.
1893         * @since 3.2.0
1894         */
1895        delegate       : noop,
1896
1897        /**
1898         * <p>Implementers SHOULD provide this method definition.</p>
1899         *
1900         * <p>Implementation logic for detaching subscriptions done via
1901         * <code>node.delegate(type, fn, filter)</code> or
1902         * <code>Y.delegate(type, fn, container, filter)</code>.  This function
1903         * should clean up any subscriptions made in the
1904         * <code>delegate()</code> phase.</p>
1905         *
1906         * @method detachDelegate
1907         * @param node {Node} the node the subscription was applied to
1908         * @param sub {Subscription} the object tracking this subscription
1909         * @param notifier {SyntheticEvent.Notifier} the Notifier used to
1910         *              trigger the execution of the subscribers
1911         * @param filter {String|Function} Selector string or function that
1912         *              accepts an event object and returns null, a Node, or an
1913         *              array of Nodes matching the criteria for processing.
1914         * @since 3.2.0
1915         */
1916        detachDelegate : noop,
1917
1918        /**
1919         * Sets up the boilerplate for detaching the event and facilitating the
1920         * execution of subscriber callbacks.
1921         *
1922         * @method _on
1923         * @param args {Array} array of arguments passed to
1924         *              <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
1925         * @param delegate {Boolean} true if called from
1926         * <code>Y.delegate(...)</code>
1927         * @return {EventHandle} the detach handle for this subscription
1928         * @private
1929         * since 3.2.0
1930         */
1931        _on: function (args, delegate) {
1932            var handles  = [],
1933                originalArgs = args.slice(),
1934                extra    = this.processArgs(args, delegate),
1935                selector = args[2],
1936                method   = delegate ? 'delegate' : 'on',
1937                nodes, handle;
1938
1939            // Can't just use Y.all because it doesn't support window (yet?)
1940            nodes = (isString(selector)) ?
1941                query(selector) :
1942                toArray(selector || Y.one(Y.config.win));
1943
1944            if (!nodes.length && isString(selector)) {
1945                handle = Y.on('available', function () {
1946                    Y.mix(handle, Y[method].apply(Y, originalArgs), true);
1947                }, selector);
1948
1949                return handle;
1950            }
1951
1952            Y.Array.each(nodes, function (node) {
1953                var subArgs = args.slice(),
1954                    filter;
1955
1956                node = Y.one(node);
1957
1958                if (node) {
1959                    if (delegate) {
1960                        filter = subArgs.splice(3, 1)[0];
1961                    }
1962
1963                    // (type, fn, el, thisObj, ...) => (fn, thisObj, ...)
1964                    subArgs.splice(0, 4, subArgs[1], subArgs[3]);
1965
1966                    if (!this.preventDups ||
1967                        !this.getSubs(node, args, null, true))
1968                    {
1969                        handles.push(this._subscribe(node, method, subArgs, extra, filter));
1970                    }
1971                }
1972            }, this);
1973
1974            return (handles.length === 1) ?
1975                handles[0] :
1976                new Y.EventHandle(handles);
1977        },
1978
1979        /**
1980         * Creates a new Notifier object for use by this event's
1981         * <code>on(...)</code> or <code>delegate(...)</code> implementation
1982         * and register the custom event proxy in the DOM system for cleanup.
1983         *
1984         * @method _subscribe
1985         * @param node {Node} the Node hosting the event
1986         * @param method {String} "on" or "delegate"
1987         * @param args {Array} the subscription arguments passed to either
1988         *              <code>Y.on(...)</code> or <code>Y.delegate(...)</code>
1989         *              after running through <code>processArgs(args)</code> to
1990         *              normalize the argument signature
1991         * @param extra {any} Extra data parsed from
1992         *              <code>processArgs(args)</code>
1993         * @param filter {String|Function} the selector string or function
1994         *              filter passed to <code>Y.delegate(...)</code> (not
1995         *              present when called from <code>Y.on(...)</code>)
1996         * @return {EventHandle}
1997         * @private
1998         * @since 3.2.0
1999         */
2000        _subscribe: function (node, method, args, extra, filter) {
2001            var dispatcher = new Y.CustomEvent(this.type, this.publishConfig),
2002                handle     = dispatcher.on.apply(dispatcher, args),
2003                notifier   = new Notifier(handle, this.emitFacade),
2004                registry   = SyntheticEvent.getRegistry(node, this.type, true),
2005                sub        = handle.sub;
2006
2007            sub.node   = node;
2008            sub.filter = filter;
2009            if (extra) {
2010                this.applyArgExtras(extra, sub);
2011            }
2012
2013            Y.mix(dispatcher, {
2014                eventDef     : this,
2015                notifier     : notifier,
2016                host         : node,       // I forget what this is for
2017                currentTarget: node,       // for generating facades
2018                target       : node,       // for generating facades
2019                el           : node._node, // For category detach
2020
2021                _delete      : SyntheticEvent._deleteSub
2022            }, true);
2023
2024            handle.notifier = notifier;
2025
2026            registry.register(handle);
2027
2028            // Call the implementation's "on" or "delegate" method
2029            this[method](node, sub, notifier, filter);
2030
2031            return handle;
2032        },
2033
2034        /**
2035         * <p>Implementers MAY provide this method definition.</p>
2036         *
2037         * <p>Implement this function if you want extra data extracted during
2038         * processArgs to be propagated to subscriptions on a per-node basis.
2039         * That is to say, if you call <code>Y.on('xyz', fn, xtra, 'div')</code>
2040         * the data returned from processArgs will be shared
2041         * across the subscription objects for all the divs.  If you want each
2042         * subscription to receive unique information, do that processing
2043         * here.</p>
2044         *
2045         * <p>The default implementation adds the data extracted by processArgs
2046         * to the subscription object as <code>sub._extra</code>.</p>
2047         *
2048         * @method applyArgExtras
2049         * @param extra {any} Any extra data extracted from processArgs
2050         * @param sub {Subscription} the individual subscription
2051         */
2052        applyArgExtras: function (extra, sub) {
2053            sub._extra = extra;
2054        },
2055
2056        /**
2057         * Removes the subscription(s) from the internal subscription dispatch
2058         * mechanism.  See <code>SyntheticEvent._deleteSub</code>.
2059         *
2060         * @method _detach
2061         * @param args {Array} The arguments passed to
2062         *                  <code>node.detach(...)</code>
2063         * @private
2064         * @since 3.2.0
2065         */
2066        _detach: function (args) {
2067            // Can't use Y.all because it doesn't support window (yet?)
2068            // TODO: Does Y.all support window now?
2069            var target = args[2],
2070                els    = (isString(target)) ?
2071                            query(target) : toArray(target),
2072                node, i, len, handles, j;
2073
2074            // (type, fn, el, context, filter?) => (type, fn, context, filter?)
2075            args.splice(2, 1);
2076
2077            for (i = 0, len = els.length; i < len; ++i) {
2078                node = Y.one(els[i]);
2079
2080                if (node) {
2081                    handles = this.getSubs(node, args);
2082
2083                    if (handles) {
2084                        for (j = handles.length - 1; j >= 0; --j) {
2085                            handles[j].detach();
2086                        }
2087                    }
2088                }
2089            }
2090        },
2091
2092        /**
2093         * Returns the detach handles of subscriptions on a node that satisfy a
2094         * search/filter function.  By default, the filter used is the
2095         * <code>subMatch</code> method.
2096         *
2097         * @method getSubs
2098         * @param node {Node} the node hosting the event
2099         * @param args {Array} the array of original subscription args passed
2100         *              to <code>Y.on(...)</code> (before
2101         *              <code>processArgs</code>
2102         * @param filter {Function} function used to identify a subscription
2103         *              for inclusion in the returned array
2104         * @param first {Boolean} stop after the first match (used to check for
2105         *              duplicate subscriptions)
2106         * @return {EventHandle[]} detach handles for the matching subscriptions
2107         */
2108        getSubs: function (node, args, filter, first) {
2109            var registry = SyntheticEvent.getRegistry(node, this.type),
2110                handles  = [],
2111                allHandles, i, len, handle;
2112
2113            if (registry) {
2114                allHandles = registry.handles;
2115
2116                if (!filter) {
2117                    filter = this.subMatch;
2118                }
2119
2120                for (i = 0, len = allHandles.length; i < len; ++i) {
2121                    handle = allHandles[i];
2122                    if (filter.call(this, handle.sub, args)) {
2123                        if (first) {
2124                            return handle;
2125                        } else {
2126                            handles.push(allHandles[i]);
2127                        }
2128                    }
2129                }
2130            }
2131
2132            return handles.length && handles;
2133        },
2134
2135        /**
2136         * <p>Implementers MAY override this to define what constitutes a
2137         * &quot;same&quot; subscription.  Override implementations should
2138         * consider the lack of a comparator as a match, so calling
2139         * <code>getSubs()</code> with no arguments will return all subs.</p>
2140         *
2141         * <p>Compares a set of subscription arguments against a Subscription
2142         * object to determine if they match.  The default implementation
2143         * compares the callback function against the second argument passed to
2144         * <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
2145         *
2146         * @method subMatch
2147         * @param sub {Subscription} the existing subscription
2148         * @param args {Array} the calling arguments passed to
2149         *                  <code>Y.on(...)</code> etc.
2150         * @return {Boolean} true if the sub can be described by the args
2151         *                  present
2152         * @since 3.2.0
2153         */
2154        subMatch: function (sub, args) {
2155            // Default detach cares only about the callback matching
2156            return !args[1] || sub.fn === args[1];
2157        }
2158    }
2159}, true);
2160
2161Y.SyntheticEvent = SyntheticEvent;
2162
2163/**
2164 * <p>Defines a new event in the DOM event system.  Implementers are
2165 * responsible for monitoring for a scenario whereby the event is fired.  A
2166 * notifier object is provided to the functions identified below.  When the
2167 * criteria defining the event are met, call notifier.fire( [args] ); to
2168 * execute event subscribers.</p>
2169 *
2170 * <p>The first parameter is the name of the event.  The second parameter is a
2171 * configuration object which define the behavior of the event system when the
2172 * new event is subscribed to or detached from.  The methods that should be
2173 * defined in this configuration object are <code>on</code>,
2174 * <code>detach</code>, <code>delegate</code>, and <code>detachDelegate</code>.
2175 * You are free to define any other methods or properties needed to define your
2176 * event.  Be aware, however, that since the object is used to subclass
2177 * SyntheticEvent, you should avoid method names used by SyntheticEvent unless
2178 * your intention is to override the default behavior.</p>
2179 *
2180 * <p>This is a list of properties and methods that you can or should specify
2181 * in the configuration object:</p>
2182 *
2183 * <dl>
2184 *   <dt><code>on</code></dt>
2185 *       <dd><code>function (node, subscription, notifier)</code> The
2186 *       implementation logic for subscription.  Any special setup you need to
2187 *       do to create the environment for the event being fired--E.g. native
2188 *       DOM event subscriptions.  Store subscription related objects and
2189 *       state on the <code>subscription</code> object.  When the
2190 *       criteria have been met to fire the synthetic event, call
2191 *       <code>notifier.fire(e)</code>.  See Notifier's <code>fire()</code>
2192 *       method for details about what to pass as parameters.</dd>
2193 *
2194 *   <dt><code>detach</code></dt>
2195 *       <dd><code>function (node, subscription, notifier)</code> The
2196 *       implementation logic for cleaning up a detached subscription. E.g.
2197 *       detach any DOM subscriptions added in <code>on</code>.</dd>
2198 *
2199 *   <dt><code>delegate</code></dt>
2200 *       <dd><code>function (node, subscription, notifier, filter)</code> The
2201 *       implementation logic for subscription via <code>Y.delegate</code> or
2202 *       <code>node.delegate</code>.  The filter is typically either a selector
2203 *       string or a function.  You can use
2204 *       <code>Y.delegate.compileFilter(selectorString)</code> to create a
2205 *       filter function from a selector string if needed.  The filter function
2206 *       expects an event object as input and should output either null, a
2207 *       matching Node, or an array of matching Nodes.  Otherwise, this acts
2208 *       like <code>on</code> DOM event subscriptions.  Store subscription
2209 *       related objects and information on the <code>subscription</code>
2210 *       object.  When the criteria have been met to fire the synthetic event,
2211 *       call <code>notifier.fire(e)</code> as noted above.</dd>
2212 *
2213 *   <dt><code>detachDelegate</code></dt>
2214 *       <dd><code>function (node, subscription, notifier)</code> The
2215 *       implementation logic for cleaning up a detached delegate subscription.
2216 *       E.g. detach any DOM delegate subscriptions added in
2217 *       <code>delegate</code>.</dd>
2218 *
2219 *   <dt><code>publishConfig</code></dt>
2220 *       <dd>(Object) The configuration object that will be used to instantiate
2221 *       the underlying CustomEvent. See Notifier's <code>fire</code> method
2222 *       for details.</dd>
2223 *
2224 *   <dt><code>processArgs</code></dt
2225 *       <dd>
2226 *          <p><code>function (argArray, fromDelegate)</code> Optional method
2227 *          to extract any additional arguments from the subscription
2228 *          signature.  Using this allows <code>on</code> or
2229 *          <code>delegate</code> signatures like
2230 *          <code>node.on(&quot;hover&quot;, overCallback,
2231 *          outCallback)</code>.</p>
2232 *          <p>When processing an atypical argument signature, make sure the
2233 *          args array is returned to the normal signature before returning
2234 *          from the function.  For example, in the &quot;hover&quot; example
2235 *          above, the <code>outCallback</code> needs to be <code>splice</code>d
2236 *          out of the array.  The expected signature of the args array for
2237 *          <code>on()</code> subscriptions is:</p>
2238 *          <pre>
2239 *              <code>[type, callback, target, contextOverride, argN...]</code>
2240 *          </pre>
2241 *          <p>And for <code>delegate()</code>:</p>
2242 *          <pre>
2243 *              <code>[type, callback, target, filter, contextOverride, argN...]</code>
2244 *          </pre>
2245 *          <p>where <code>target</code> is the node the event is being
2246 *          subscribed for.  You can see these signatures documented for
2247 *          <code>Y.on()</code> and <code>Y.delegate()</code> respectively.</p>
2248 *          <p>Whatever gets returned from the function will be stored on the
2249 *          <code>subscription</code> object under
2250 *          <code>subscription._extra</code>.</p></dd>
2251 *   <dt><code>subMatch</code></dt>
2252 *       <dd>
2253 *           <p><code>function (sub, args)</code>  Compares a set of
2254 *           subscription arguments against a Subscription object to determine
2255 *           if they match.  The default implementation compares the callback
2256 *           function against the second argument passed to
2257 *           <code>Y.on(...)</code> or <code>node.detach(...)</code> etc.</p>
2258 *       </dd>
2259 * </dl>
2260 *
2261 * @method define
2262 * @param type {String} the name of the event
2263 * @param config {Object} the prototype definition for the new event (see above)
2264 * @param force {Boolean} override an existing event (use with caution)
2265 * @return {SyntheticEvent} the subclass implementation instance created to
2266 *              handle event subscriptions of this type
2267 * @static
2268 * @for Event
2269 * @since 3.1.0
2270 * @in event-synthetic
2271 */
2272Y.Event.define = function (type, config, force) {
2273    var eventDef, Impl, synth;
2274
2275    if (type && type.type) {
2276        eventDef = type;
2277        force = config;
2278    } else if (config) {
2279        eventDef = Y.merge({ type: type }
2279, config);
2280    }
2281
2282    if (eventDef) {
2283        if (force || !Y.Node.DOM_EVENTS[eventDef.type]) {
2284            Impl = function () {
2285                SyntheticEvent.apply(this, arguments);
2286            };
2287            Y.extend(Impl, SyntheticEvent, eventDef);
2288            synth = new Impl();
2289
2290            type = synth.type;
2291
2292            Y.Node.DOM_EVENTS[type] = Y.Env.evt.plugins[type] = {
2293                eventDef: synth,
2294
2295                on: function () {
2296                    return synth._on(toArray(arguments));
2297                },
2298
2299                delegate: function () {
2300                    return synth._on(toArray(arguments), true);
2301                },
2302
2303                detach: function () {
2304                    return synth._detach(toArray(arguments));
2305                }
2306            };
2307
2308        }
2309    } else if (isString(type) || isArray(type)) {
2310        Y.Array.each(toArray(type), function (t) {
2311            Y.Node.DOM_EVENTS[t] = 1;
2312        });
2313    }
2314
2315    return synth;
2316};
2317
2318
2319}, 'patched-v3.18.3', {"requires": ["node-base", "event-custom-complex"]});
2320
2321YUI.add('intl', function (Y, NAME) {
2322
2323var _mods = {},
2324
2325    ROOT_LANG = "yuiRootLang",
2326    ACTIVE_LANG = "yuiActiveLang",
2327    NONE = [];
2328
2329/**
2330 * Provides utilities to support the management of localized resources (strings and formatting patterns).
2331 *
2332 * @module intl
2333 */
2334
2335/**
2336 * The Intl utility provides a central location for managing sets of localized resources (strings and formatting patterns).
2337 *
2338 * @class Intl
2339 * @uses EventTarget
2340 * @static
2341 */
2342Y.mix(Y.namespace("Intl"), {
2343
2344    /**
2345     * Private method to retrieve the language hash for a given module.
2346     *
2347     * @method _mod
2348     * @private
2349     *
2350     * @param {String} module The name of the module
2351     * @return {Object} The hash of localized resources for the module, keyed by BCP language tag
2352     */
2353    _mod : function(module) {
2354        if (!_mods[module]) {
2355            _mods[module] = {};
2356        }
2357        return _mods[module];
2358    },
2359
2360    /**
2361     * Sets the active language for the given module.
2362     *
2363     * Returns false on failure, which would happen if the language had not been registered through the <a href="#method_add">add()</a> method.
2364     *
2365     * @method setLang
2366     *
2367     * @param {String} module The module name.
2368     * @param {String} lang The BCP 47 language tag.
2369     * @return boolean true if successful, false if not.
2370     */
2371    setLang : function(module, lang) {
2372        var langs = this._mod(module),
2373            currLang = langs[ACTIVE_LANG],
2374            exists = !!langs[lang];
2375
2376        if (exists && lang !== currLang) {
2377            langs[ACTIVE_LANG] = lang;
2378            this.fire("intl:langChange", {module: module, prevVal: currLang, newVal: (lang === ROOT_LANG) ? "" : lang});
2379        }
2380
2381        return exists;
2382    },
2383
2384    /**
2385     * Get the currently active language for the given module.
2386     *
2387     * @method getLang
2388     *
2389     * @param {String} module The module name.
2390     * @return {String} The BCP 47 language tag.
2391     */
2392    getLang : function(module) {
2393        var lang = this._mod(module)[ACTIVE_LANG];
2394        return (lang === ROOT_LANG) ? "" : lang;
2395    },
2396
2397    /**
2398     * Register a hash of localized resources for the given module and language
2399     *
2400     * @method add
2401     *
2402     * @param {String} module The module name.
2403     * @param {String} lang The BCP 47 language tag.
2404     * @param {Object} strings The hash of localized values, keyed by the string name.
2405     */
2406    add : function(module, lang, strings) {
2407        lang = lang || ROOT_LANG;
2408        this._mod(module)[lang] = strings;
2409        this.setLang(module, lang);
2410    },
2411
2412    /**
2413     * Gets the module's localized resources for the currently active language (as provided by the <a href="#method_getLang">getLang</a> method).
2414     * <p>
2415     * Optionally, the localized resources for alternate languages which have been added to Intl (see the <a href="#method_add">add</a> method) can
2416     * be retrieved by providing the BCP 47 language tag as the lang parameter.
2417     * </p>
2418     * @method get
2419     *
2420     * @param {String} module The module name.
2421     * @param {String} key Optional. A single resource key. If not provided, returns a copy (shallow clone) of all resources.
2422     * @param {String} lang Optional. The BCP 47 language tag. If not provided, the module's currently active language is used.
2423     * @return String | Object A copy of the module's localized resources, or a single value if key is provided.
2424     */
2425    get : function(module, key, lang) {
2426        var mod = this._mod(module),
2427            strs;
2428
2429        lang = lang || mod[ACTIVE_LANG];
2430        strs = mod[lang] || {};
2431
2432        return (key) ? strs[key] : Y.merge(strs);
2433    },
2434
2435    /**
2436     * Gets the list of languages for which localized resources are available for a given module, based on the module
2437     * meta-data (part of loader). If loader is not on the page, returns an empty array.
2438     *
2439     * @method getAvailableLangs
2440     * @param {String} module The name of the module
2441     * @return {Array} The array of languages available.
2442     */
2443    getAvailableLangs : function(module) {
2444        var loader = Y.Env._loader,
2445            mod = loader && loader.moduleInfo[module],
2446            langs = mod && mod.lang;
2447        return (langs) ? langs.concat() : NONE;
2448
2449    }
2450});
2451
2452Y.augment(Y.Intl, Y.EventTarget);
2453
2454/**
2455 * Notification event to indicate when the lang for a module has changed. There is no default behavior associated with this event,
2456 * so the on and after moments are equivalent.
2457 *
2458 * @event intl:langChange
2459 * @param {EventFacade} e The event facade
2460 * <p>The event facade contains:</p>
2461 * <dl>
2462 *     <dt>module</dt><dd>The name of the module for which the language changed</dd>
2463 *     <dt>newVal</dt><dd>The new language tag</dd>
2464 *     <dt>prevVal</dt><dd>The current language tag</dd>
2465 * </dl>
2466 */
2467Y.Intl.publish("intl:langChange", {emitFacade:true});
2468
2469
2470}, 'patched-v3.18.3', {"requires": ["intl-base", "event-custom"]});
2471
2472YUI.add('io-base', function (Y, NAME) {
2473
2474/**
2475Base IO functionality. Provides basic XHR transport support.
2476
2477@module io
2478@submodule io-base
2479@for IO
2480**/
2481
2482var // List of events that comprise the IO event lifecycle.
2483    EVENTS = ['start', 'complete', 'end', 'success', 'failure', 'progress'],
2484
2485    // Whitelist of used XHR response object properties.
2486    XHR_PROPS = ['status', 'statusText', 'responseText', 'responseXML'],
2487
2488    win = Y.config.win,
2489    uid = 0;
2490
2491/**
2492The IO class is a utility that brokers HTTP requests through a simplified
2493interface.  Specifically, it allows JavaScript to make HTTP requests to
2494a resource without a page reload.  The underlying transport for making
2495same-domain requests is the XMLHttpRequest object.  IO can also use
2496Flash, if specified as a transport, for cross-domain requests.
2497
2498@class IO
2499@constructor
2500@param {Object} config Object of EventTarget's publish method configurations
2501                    used to configure IO's events.
2502
2503IO can be called statically using {{#crossLink "YUI/io:method"}}YUI.io{{/crossLink}}.
2504**/
2505function IO (config) {
2506    var io = this;
2507
2508    io._uid = 'io:' + uid++;
2509    io._init(config);
2510    Y.io._map[io._uid] = io;
2511}
2512
2513IO.prototype = {
2514    //--------------------------------------
2515    //  Properties
2516    //--------------------------------------
2517
2518   /**
2519    * A counter that increments for each transaction.
2520    *
2521    * @property _id
2522    * @private
2523    * @type {Number}
2524    */
2525    _id: 0,
2526
2527   /**
2528    * Object of IO HTTP headers sent with each transaction.
2529    *
2530    * @property _headers
2531    * @private
2532    * @type {Object}
2533    */
2534    _headers: {
2535        'X-Requested-With' : 'XMLHttpRequest'
2536    },
2537
2538   /**
2539    * Object that stores timeout values for any transaction with a defined
2540    * "timeout" configuration property.
2541    *
2542    * @property _timeout
2543    * @private
2544    * @type {Object}
2545    */
2546    _timeout: {},
2547
2548    //--------------------------------------
2549    //  Methods
2550    //--------------------------------------
2551
2552    _init: function(config) {
2553        var io = this, i, len;
2554
2555        io.cfg = config || {};
2556
2557        Y.augment(io, Y.EventTarget);
2558        for (i = 0, len = EVENTS.length; i < len; ++i) {
2559            // Publish IO global events with configurations, if any.
2560            // IO global events are set to broadcast by default.
2561            // These events use the "io:" namespace.
2562            io.publish('io:' + EVENTS[i], Y.merge({ broadcast: 1 }, config));
2563            // Publish IO transaction events with configurations, if
2564            // any.  These events use the "io-trn:" namespace.
2565            io.publish('io-trn:' + EVENTS[i], config);
2566        }
2567    },
2568
2569   /**
2570    * Method that creates a unique transaction object for each request.
2571    *
2572    * @method _create
2573    * @private
2574    * @param {Object} cfg Configuration object subset to determine if
2575    *                 the transaction is an XDR or file upload,
2576    *                 requiring an alternate transport.
2577    * @param {Number} id Transaction id
2578    * @return {Object} The transaction object
2579    */
2580    _create: function(config, id) {
2581        var io = this,
2582            transaction = {
2583                id : Y.Lang.isNumber(id) ? id : io._id++,
2584                uid: io._uid
2585            },
2586            alt = config.xdr ? config.xdr.use : null,
2587            form = config.form && config.form.upload ? 'iframe' : null,
2588            use;
2589
2590        if (alt === 'native') {
2591            // Non-IE and IE >= 10  can use XHR level 2 and not rely on an
2592            // external transport.
2593            alt = Y.UA.ie && !SUPPORTS_CORS ? 'xdr' : null;
2594
2595            // Prevent "pre-flight" OPTIONS request by removing the
2596            // `X-Requested-With` HTTP header from CORS requests. This header
2597            // can be added back on a per-request basis, if desired.
2598            io.setHeader('X-Requested-With');
2599        }
2600
2601        use = alt || form;
2602        transaction = use ? Y.merge(Y.IO.customTransport(use), transaction) :
2603                            Y.merge(Y.IO.defaultTransport(), transaction);
2604
2605        if (transaction.notify) {
2606            config.notify = function (e, t, c) { io.notify(e, t, c); };
2607        }
2608
2609        if (!use) {
2610            if (win && win.FormData && config.data instanceof win.FormData) {
2611                transaction.c.upload.onprogress = function (e) {
2612                    io.progress(transaction, e, config);
2613                };
2614                transaction.c.onload = function (e) {
2615                    io.load(transaction, e, config);
2616                };
2617                transaction.c.onerror = function (e) {
2618                    io.error(transaction, e, config);
2619                };
2620                transaction.upload = true;
2621            }
2622        }
2623
2624        return transaction;
2625    },
2626
2627    _destroy: function(transaction) {
2628        if (win && !transaction.notify && !transaction.xdr) {
2629            if (XHR && !transaction.upload) {
2630                transaction.c.onreadystatechange = null;
2631            } else if (transaction.upload) {
2632                transaction.c.upload.onprogress = null;
2633                transaction.c.onload = null;
2634                transaction.c.onerror = null;
2635            } else if (Y.UA.ie && !transaction.e) {
2636                // IE, when using XMLHttpRequest as an ActiveX Object, will throw
2637                // a "Type Mismatch" error if the event handler is set to "null".
2638                transaction.c.abort();
2639            }
2640        }
2641
2642        transaction = transaction.c = null;
2643    },
2644
2645   /**
2646    * Method for creating and firing events.
2647    *
2648    * @method _evt
2649    * @private
2650    * @param {String} eventName Event to be published.
2651    * @param {Object} transaction Transaction object.
2652    * @param {Object} config Configuration data subset for event subscription.
2653    */
2654    _evt: function(eventName, transaction, config) {
2655        var io          = this, params,
2656            args        = config['arguments'],
2657            emitFacade  = io.cfg.emitFacade,
2658            globalEvent = "io:" + eventName,
2659            trnEvent    = "io-trn:" + eventName;
2660
2661        // Workaround for #2532107
2662        this.detach(trnEvent);
2663
2664        if (transaction.e) {
2665            transaction.c = { status: 0, statusText: transaction.e };
2666        }
2667
2668        // Fire event with parameters or an Event Facade.
2669        params = [ emitFacade ?
2670            {
2671                id: transaction.id,
2672                data: transaction.c,
2673                cfg: config,
2674                'arguments': args
2675            } :
2676            transaction.id
2677        ];
2678
2679        if (!emitFacade) {
2680            if (eventName === EVENTS[0] || eventName === EVENTS[2]) {
2681                if (args) {
2682                    params.push(args);
2683                }
2684            } else {
2685                if (transaction.evt) {
2686                    params.push(transaction.evt);
2687                } else {
2688                    params.push(transaction.c);
2689                }
2690                if (args) {
2691                    params.push(args);
2692                }
2693            }
2694        }
2695
2696        params.unshift(globalEvent);
2697        // Fire global events.
2698        io.fire.apply(io, params);
2699        // Fire transaction events, if receivers are defined.
2700        if (config.on) {
2701            params[0] = trnEvent;
2702            io.once(trnEvent, config.on[eventName], config.context || Y);
2703            io.fire.apply(io, params);
2704        }
2705    },
2706
2707   /**
2708    * Fires event "io:start" and creates, fires a transaction-specific
2709    * start event, if `config.on.start` is defined.
2710    *
2711    * @method start
2712    * @param {Object} transaction Transaction object.
2713    * @param {Object} config Configuration object for the transaction.
2714    */
2715    start: function(transaction, config) {
2716       /**
2717        * Signals the start of an IO request.
2718        * @event io:start
2719        */
2720        this._evt(EVENTS[0], transaction, config);
2721    },
2722
2723   /**
2724    * Fires event "io:complete" and creates, fires a
2725    * transaction-specific "complete" event, if config.on.complete is
2726    * defined.
2727    *
2728    * @method complete
2729    * @param {Object} transaction Transaction object.
2730    * @param {Object} config Configuration object for the transaction.
2731    */
2732    complete: function(transaction, config) {
2733       /**
2734        * Signals the completion of the request-response phase of a
2735        * transaction. Response status and data are accessible, if
2736        * available, in this event.
2737        * @event io:complete
2738        */
2739        this._evt(EVENTS[1], transaction, config);
2740    },
2741
2742   /**
2743    * Fires event "io:end" and creates, fires a transaction-specific "end"
2744    * event, if config.on.end is defined.
2745    *
2746    * @method end
2747    * @param {Object} transaction Transaction object.
2748    * @param {Object} config Configuration object for the transaction.
2749    */
2750    end: function(transaction, config) {
2751       /**
2752        * Signals the end of the transaction lifecycle.
2753        * @event io:end
2754        */
2755        this._evt(EVENTS[2], transaction, config);
2756        this._destroy(transaction);
2757    },
2758
2759   /**
2760    * Fires event "io:success" and creates, fires a transaction-specific
2761    * "success" event, if config.on.success is defined.
2762    *
2763    * @method success
2764    * @param {Object} transaction Transaction object.
2765    * @param {Object} config Configuration object for the transaction.
2766    */
2767    success: function(transaction, config) {
2768       /**
2769        * Signals an HTTP response with status in the 2xx range.
2770        * Fires after io:complete.
2771        * @event io:success
2772        */
2773        this._evt(EVENTS[3], transaction, config);
2774        this.end(transaction, config);
2775    },
2776
2777   /**
2778    * Fires event "io:failure" and creates, fires a transaction-specific
2779    * "failure" event, if config.on.failure is defined.
2780    *
2781    * @method failure
2782    * @param {Object} transaction Transaction object.
2783    * @param {Object} config Configuration object for the transaction.
2784    */
2785    failure: function(transaction, config) {
2786       /**
2787        * Signals an HTTP response with status outside of the 2xx range.
2788        * Fires after io:complete.
2789        * @event io:failure
2790        */
2791        this._evt(EVENTS[4], transaction, config);
2792        this.end(transaction, config);
2793    },
2794
2795   /**
2796    * Fires event "io:progress" and creates, fires a transaction-specific
2797    * "progress" event -- for XMLHttpRequest file upload -- if
2798    * config.on.progress is defined.
2799    *
2800    * @method progress
2801    * @param {Object} transaction Transaction object.
2802    * @param {Object} progress event.
2803    * @param {Object} config Configuration object for the transaction.
2804    */
2805    progress: function(transaction, e, config) {
2806       /**
2807        * Signals the interactive state during a file upload transaction.
2808        * This event fires after io:start and before io:complete.
2809        * @event io:progress
2810        */
2811        transaction.evt = e;
2812        this._evt(EVENTS[5], transaction, config);
2813    },
2814
2815   /**
2816    * Fires event "io:complete" and creates, fires a transaction-specific
2817    * "complete" event -- for XMLHttpRequest file upload -- if
2818    * config.on.complete is defined.
2819    *
2820    * @method load
2821    * @param {Object} transaction Transaction object.
2822    * @param {Object} load event.
2823    * @param {Object} config Configuration object for the transaction.
2824    */
2825    load: function (transaction, e, config) {
2826        transaction.evt = e.target;
2827        this._evt(EVENTS[1], transaction, config);
2828    },
2829
2830   /**
2831    * Fires event "io:failure" and creates, fires a transaction-specific
2832    * "failure" event -- for XMLHttpRequest file upload -- if
2833    * config.on.failure is defined.
2834    *
2835    * @method error
2836    * @param {Object} transaction Transaction object.
2837    * @param {Object} error event.
2838    * @param {Object} config Configuration object for the transaction.
2839    */
2840    error: function (transaction, e, config) {
2841        transaction.evt = e;
2842        this._evt(EVENTS[4], transaction, config);
2843    },
2844
2845   /**
2846    * Retry an XDR transaction, using the Flash tranport, if the native
2847    * transport fails.
2848    *
2849    * @method _retry
2850    * @private
2851    * @param {Object} transaction Transaction object.
2852    * @param {String} uri Qualified path to transaction resource.
2853    * @param {Object} config Configuration object for the transaction.
2854    */
2855    _retry: function(transaction, uri, config) {
2856        this._destroy(transaction);
2857        config.xdr.use = 'flash';
2858        return this.send(uri, config, transaction.id);
2859    },
2860
2861   /**
2862    * Method that concatenates string data for HTTP GET transactions.
2863    *
2864    * @method _concat
2865    * @private
2866    * @param {String} uri URI or root data.
2867    * @param {String} data Data to be concatenated onto URI.
2868    * @return {String}
2869    */
2870    _concat: function(uri, data) {
2871        uri += (uri.indexOf('?') === -1 ? '?' : '&') + data;
2872        return uri;
2873    },
2874
2875   /**
2876    * Stores default client headers for all transactions. If a label is
2877    * passed with no value argument, the header will be deleted.
2878    *
2879    * @method setHeader
2880    * @param {String} name HTTP header
2881    * @param {String} value HTTP header value
2882    */
2883    setHeader: function(name, value) {
2884        if (value) {
2885            this._headers[name] = value;
2886        } else {
2887            delete this._headers[name];
2888        }
2889    },
2890
2891   /**
2892    * Method that sets all HTTP headers to be sent in a transaction.
2893    *
2894    * @method _setHeaders
2895    * @private
2896    * @param {Object} transaction - XHR instance for the specific transaction.
2897    * @param {Object} headers - HTTP headers for the specific transaction, as
2898    *                    defined in the configuration object passed to YUI.io().
2899    */
2900    _setHeaders: function(transaction, headers) {
2901        headers = Y.merge(this._headers, headers);
2902        Y.Object.each(headers, function(value, name) {
2903            if (value !== 'disable') {
2904                transaction.setRequestHeader(name, headers[name]);
2905            }
2906        });
2907    },
2908
2909   /**
2910    * Starts timeout count if the configuration object has a defined
2911    * timeout property.
2912    *
2913    * @method _startTimeout
2914    * @private
2915    * @param {Object} transaction Transaction object generated by _create().
2916    * @param {Object} timeout Timeout in milliseconds.
2917    */
2918    _startTimeout: function(transaction, timeout) {
2919        var io = this;
2920
2921        io._timeout[transaction.id] = setTimeout(function() {
2922            io._abort(transaction, 'timeout');
2923        }, timeout);
2924    },
2925
2926   /**
2927    * Clears the timeout interval started by _startTimeout().
2928    *
2929    * @method _clearTimeout
2930    * @private
2931    * @param {Number} id - Transaction id.
2932    */
2933    _clearTimeout: function(id) {
2934        clearTimeout(this._timeout[id]);
2935        delete this._timeout[id];
2936    },
2937
2938   /**
2939    * Method that determines if a transaction response qualifies as success
2940    * or failure, based on the response HTTP status code, and fires the
2941    * appropriate success or failure events.
2942    *
2943    * @method _result
2944    * @private
2945    * @static
2946    * @param {Object} transaction Transaction object generated by _create().
2947    * @param {Object} config Configuration object passed to io().
2948    */
2949    _result: function(transaction, config) {
2950        var status;
2951        // Firefox will throw an exception if attempting to access
2952        // an XHR object's status property, after a request is aborted.
2953        try {
2954            status = transaction.c.status;
2955        } catch(e) {
2956            status = 0;
2957        }
2958
2959        // IE reports HTTP 204 as HTTP 1223.
2960        if (status >= 200 && status < 300 || status === 304 || status === 1223) {
2961            this.success(transaction, config);
2962        } else {
2963            this.failure(transaction, config);
2964        }
2965    },
2966
2967   /**
2968    * Event handler bound to onreadystatechange.
2969    *
2970    * @method _rS
2971    * @private
2972    * @param {Object} transaction Transaction object generated by _create().
2973    * @param {Object} config Configuration object passed to YUI.io().
2974    */
2975    _rS: function(transaction, config) {
2976        var io = this;
2977
2978        if (transaction.c.readyState === 4) {
2979            if (config.timeout) {
2980                io._clearTimeout(transaction.id);
2981            }
2982
2983            // Yield in the event of request timeout or abort.
2984            setTimeout(function() {
2985                io.complete(transaction, config);
2986                io._result(transaction, config);
2987            }, 0);
2988        }
2989    },
2990
2991   /**
2992    * Terminates a transaction due to an explicit abort or timeout.
2993    *
2994    * @method _abort
2995    * @private
2996    * @param {Object} transaction Transaction object generated by _create().
2997    * @param {String} type Identifies timed out or aborted transaction.
2998    */
2999    _abort: function(transaction, type) {
3000        if (transaction && transaction.c) {
3001            transaction.e = type;
3002            transaction.c.abort();
3003        }
3004    },
3005
3006   /**
3007    * Requests a transaction. `send()` is implemented as `Y.io()`.  Each
3008    * transaction may include a configuration object.  Its properties are:
3009    *
3010    * <dl>
3011    *   <dt>method</dt>
3012    *     <dd>HTTP method verb (e.g., GET or POST). If this property is not
3013    *         not defined, the default value will be GET.</dd>
3014    *
3015    *   <dt>data</dt>
3016    *     <dd>This is the name-value string that will be sent as the
3017    *     transaction data. If the request is HTTP GET, the data become
3018    *     part of querystring. If HTTP POST, the data are sent in the
3019    *     message body.</dd>
3020    *
3021    *   <dt>xdr</dt>
3022    *     <dd>Defines the transport to be used for cross-domain requests.
3023    *     By setting this property, the transaction will use the specified
3024    *     transport instead of XMLHttpRequest. The properties of the
3025    *     transport object are:
3026    *     <dl>
3027    *       <dt>use</dt>
3028    *         <dd>The transport to be used: 'flash' or 'native'</dd>
3029    *       <dt>dataType</dt>
3030    *         <dd>Set the value to 'XML' if that is the expected response
3031    *         content type.</dd>
3032    *       <dt>credentials</dt>
3033    *         <dd>Set the value to 'true' to set XHR.withCredentials property to true.</dd>
3034    *     </dl></dd>
3035    *
3036    *   <dt>form</dt>
3037    *     <dd>Form serialization configuration object.  Its properties are:
3038    *     <dl>
3039    *       <dt>id</dt>
3040    *         <dd>Node object or id of HTML form</dd>
3041    *       <dt>useDisabled</dt>
3042    *         <dd>`true` to also serialize disabled form field values
3043    *         (defaults to `false`)</dd>
3044    *     </dl></dd>
3045    *
3046    *   <dt>on</dt>
3047    *     <dd>Assigns transaction event subscriptions. Available events are:
3048    *     <dl>
3049    *       <dt>start</dt>
3050    *         <dd>Fires when a request is sent to a resource.</dd>
3051    *       <dt>complete</dt>
3052    *         <dd>Fires when the transaction is complete.</dd>
3053    *       <dt>success</dt>
3054    *         <dd>Fires when the HTTP response status is within the 2xx
3055    *         range.</dd>
3056    *       <dt>failure</dt>
3057    *         <dd>Fires when the HTTP response status is outside the 2xx
3058    *         range, if an exception occurs, if the transation is aborted,
3059    *         or if the transaction exceeds a configured `timeout`.</dd>
3060    *       <dt>end</dt>
3061    *         <dd>Fires at the conclusion of the transaction
3062    *            lifecycle, after `success` or `failure`.</dd>
3063    *     </dl>
3064    *
3065    *     <p>Callback functions for `start` and `end` receive the id of the
3066    *     transaction as a first argument. For `complete`, `success`, and
3067    *     `failure`, callbacks receive the id and the response object
3068    *     (usually the XMLHttpRequest instance).  If the `arguments`
3069    *     property was included in the configuration object passed to
3070    *     `Y.io()`, the configured data will be passed to all callbacks as
3071    *     the last argument.</p>
3072    *     </dd>
3073    *
3074    *   <dt>sync</dt>
3075    *     <dd>Pass `true` to make a same-domain transaction synchronous.
3076    *     <strong>CAVEAT</strong>: This will negatively impact the user
3077    *     experience. Have a <em>very</em> good reason if you intend to use
3078    *     this.</dd>
3079    *
3080    *   <dt>context</dt>
3081    *     <dd>The "`this'" object for all configured event handlers. If a
3082    *     specific context is needed for individual callbacks, bind the
3083    *     callback to a context using `Y.bind()`.</dd>
3084    *
3085    *   <dt>headers</dt>
3086    *     <dd>Object map of transaction headers to send to the server. The
3087    *     object keys are the header names and the values are the header
3088    *     values.</dd>
3089    *
3090    *   <dt>username</dt>
3091    *     <dd>Username to use in a HTTP authentication.</dd>
3092    *
3093    *   <dt>password</dt>
3094    *     <dd>Password to use in a HTTP authentication.</dd>
3095    *
3096    *   <dt>timeout</dt>
3097    *     <dd>Millisecond threshold for the transaction before being
3098    *     automatically aborted.</dd>
3099    *
3100    *   <dt>arguments</dt>
3101    *     <dd>User-defined data passed to all registered event handlers.
3102    *     This value is available as the second argument in the "start" and
3103    *     "end" event handlers. It is the third argument in the "complete",
3104    *     "success", and "failure" event handlers. <strong>Be sure to quote
3105    *     this property name in the transaction configuration as
3106    *     "arguments" is a reserved word in JavaScript</strong> (e.g.
3107    *     `Y.io({ ..., "arguments": stuff })`).</dd>
3108    * </dl>
3109    *
3110    * @method send
3111    * @public
3112    * @param {String} uri Qualified path to transaction resource.
3113    * @param {Object} config Configuration object for the transaction.
3114    * @param {Number} id Transaction id, if already set.
3115    * @return {Object}
3115 An object containing:
3116    * <dl>
3117    *  <dt>`id`</dt>
3118    *  <dd>
3119    *    The transaction ID for this request.
3120    *  </dd>
3121    *  <dt>`abort`</dt>
3122    *  <dd>
3123    *    A function to abort the current transaction.
3124    *  </dd>
3125    *  <dt>`isInProgress`</dt>
3126    *  <dd>
3127    *    A helper to determine whether the current transaction is in progress.
3128    *  </dd>
3129    *  <dt>`io`</dt>
3130    *  <dd>
3131    *    A reference to the IO object for this transaction.
3132    *  </dd>
3133    * </dl>
3134    */
3135    send: function(uri, config, id) {
3136        var transaction, method, i, len, sync, data,
3137            io = this,
3138            u = uri,
3139            response = {};
3140
3141        config = config ? Y.Object(config) : {};
3142        transaction = io._create(config, id);
3143        method = config.method ? config.method.toUpperCase() : 'GET';
3144        sync = config.sync;
3145        data = config.data;
3146
3147        // Serialize a map object into a key-value string using
3148        // querystring-stringify-simple.
3149        if ((Y.Lang.isObject(data) && !data.nodeType) && !transaction.upload) {
3150            if (Y.QueryString && Y.QueryString.stringify) {
3151                config.data = data = Y.QueryString.stringify(data);
3152            } else {
3153            }
3154        }
3155
3156        if (config.form) {
3157            if (config.form.upload) {
3158                // This is a file upload transaction, calling
3159                // upload() in io-upload-iframe.
3160                return io.upload(transaction, uri, config);
3161            } else {
3162                // Serialize HTML form data into a key-value string.
3163                data = io._serialize(config.form, data);
3164            }
3165        }
3166
3167        // Convert falsy values to an empty string. This way IE can't be
3168        // rediculous and translate `undefined` to "undefined".
3169        data || (data = '');
3170
3171        if (data) {
3172            switch (method) {
3173                case 'GET':
3174                case 'HEAD':
3175                case 'DELETE':
3176                    u = io._concat(u, data);
3177                    data = '';
3178                    break;
3179                case 'POST':
3180                case 'PUT':
3181                    // If Content-Type is defined in the configuration object, or
3182                    // or as a default header, it will be used instead of
3183                    // 'application/x-www-form-urlencoded; charset=UTF-8'
3184                    config.headers = Y.merge({
3185                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
3186                    }, config.headers);
3187                    break;
3188            }
3189        }
3190
3191        if (transaction.xdr) {
3192            // Route data to io-xdr module for flash and XDomainRequest.
3193            return io.xdr(u, transaction, config);
3194        }
3195        else if (transaction.notify) {
3196            // Route data to custom transport
3197            return transaction.c.send(transaction, uri, config);
3198        }
3199
3200        if (!sync && !transaction.upload) {
3201            transaction.c.onreadystatechange = function() {
3202                io._rS(transaction, config);
3203            };
3204        }
3205
3206        try {
3207            // Determine if request is to be set as
3208            // synchronous or asynchronous.
3209            transaction.c.open(method, u, !sync, config.username || null, config.password || null);
3210            io._setHeaders(transaction.c, config.headers || {});
3211            io.start(transaction, config);
3212
3213            // Will work only in browsers that implement the
3214            // Cross-Origin Resource Sharing draft.
3215            if (config.xdr && config.xdr.credentials && SUPPORTS_CORS) {
3216                transaction.c.withCredentials = true;
3217            }
3218
3219            // Using "null" with HTTP POST will result in a request
3220            // with no Content-Length header defined.
3221            transaction.c.send(data);
3222
3223            if (sync) {
3224                // Create a response object for synchronous transactions,
3225                // mixing id and arguments properties with the xhr
3226                // properties whitelist.
3227                for (i = 0, len = XHR_PROPS.length; i < len; ++i) {
3228                    response[XHR_PROPS[i]] = transaction.c[XHR_PROPS[i]];
3229                }
3230
3231                response.getAllResponseHeaders = function() {
3232                    return transaction.c.getAllResponseHeaders();
3233                };
3234
3235                response.getResponseHeader = function(name) {
3236                    return transaction.c.getResponseHeader(name);
3237                };
3238
3239                io.complete(transaction, config);
3240                io._result(transaction, config);
3241
3242                return response;
3243            }
3244        } catch(e) {
3245            if (transaction.xdr) {
3246                // This exception is usually thrown by browsers
3247                // that do not support XMLHttpRequest Level 2.
3248                // Retry the request with the XDR transport set
3249                // to 'flash'.  If the Flash transport is not
3250                // initialized or available, the transaction
3251                // will resolve to a transport error.
3252                return io._retry(transaction, uri, config);
3253            } else {
3254                io.complete(transaction, config);
3255                io._result(transaction, config);
3256            }
3257        }
3258
3259        // If config.timeout is defined, and the request is standard XHR,
3260        // initialize timeout polling.
3261        if (config.timeout) {
3262            io._startTimeout(transaction, config.timeout);
3263        }
3264
3265        return {
3266            id: transaction.id,
3267            abort: function() {
3268                return transaction.c ? io._abort(transaction, 'abort') : false;
3269            },
3270            isInProgress: function() {
3271                return transaction.c ? (transaction.c.readyState % 4) : false;
3272            },
3273            io: io
3274        };
3275    }
3276};
3277
3278/**
3279Method for initiating an ajax call.  The first argument is the url end
3280point for the call.  The second argument is an object to configure the
3281transaction and attach event subscriptions.  The configuration object
3282supports the following properties:
3283
3284<dl>
3285  <dt>method</dt>
3286    <dd>HTTP method verb (e.g., GET or POST). If this property is not
3287        not defined, the default value will be GET.</dd>
3288
3289  <dt>data</dt>
3290    <dd>This is the name-value string that will be sent as the
3291    transaction data. If the request is HTTP GET, the data become
3292    part of querystring. If HTTP POST, the data are sent in the
3293    message body.</dd>
3294
3295  <dt>xdr</dt>
3296    <dd>Defines the transport to be used for cross-domain requests.
3297    By setting this property, the transaction will use the specified
3298    transport instead of XMLHttpRequest. The properties of the
3299    transport object are:
3300    <dl>
3301      <dt>use</dt>
3302        <dd>The transport to be used: 'flash' or 'native'</dd>
3303      <dt>dataType</dt>
3304        <dd>Set the value to 'XML' if that is the expected response
3305        content type.</dd>
3306    </dl></dd>
3307
3308  <dt>form</dt>
3309    <dd>Form serialization configuration object.  Its properties are:
3310    <dl>
3311      <dt>id</dt>
3312        <dd>Node object or id of HTML form</dd>
3313      <dt>useDisabled</dt>
3314        <dd>`true` to also serialize disabled form field values
3315        (defaults to `false`)</dd>
3316    </dl></dd>
3317
3318  <dt>on</dt>
3319    <dd>Assigns transaction event subscriptions. Available events are:
3320    <dl>
3321      <dt>start</dt>
3322        <dd>Fires when a request is sent to a resource.</dd>
3323      <dt>complete</dt>
3324        <dd>Fires when the transaction is complete.</dd>
3325      <dt>success</dt>
3326        <dd>Fires when the HTTP response status is within the 2xx
3327        range.</dd>
3328      <dt>failure</dt>
3329        <dd>Fires when the HTTP response status is outside the 2xx
3330        range, if an exception occurs, if the transation is aborted,
3331        or if the transaction exceeds a configured `timeout`.</dd>
3332      <dt>end</dt>
3333        <dd>Fires at the conclusion of the transaction
3334           lifecycle, after `success` or `failure`.</dd>
3335    </dl>
3336
3337    <p>Callback functions for `start` and `end` receive the id of the
3338    transaction as a first argument. For `complete`, `success`, and
3339    `failure`, callbacks receive the id and the response object
3340    (usually the XMLHttpRequest instance).  If the `arguments`
3341    property was included in the configuration object passed to
3342    `Y.io()`, the configured data will be passed to all callbacks as
3343    the last argument.</p>
3344    </dd>
3345
3346  <dt>sync</dt>
3347    <dd>Pass `true` to make a same-domain transaction synchronous.
3348    <strong>CAVEAT</strong>: This will negatively impact the user
3349    experience. Have a <em>very</em> good reason if you intend to use
3350    this.</dd>
3351
3352  <dt>context</dt>
3353    <dd>The "`this'" object for all configured event handlers. If a
3354    specific context is needed for individual callbacks, bind the
3355    callback to a context using `Y.bind()`.</dd>
3356
3357  <dt>headers</dt>
3358    <dd>Object map of transaction headers to send to the server. The
3359    object keys are the header names and the values are the header
3360    values.</dd>
3361
3362  <dt>timeout</dt>
3363    <dd>Millisecond threshold for the transaction before being
3364    automatically aborted.</dd>
3365
3366  <dt>arguments</dt>
3367    <dd>User-defined data passed to all registered event handlers.
3368    This value is available as the second argument in the "start" and
3369    "end" event handlers. It is the third argument in the "complete",
3370    "success", and "failure" event handlers. <strong>Be sure to quote
3371    this property name in the transaction configuration as
3372    "arguments" is a reserved word in JavaScript</strong> (e.g.
3373    `Y.io({ ..., "arguments": stuff })`).</dd>
3374</dl>
3375
3376@method io
3377@static
3378@param {String} url qualified path to transaction resource.
3379@param {Object} config configuration object for the transaction.
3380@return {Object} An object containing:
3381<dl>
3382 <dt>`id`</dt>
3383 <dd>
3384   The transaction ID for this request.
3385 </dd>
3386 <dt>`abort`</dt>
3387 <dd>
3388   A function to abort the current transaction.
3389 </dd>
3390 <dt>`isInProgress`</dt>
3391 <dd>
3392   A helper to determine whether the current transaction is in progress.
3393 </dd>
3394 <dt>`io`</dt>
3395 <dd>
3396   A reference to the IO object for this transaction.
3397 </dd>
3398</dl>
3399
3400@for YUI
3401**/
3402Y.io = function(url, config) {
3403    // Calling IO through the static interface will use and reuse
3404    // an instance of IO.
3405    var transaction = Y.io._map['io:0'] || new IO();
3406    return transaction.send.apply(transaction, [url, config]);
3407};
3408
3409/**
3410Method for setting and deleting IO HTTP headers to be sent with every
3411request.
3412
3413Hosted as a property on the `io` function (e.g. `Y.io.header`).
3414
3415@method header
3416@param {String} name HTTP header
3417@param {String} value HTTP header value
3418@static
3419**/
3420Y.io.header = function(name, value) {
3421    // Calling IO through the static interface will use and reuse
3422    // an instance of IO.
3423    var transaction = Y.io._map['io:0'] || new IO();
3424    transaction.setHeader(name, value);
3425};
3426
3427Y.IO = IO;
3428// Map of all IO instances created.
3429Y.io._map = {};
3430var XHR = win && win.XMLHttpRequest,
3431    XDR = win && win.XDomainRequest,
3432    AX = win && win.ActiveXObject,
3433
3434    // Checks for the presence of the `withCredentials` in an XHR instance
3435    // object, which will be present if the environment supports CORS.
3436    SUPPORTS_CORS = XHR && 'withCredentials' in (new XMLHttpRequest());
3437
3438
3439Y.mix(Y.IO, {
3440    /**
3441    * The ID of the default IO transport, defaults to `xhr`
3442    * @property _default
3443    * @type {String}
3444    * @static
3445    */
3446    _default: 'xhr',
3447    /**
3448    *
3449    * @method defaultTransport
3450    * @static
3451    * @param {String} [id] The transport to set as the default, if empty a new transport is created.
3452    * @return {Object} The transport object with a `send` method
3453    */
3454    defaultTransport: function(id) {
3455        if (id) {
3456            Y.IO._default = id;
3457        } else {
3458            var o = {
3459                c: Y.IO.transports[Y.IO._default](),
3460                notify: Y.IO._default === 'xhr' ? false : true
3461            };
3462            return o;
3463        }
3464    },
3465    /**
3466    * An object hash of custom transports available to IO
3467    * @property transports
3468    * @type {Object}
3469    * @static
3470    */
3471    transports: {
3472        xhr: function () {
3473            return XHR ? new XMLHttpRequest() :
3474                AX ? new ActiveXObject('Microsoft.XMLHTTP') : null;
3475        },
3476        xdr: function () {
3477            return XDR ? new XDomainRequest() : null;
3478        },
3479        iframe: function () { return {}; },
3480        flash: null,
3481        nodejs: null
3482    },
3483    /**
3484    * Create a custom transport of type and return it's object
3485    * @method customTransport
3486    * @param {String} id The id of the transport to create.
3487    * @static
3488    */
3489    customTransport: function(id) {
3490        var o = { c: Y.IO.transports[id]() };
3491
3492        o[(id === 'xdr' || id === 'flash') ? 'xdr' : 'notify'] = true;
3493        return o;
3494    }
3495});
3496
3497Y.mix(Y.IO.prototype, {
3498    /**
3499    * Fired from the notify method of the transport which in turn fires
3500    * the event on the IO object.
3501    * @method notify
3502    * @param {String} event The name of the event
3503    * @param {Object} transaction The transaction object
3504    * @param {Object} config The configuration object for this transaction
3505    */
3506    notify: function(event, transaction, config) {
3507        var io = this;
3508
3509        switch (event) {
3510            case 'timeout':
3511            case 'abort':
3512            case 'transport error':
3513                transaction.c = { status: 0, statusText: event };
3514                event = 'failure';
3515            default:
3516                io[event].apply(io, [transaction, config]);
3517        }
3518    }
3519});
3520
3521
3522
3523
3524}, 'patched-v3.18.3', {"requires": ["event-custom-base", "querystring-stringify-simple"]});
3525
3526YUI.add('io-form', function (Y, NAME) {
3527
3528/**
3529* Extends IO to enable HTML form data serialization, when specified
3530* in the transaction's configuration object.
3531* @module io
3532* @submodule io-form
3533* @for IO
3534*/
3535
3536var eUC = encodeURIComponent;
3537
3538/**
3539 * Enumerate through an HTML form's elements collection
3540 * and return a string comprised of key-value pairs.
3541 *
3542 * @method stringify
3543 * @static
3544 * @param {Node|String} form YUI form node or HTML form id
3545 * @param {Object} [options] Configuration options.
3546 * @param {Boolean} [options.useDisabled=false] Whether to include disabled fields.
3547 * @param {Object|String} [options.extra] Extra values to include. May be a query string or an object with key/value pairs.
3548 * @return {String}
3549 */
3550Y.IO.stringify = function(form, options) {
3551    options = options || {};
3552
3553    var s = Y.IO.prototype._serialize({
3554        id: form,
3555        useDisabled: options.useDisabled
3556    },
3557    options.extra && typeof options.extra === 'object' ? Y.QueryString.stringify(options.extra) : options.extra);
3558
3559    return s;
3560};
3561
3562Y.mix(Y.IO.prototype, {
3563   /**
3564    * Enumerate through an HTML form's elements collection
3565    * and return a string comprised of key-value pairs.
3566    *
3567    * @method _serialize
3568    * @private
3569    * @param {Object} c
3570    * @param {String|Element} c.id YUI form node or HTML form id
3571    * @param {Boolean} c.useDisabled `true` to include disabled fields
3572    * @param {String} s Key-value data defined in the configuration object.
3573    * @return {String}
3574    */
3575    _serialize: function(c, s) {
3576        var data = [],
3577            df = c.useDisabled || false,
3578            item = 0,
3579            id = (typeof c.id === 'string') ? c.id : c.id.getAttribute('id'),
3580            e, f, n, v, d, i, il, j, jl, o;
3581
3582        if (!id) {
3583            id = Y.guid('io:');
3584            c.id.setAttribute('id', id);
3585        }
3586
3587        f = Y.config.doc.getElementById(id);
3588
3589        if (!f || !f.elements) {
3590            return s || '';
3591        }
3592
3593        // Iterate over the form elements collection to construct the
3594        // label-value pairs.
3595        for (i = 0, il = f.elements.length; i < il; ++i) {
3596            e = f.elements[i];
3597            d = e.disabled;
3598            n = e.name;
3599
3600            if (df ? n : n && !d) {
3601                n = eUC(n) + '=';
3602                v = eUC(e.value);
3603
3604                switch (e.type) {
3605                    // Safari, Opera, FF all default options.value from .text if
3606                    // value attribute not specified in markup
3607                    case 'select-one':
3608                        if (e.selectedIndex > -1) {
3609                            o = e.options[e.selectedIndex];
3610                            data[item++] = n + eUC(o.attributes.value && o.attributes.value.specified ? o.value : o.text);
3611                        }
3612                        break;
3613                    case 'select-multiple':
3614                        if (e.selectedIndex > -1) {
3615                            for (j = e.selectedIndex, jl = e.options.length; j < jl; ++j) {
3616                                o = e.options[j];
3617                                if (o.selected) {
3618                                  data[item++] = n + eUC(o.attributes.value && o.attributes.value.specified ? o.value : o.text);
3619                                }
3620                            }
3621                        }
3622                        break;
3623                    case 'radio':
3624                    case 'checkbox':
3625                        if (e.checked) {
3626                            data[item++] = n + v;
3627                        }
3628                        break;
3629                    case 'file':
3630                        // stub case as XMLHttpRequest will only send the file path as a string.
3631                    case undefined:
3632                        // stub case for fieldset element which returns undefined.
3633                    case 'reset':
3634                        // stub case for input type reset button.
3635                    case 'button':
3636                        // stub case for input type button elements.
3637                        break;
3638                    case 'submit':
3639                    default:
3640                        data[item++] = n + v;
3641                }
3642            }
3643        }
3644
3645        if (s) {
3646            data[item++] = s;
3647        }
3648
3649        return data.join('&');
3650    }
3651}, true);
3652
3653
3654}, 'patched-v3.18.3', {"requires": ["io-base", "node-base"]});
3655
3656YUI.add('io-queue', function (Y, NAME) {
3657
3658/**
3659Extends IO to implement Queue for synchronous
3660transaction processing.
3661@module io
3662@submodule io-queue
3663@for IO
3664**/
3665var io = Y.io._map['io:0'] || new Y.IO();
3666
3667Y.mix(Y.IO.prototype, {
3668   /**
3669    * Array of transactions queued for processing
3670    *
3671    * @property _q
3672    * @private
3673    * @static
3674    * @type {Object}
3675    */
3676    _q: new Y.Queue(),
3677    _qActiveId: null,
3678    _qInit: false,
3679
3680   /**
3681    * Property to determine whether the queue is set to
3682    * 1 (active) or 0 (inactive).  When inactive, transactions
3683    * will be stored in the queue until the queue is set to active.
3684    *
3685    * @property _qState
3686    * @private
3687    * @static
3688    * @type {Number}
3689    */
3690    _qState: 1,
3691
3692   /**
3693    * Method Process the first transaction from the
3694    * queue in FIFO order.
3695    *
3696    * @method _qShift
3697    * @private
3698    * @static
3699    */
3700    _qShift: function() {
3701        var io = this,
3702            o = io._q.next();
3703
3704        io._qActiveId = o.id;
3705        io._qState = 0;
3706        io.send(o.uri, o.cfg, o.id);
3707    },
3708
3709   /**
3710    * Method for queueing a transaction before the request is sent to the
3711    * resource, to ensure sequential processing.
3712    *
3713    * @method queue
3714    * @static
3715    * @return {Object}
3716    */
3717    queue: function(uri, c) {
3718        var io = this,
3719            o = { uri: uri, cfg:c, id: this._id++ };
3720
3721        if(!io._qInit) {
3722            Y.on('io:complete', function(id, o) { io._qNext(id); }, io);
3723            io._qInit = true;
3724        }
3725
3726        io._q.add(o);
3727        if (io._qState === 1) {
3728            io._qShift();
3729        }
3730
3731        return o;
3732    },
3733
3734    _qNext: function(id) {
3735        var io = this;
3736        io._qState = 1;
3737        if (io._qActiveId === id && io._q.size() > 0) {
3738            io._qShift();
3739        }
3740    },
3741
3742   /**
3743    * Method for promoting a transaction to the top of the queue.
3744    *
3745    * @method promote
3746    * @static
3747    */
3748    qPromote: function(o) {
3749        this._q.promote(o);
3750    },
3751
3752   /**
3753    * Method for removing a specific, pending transaction from
3754    * the queue.
3755    *
3756    * @method remove
3757    * @private
3758    * @static
3759    */
3760    qRemove: function(o) {
3761        this._q.remove(o);
3762    },
3763
3764   /**
3765    * Method for cancel all pending transaction from
3766    * the queue.
3767    *
3768    * @method empty
3769    * @static
3770    * @since 3.7.3
3771    */
3772    qEmpty: function() {
3773        this._q = new Y.Queue();
3774    },
3775
3776    qStart: function() {
3777        var io = this;
3778        io._qState = 1;
3779
3780        if (io._q.size() > 0) {
3781            io._qShift();
3782        }
3783    },
3784
3785   /**
3786    * Method for setting queue processing to inactive.
3787    * Transaction requests to YUI.io.queue() will be stored in the queue, but
3788    * not processed until the queue is reset to "active".
3789    *
3790    * @method _stop
3791    * @private
3792    * @static
3793    */
3794    qStop: function() {
3795        this._qState = 0;
3796    },
3797
3798   /**
3799    * Method to query the current size of the queue.
3800    *
3801    * @method _size
3802    * @private
3803    * @static
3804    * @return {Number}
3805    */
3806    qSize: function() {
3807        return this._q.size();
3808    }
3809
3810}, true);
3811
3812function _queue(u, c) {
3813    return io.queue.apply(io, [u, c]);
3814}
3815
3816_queue.start = function () { io.qStart(); };
3817_queue.stop = function () { io.qStop(); };
3818_queue.promote = function (o) { io.qPromote(o); };
3819_queue.remove = function (o) { io.qRemove(o); };
3820_queue.size = function () { io.qSize(); };
3821_queue.empty = function () { io.qEmpty(); };
3822Y.io.queue = _queue;
3823
3824
3825}, 'patched-v3.18.3', {"requires": ["io-base", "queue-promote"]});
3826
3827YUI.add('io-upload-iframe', function (Y, NAME) {
3828
3829/**
3830Extends the IO  to enable file uploads, with HTML forms
3831using an iframe as the transport medium.
3832@module io
3833@submodule io-upload-iframe
3834@for IO
3835**/
3836
3837var w = Y.config.win,
3838    d = Y.config.doc,
3839    _std = (d.documentMode && d.documentMode >= 8),
3840    _d = decodeURIComponent,
3841    _end = Y.IO.prototype.end;
3842
3843/**
3844 * Creates the iframe transported used in file upload
3845 * transactions, and binds the response event handler.
3846 *
3847 * @method _cFrame
3848 * @private
3849 * @param {Object} o Transaction object generated by _create().
3850 * @param {Object} c Configuration object passed to YUI.io().
3851 * @param {Object} io
3852 */
3853function _cFrame(o, c, io) {
3854    var i = Y.Node.create('<iframe id="io_iframe' + o.id + '" name="io_iframe' + o.id + '" />');
3855        i._node.style.position = 'absolute';
3856        i._node.style.top = '-1000px';
3857        i._node.style.left = '-1000px';
3858        Y.one('body').appendChild(i);
3859    // Bind the onload handler to the iframe to detect the file upload response.
3860    Y.on("load", function() { io._uploadComplete(o, c); }, '#io_iframe' + o.id);
3861}
3862
3863/**
3864 * Removes the iframe transport used in the file upload
3865 * transaction.
3866 *
3867 * @method _dFrame
3868 * @private
3869 * @param {Number} id The transaction ID used in the iframe's creation.
3870 */
3871function _dFrame(id) {
3872	Y.Event.purgeElement('#io_iframe' + id, false);
3873	Y.one('body').removeChild(Y.one('#io_iframe' + id));
3874}
3875
3876Y.mix(Y.IO.prototype, {
3877   /**
3878    * Parses the POST data object and creates hidden form elements
3879    * for each key-value, and appends them to the HTML form object.
3880    * @method _addData
3881    * @private
3882    * @static
3883    * @param {Object} f HTML form object.
3884    * @param {String} s The key-value POST data.
3885    * @return {Array} o Array of created fields.
3886    */
3887    _addData: function(f, s) {
3888        // Serialize an object into a key-value string using
3889        // querystring-stringify-simple.
3890        if (Y.Lang.isObject(s)) {
3891            s = Y.QueryString.stringify(s);
3892        }
3893
3894        var o = [],
3895            m = s.split('='),
3896            i, l;
3897
3898        for (i = 0, l = m.length - 1; i < l; i++) {
3899            var name = _d(m[i].substring(m[i].lastIndexOf('&') + 1));
3900            var input = f.elements[name];
3901
3902            if (!input) {
3903                o[i] = d.createElement('input');
3904                o[i].type = 'hidden';
3905                o[i].name = name;
3906                o[i].value = (i + 1 === l) ? _d(m[i + 1]) : _d(m[i + 1].substring(0, (m[i + 1].lastIndexOf('&'))));
3907                f.appendChild(o[i]);
3908            }
3909        }
3910
3911        return o;
3912    },
3913
3914   /**
3915    * Removes the custom fields created to pass additional POST
3916    * data, along with the HTML form fields.
3917    * @method _removeData
3918    * @private
3919    * @static
3920    * @param {Object} f HTML form object.
3921    * @param {Object} o HTML form fields created from configuration.data.
3922    */
3923    _removeData: function(f, o) {
3924        var i, l;
3925
3926        for (i = 0, l = o.length; i < l; i++) {
3927            f.removeChild(o[i]);
3928        }
3929    },
3930
3931   /**
3932    * Sets the appropriate attributes and values to the HTML
3933    * form, in preparation of a file upload transaction.
3934    * @method _setAttrs
3935    * @private
3936    * @static
3937    * @param {Object} f HTML form object.
3938    * @param {Object} id The Transaction ID.
3939    * @param {Object} uri Qualified path to transaction resource.
3940    */
3941    _setAttrs: function(f, id, uri) {
3942        // Track original HTML form attribute values.
3943        this._originalFormAttrs = {
3944            action: f.getAttribute('action'),
3945            target: f.getAttribute('target')
3946        };
3947
3948        f.setAttribute('action', uri);
3949        f.setAttribute('method', 'POST');
3950        f.setAttribute('target', 'io_iframe' + id );
3951        f.setAttribute(Y.UA.ie && !_std ? 'encoding' : 'enctype', 'multipart/form-data');
3952    },
3953
3954   /**
3955    * Reset the HTML form attributes to their original values.
3956    * @method _resetAttrs
3957    * @private
3958    * @static
3959    * @param {Object} f HTML form object.
3960    * @param {Object} a Object of original attributes.
3961    */
3962    _resetAttrs: function(f, a) {
3963        Y.Object.each(a, function(v, p) {
3964            if (v) {
3965                f.setAttribute(p, v);
3966            }
3967            else {
3968                f.removeAttribute(p);
3969            }
3970        });
3971    },
3972
3973   /**
3974    * Starts timeout count if the configuration object
3975    * has a defined timeout property.
3976    *
3977    * @method _startUploadTimeout
3978    * @private
3979    * @static
3980    * @param {Object} o Transaction object generated by _create().
3981    * @param {Object} c Configuration object passed to YUI.io().
3982    */
3983    _startUploadTimeout: function(o, c) {
3984        var io = this;
3985
3986        io._timeout[o.id] = w.setTimeout(
3987            function() {
3988                o.status = 0;
3989                o.statusText = 'timeout';
3990                io.complete(o, c);
3991                io.end(o, c);
3992            }, c.timeout);
3993    },
3994
3995   /**
3996    * Clears the timeout interval started by _startUploadTimeout().
3997    * @method _clearUploadTimeout
3998    * @private
3999    * @static
4000    * @param {Number} id - Transaction ID.
4001    */
4002    _clearUploadTimeout: function(id) {
4003        var io = this;
4004
4005        w.clearTimeout(io._timeout[id]);
4006        delete io._timeout[id];
4007    },
4008
4009   /**
4010    * Bound to the iframe's Load event and processes
4011    * the response data.
4012    * @method _uploadComplete
4013    * @private
4014    * @static
4015    * @param {Object} o The transaction object
4016    * @param {Object} c Configuration object for the transaction.
4017    */
4018    _uploadComplete: function(o, c) {
4019        var io = this,
4020            d = Y.one('#io_iframe' + o.id).get('contentWindow.document'),
4021            b = d.one('body'),
4022            p;
4023
4024        if (c.timeout) {
4025            io._clearUploadTimeout(o.id);
4026        }
4027
4028		try {
4029			if (b) {
4030				// When a response Content-Type of "text/plain" is used, Firefox and Safari
4031				// will wrap the response string with <pre></pre>.
4032				p = b.one('pre:first-child');
4033				o.c.responseText = p ? p.get('text') : b.get('text');
4034			}
4035			else {
4036				o.c.responseXML = d._node;
4037			}
4038		}
4039		catch (e) {
4040			o.e = "upload failure";
4041		}
4042
4043        io.complete(o, c);
4044        io.end(o, c);
4045        // The transaction is complete, so call _dFrame to remove
4046        // the event listener bound to the iframe transport, and then
4047        // destroy the iframe.
4048        w.setTimeout( function() { _dFrame(o.id); }, 0);
4049    },
4050
4051   /**
4052    * Uploads HTML form data, inclusive of files/attachments,
4053    * using the iframe created in _create to facilitate the transaction.
4054    * @method _upload
4055    * @private
4056    * @static
4057    * @param {Object} o The transaction object
4058    * @param {Object} uri Qualified path to transaction resource.
4059    * @param {Object} c Configuration object for the transaction.
4060    */
4061    _upload: function(o, uri, c) {
4062        var io = this,
4063            f = (typeof c.form.id === 'string') ? d.getElementById(c.form.id) : Y.Node.getDOMNode(c.form.id),
4064            fields;
4065
4066        // Initialize the HTML form properties in case they are
4067        // not defined in the HTML form.
4068        io._setAttrs(f, o.id, uri);
4069        if (c.data) {
4070            fields = io._addData(f, c.data);
4071        }
4072
4073        // Start polling if a callback is present and the timeout
4074        // property has been defined.
4075        if (c.timeout) {
4076            io._startUploadTimeout(o, c);
4077        }
4078
4079        // Start file upload.
4080        f.submit();
4081        io.start(o, c);
4082        if (c.data) {
4083            var _onIoEndHandler = io.on('io:end', function (event) {
4084                _onIoEndHandler.detach();
4085                io._removeData(f, fields);
4086            });
4087        }
4088
4089        return {
4090            id: o.id,
4091            abort: function() {
4092                o.status = 0;
4093                o.statusText = 'abort';
4094                if (Y.one('#io_iframe' + o.id)) {
4095                    _dFrame(o.id);
4096                    io.complete(o, c);
4097                    io.end(o, c);
4098                }
4099                else {
4100                    return false;
4101                }
4102            },
4103            isInProgress: function() {
4104                return Y.one('#io_iframe' + o.id) ? true : false;
4105            },
4106            io: io
4107        };
4108    },
4109
4110    upload: function(o, uri, c) {
4111        _cFrame(o, c, this);
4112        return this._upload(o, uri, c);
4113    },
4114
4115    end: function(transaction, config) {
4116        var form, io;
4117
4118        if (config) {
4119            form = config.form;
4120
4121            if (form && form.upload) {
4122                io = this;
4123
4124                // Restore HTML form attributes to their original values.
4125                form = (typeof form.id === 'string') ? d.getElementById(form.id) : form.id;
4126
4127                // Check whether the form still exists before resetting it.
4128                if (form) {
4129                    io._resetAttrs(form, this._originalFormAttrs);
4130                }
4131            }
4132        }
4133
4134        return _end.call(this, transaction, config);
4135    }
4136}, true);
4137
4138
4139}, 'patched-v3.18.3', {"requires": ["io-base", "node-base"]});
4140
4141YUI.add('io-xdr', function (Y, NAME) {
4142
4143/**
4144Extends IO to provide an alternate, Flash transport, for making
4145cross-domain requests.
4146@module io
4147@submodule io-xdr
4148@for IO
4149@deprecated
4150**/
4151
4152// Helpful resources when working with the mess that is XDomainRequest:
4153// http://www.cypressnorth.com/blog/web-programming-and-development/internet-explorer-aborting-ajax-requests-fixed/
4154// http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
4155
4156/**
4157Fires when the XDR transport is ready for use.
4158@event io:xdrReady
4159**/
4160var E_XDR_READY = Y.publish('io:xdrReady', { fireOnce: true }),
4161
4162/**
4163Map of stored configuration objects when using
4164Flash as the transport for cross-domain requests.
4165
4166@property _cB
4167@private
4168@type {Object}
4169**/
4170_cB = {},
4171
4172/**
4173Map of transaction simulated readyState values
4174when XDomainRequest is the transport.
4175
4176@property _rS
4177@private
4178@type {Object}
4179**/
4180_rS = {},
4181
4182// Document reference
4183d = Y.config.doc,
4184// Window reference
4185w = Y.config.win,
4186// XDomainRequest cross-origin request detection
4187xdr = w && w.XDomainRequest;
4188
4189/**
4190Method that creates the Flash transport swf.
4191
4192@method _swf
4193@private
4194@param {String} uri - location of io.swf.
4195@param {String} yid - YUI sandbox id.
4196@param {String} uid - IO instance id.
4197**/
4198function _swf(uri, yid, uid) {
4199    var o = '<object id="io_swf" type="application/x-shockwave-flash" data="' +
4200            uri + '" width="0" height="0">' +
4201            '<param name="movie" value="' + uri + '">' +
4202            '<param name="FlashVars" value="yid=' + yid + '&uid=' + uid + '">' +
4203            '<param name="allowScriptAccess" value="always">' +
4204            '</object>',
4205        c = d.createElement('div');
4206
4207    d.body.appendChild(c);
4208    c.innerHTML = o;
4209}
4210
4211/**
4212Creates a response object for XDR transactions, for success
4213and failure cases.
4214
4215@method _data
4216@private
4217@param {Object} o - Transaction object generated by _create() in io-base.
4218@param {Boolean} u - Configuration xdr.use.
4219@param {Boolean} d - Configuration xdr.dataType.
4220
4221@return {Object}
4222**/
4223function _data(o, u, d) {
4224    if (u === 'flash') {
4225        o.c.responseText = decodeURI(o.c.responseText);
4226    }
4227    if (d === 'xml') {
4228        o.c.responseXML = Y.DataType.XML.parse(o.c.responseText);
4229    }
4230
4231    return o;
4232}
4233
4234/**
4235Method for intiating an XDR transaction abort.
4236
4237@method _abort
4238@private
4239@param {Object} o - Transaction object generated by _create() in io-base.
4240@param {Object} c - configuration object for the transaction.
4241**/
4242function _abort(o, c) {
4243    return o.c.abort(o.id, c);
4244}
4245
4246/**
4247Method for determining if an XDR transaction has completed
4248and all data are received.
4249
4250@method _isInProgress
4251@private
4252@param {Object} o - Transaction object generated by _create() in io-base.
4253**/
4254function _isInProgress(o) {
4255    return xdr ? _rS[o.id] !== 4 : o.c.isInProgress(o.id);
4256}
4257
4258Y.mix(Y.IO.prototype, {
4259
4260    /**
4261    Map of io transports.
4262
4263    @property _transport
4264    @private
4265    @type {Object}
4266    **/
4267    _transport: {},
4268
4269    /**
4270    Sets event handlers for XDomainRequest transactions.
4271
4272    @method _ieEvt
4273    @private
4274    @static
4275    @param {Object} o - Transaction object generated by _create() in io-base.
4276    @param {Object} c - configuration object for the transaction.
4277    **/
4278    _ieEvt: function(o, c) {
4279        var io = this,
4280            i = o.id,
4281            t = 'timeout';
4282
4283        o.c.onprogress = function() { _rS[i] = 3; };
4284        o.c.onload = function() {
4285            _rS[i] = 4;
4286            io.xdrResponse('success', o, c);
4287        };
4288        o.c.onerror = function() {
4289            _rS[i] = 4;
4290            io.xdrResponse('failure', o, c);
4291        };
4292        o.c.ontimeout = function() {
4293            _rS[i] = 4;
4294            io.xdrResponse(t, o, c);
4295        };
4296        o.c[t] = c[t] || 0;
4297    },
4298
4299    /**
4300    Method for accessing the transport's interface for making a
4301    cross-domain transaction.
4302
4303    @method xdr
4304    @param {String} uri - qualified path to transaction resource.
4305    @param {Object} o - Transaction object generated by _create() in io-base.
4306    @param {Object} c - configuration object for the transaction.
4307    **/
4308    xdr: function(uri, o, c) {
4309        var io = this;
4310
4311        if (c.xdr.use === 'flash') {
4312            // The configuration object cannot be serialized safely
4313            // across Flash's ExternalInterface.
4314            _cB[o.id] = c;
4315            w.setTimeout(function() {
4316                try {
4317                    o.c.send(uri, { id: o.id,
4318                                    uid: o.uid,
4319                                    method: c.method,
4320                                    data: c.data,
4321                                    headers: c.headers });
4322                }
4323                catch(e) {
4324                    io.xdrResponse('transport error', o, c);
4325                    delete _cB[o.id];
4326                }
4327            }, Y.io.xdr.delay);
4328        }
4329        else if (xdr) {
4330            io._ieEvt(o, c);
4331            o.c.open(c.method || 'GET', uri);
4332
4333            // Make async to protect against IE 8 oddities.
4334            setTimeout(function() {
4335                o.c.send(c.data);
4336            }, 0);
4337        }
4338        else {
4339            o.c.send(uri, o, c);
4340        }
4341
4342        return {
4343            id: o.id,
4344            abort: function() {
4345                return o.c ? _abort(o, c) : false;
4346            },
4347            isInProgress: function() {
4348                return o.c ? _isInProgress(o.id) : false;
4349            },
4350            io: io
4351        };
4352    },
4353
4354    /**
4355    Response controller for cross-domain requests when using the
4356    Flash transport or IE8's XDomainRequest object.
4357
4358    @method xdrResponse
4359    @param {String} e Event name
4360    @param {Object} o Transaction object generated by _create() in io-base.
4361    @param {Object} c Configuration object for the transaction.
4362    @return {Object}
4363    **/
4364    xdrResponse: function(e, o, c) {
4365        c = _cB[o.id] ? _cB[o.id] : c;
4366        var io = this,
4367            m = xdr ? _rS : _cB,
4368            u = c.xdr.use,
4369            d = c.xdr.dataType;
4370
4371        switch (e) {
4372            case 'start':
4373                io.start(o, c);
4374                break;
4375           //case 'complete':
4376                //This case is not used by Flash or XDomainRequest.
4377                //io.complete(o, c);
4378                //break;
4379            case 'success':
4380                io.success(_data(o, u, d), c);
4381                delete m[o.id];
4382                break;
4383            case 'timeout':
4384            case 'abort':
4385            case 'transport error':
4386                o.c = { status: 0, statusText: e };
4387            case 'failure':
4388                io.failure(_data(o, u, d), c);
4389                delete m[o.id];
4390                break;
4391        }
4392    },
4393
4394    /**
4395    Fires event "io:xdrReady"
4396
4397    @method _xdrReady
4398    @private
4399    @param {Number} yid - YUI sandbox id.
4400    @param {Number} uid - IO instance id.
4401    **/
4402    _xdrReady: function(yid, uid) {
4403        Y.fire(E_XDR_READY, yid, uid);
4404    },
4405
4406    /**
4407    Initializes the desired transport.
4408
4409    @method transport
4410    @param {Object} o - object of transport configurations.
4411    **/
4412    transport: function(c) {
4413        if (c.id === 'flash') {
4414            _swf(Y.UA.ie ? c.src + '?d=' + new Date().valueOf().toString() : c.src, Y.id, c.uid);
4415            Y.IO.transports.flash = function() { return d.getElementById('io_swf'); };
4416        }
4417    }
4418});
4419
4420/**
4421Fires event "io:xdrReady"
4422
4423@method xdrReady
4424@protected
4425@static
4426@param {Number} yid - YUI sandbox id.
4427@param {Number} uid - IO instance id.
4428**/
4429Y.io.xdrReady = function(yid, uid){
4430    var io = Y.io._map[uid];
4431    Y.io.xdr.delay = 0;
4432    io._xdrReady.apply(io, [yid, uid]);
4433};
4434
4435Y.io.xdrResponse = function(e, o, c){
4436    var io = Y.io._map[o.uid];
4437    io.xdrResponse.apply(io, [e, o, c]);
4438};
4439
4440Y.io.transport = function(c){
4441    var io = Y.io._map['io:0'] || new Y.IO();
4442    c.uid = io._uid;
4443    io.transport.apply(io, [c]);
4444};
4445
4446/**
4447Delay value to calling the Flash transport, in the
4448event io.swf has not finished loading.  Once the E_XDR_READY
4449event is fired, this value will be set to 0.
4450
4451@property delay
4452@static
4453@type {Number}
4454**/
4455Y.io.xdr = { delay : 100 };
4456
4457
4458}, 'patched-v3.18.3', {"requires": ["io-base", "datatype-xml-parse"]});
4459
4460YUI.add('json-parse', function (Y, NAME) {
4461
4462var _JSON = Y.config.global.JSON;
4463
4464Y.namespace('JSON').parse = function (obj, reviver, space) {
4465    return _JSON.parse((typeof obj === 'string' ? obj : obj + ''), reviver, space);
4466};
4467
4468
4469}, 'patched-v3.18.3', {"requires": ["yui-base"]});
4470
4471YUI.add('json-stringify', function (Y, NAME) {
4472
4473/**
4474 * Provides Y.JSON.stringify method for converting objects to JSON strings.
4475 *
4476 * @module json
4477 * @submodule json-stringify
4478 * @for JSON
4479 * @static
4480 */
4481var COLON     = ':',
4482    _JSON     = Y.config.global.JSON;
4483
4484Y.mix(Y.namespace('JSON'), {
4485    /**
4486     * Serializes a Date instance as a UTC date string.  Used internally by
4487     * stringify.  Override this method if you need Dates serialized in a
4488     * different format.
4489     *
4490     * @method dateToString
4491     * @param d {Date} The Date to serialize
4492     * @return {String} stringified Date in UTC format YYYY-MM-DDTHH:mm:SSZ
4493     * @deprecated Use a replacer function
4494     * @static
4495     */
4496    dateToString: function (d) {
4497        function _zeroPad(v) {
4498            return v < 10 ? '0' + v : v;
4499        }
4500
4501        return d.getUTCFullYear()           + '-' +
4502              _zeroPad(d.getUTCMonth() + 1) + '-' +
4503              _zeroPad(d.getUTCDate())      + 'T' +
4504              _zeroPad(d.getUTCHours())     + COLON +
4505              _zeroPad(d.getUTCMinutes())   + COLON +
4506              _zeroPad(d.getUTCSeconds())   + 'Z';
4507    },
4508
4509    /**
4510     * <p>Converts an arbitrary value to a JSON string representation.</p>
4511     *
4512     * <p>Objects with cyclical references will trigger an exception.</p>
4513     *
4514     * <p>If a whitelist is provided, only matching object keys will be
4515     * included.  Alternately, a replacer function may be passed as the
4516     * second parameter.  This function is executed on every value in the
4517     * input, and its return value will be used in place of the original value.
4518     * This is useful to serialize specialized objects or class instances.</p>
4519     *
4520     * <p>If a positive integer or non-empty string is passed as the third
4521     * parameter, the output will be formatted with carriage returns and
4522     * indentation for readability.  If a String is passed (such as "\t") it
4523     * will be used once for each indentation level.  If a number is passed,
4524     * that number of spaces will be used.</p>
4525     *
4526     * @method stringify
4527     * @param o {MIXED} any arbitrary value to convert to JSON string
4528     * @param w {Array|Function} (optional) whitelist of acceptable object
4529     *                  keys to include, or a replacer function to modify the
4530     *                  raw value before serialization
4531     * @param ind {Number|String} (optional) indentation character or depth of
4532     *                  spaces to format the output.
4533     * @return {string} JSON string representation of the input
4534     * @static
4535     */
4536    stringify: function () {
4537        return _JSON.stringify.apply(_JSON, arguments);
4538    },
4539
4540    /**
4541     * <p>Number of occurrences of a special character within a single call to
4542     * stringify that should trigger promotion of that character to a dedicated
4543     * preprocess step for future calls.  This is only used in environments
4544     * that don't support native JSON, or when useNativeJSONStringify is set to
4545     * false.</p>
4546     *
4547     * <p>So, if set to 50 and an object is passed to stringify that includes
4548     * strings containing the special character \x07 more than 50 times,
4549     * subsequent calls to stringify will process object strings through a
4550     * faster serialization path for \x07 before using the generic, slower,
4551     * replacement process for all special characters.</p>
4552     *
4553     * <p>To prime the preprocessor cache, set this value to 1, then call
4554     * <code>Y.JSON.stringify("<em>(all special characters to
4555     * cache)</em>");</code>, then return this setting to a more conservative
4556     * value.</p>
4557     *
4558     * <p>Special characters \ " \b \t \n \f \r are already cached.</p>
4559     *
4560     * @property charCacheThreshold
4561     * @static
4562     * @default 100
4563     * @type {Number}
4564     */
4565    charCacheThreshold: 100
4566});
4567
4568
4569}, 'patched-v3.18.3', {"requires": ["yui-base"]});
4570
4571YUI.add('node-base', function (Y, NAME) {
4572
4573/**
4574 * @module node
4575 * @submodule node-base
4576 */
4577
4578var methods = [
4579/**
4580 * Determines whether the node has the given className.
4581 * @method hasClass
4582 * @for Node
4583 * @param {String} className the class name to search for
4584 * @return {Boolean} Whether or not the node has the specified class
4585 */
4586 'hasClass',
4587
4588/**
4589 * Adds a class name to the node.
4590 * @method addClass
4591 * @param {String} className the class name to add to the node's class attribute
4592 * @chainable
4593 */
4594 'addClass',
4595
4596/**
4597 * Removes a class name from the node.
4598 * @method removeClass
4599 * @param {String} className the class name to remove from the node's class attribute
4600 * @chainable
4601 */
4602 'removeClass',
4603
4604/**
4605 * Replace a class with another class on the node.
4606 * If no oldClassName is present, the newClassName is simply added.
4607 * @method replaceClass
4608 * @param {String} oldClassName the class name to be replaced
4609 * @param {String} newClassName the class name that will be replacing the old class name
4610 * @chainable
4611 */
4612 'replaceClass',
4613
4614/**
4615 * If the className exists on the node it is removed, if it doesn't exist it is added.
4616 * @method toggleClass
4617 * @param {String} className the class name to be toggled
4618 * @param {Boolean} force Option to force adding or removing the class.
4619 * @chainable
4620 */
4621 'toggleClass'
4622];
4623
4624Y.Node.importMethod(Y.DOM, methods);
4625/**
4626 * Determines whether each node has the given className.
4627 * @method hasClass
4628 * @see Node.hasClass
4629 * @for NodeList
4630 * @param {String} className the class name to search for
4631 * @return {Array} An array of booleans for each node bound to the NodeList.
4632 */
4633
4634/**
4635 * Adds a class name to each node.
4636 * @method addClass
4637 * @see Node.addClass
4638 * @param {String} className the class name to add to each node's class attribute
4639 * @chainable
4640 */
4641
4642/**
4643 * Removes a class name from each node.
4644 * @method removeClass
4645 * @see Node.removeClass
4646 * @param {String} className the class name to remove from each node's class attribute
4647 * @chainable
4648 */
4649
4650/**
4651 * Replace a class with another class for each node.
4652 * If no oldClassName is present, the newClassName is simply added.
4653 * @method replaceClass
4654 * @see Node.replaceClass
4655 * @param {String} oldClassName the class name to be replaced
4656 * @param {String} newClassName the class name that will be replacing the old class name
4657 * @chainable
4658 */
4659
4660/**
4661 * For each node, if the className exists on the node it is removed, if it doesn't exist it is added.
4662 * @method toggleClass
4663 * @see Node.toggleClass
4664 * @param {String} className the class name to be toggled
4665 * @chainable
4666 */
4667Y.NodeList.importMethod(Y.Node.prototype, methods);
4668/**
4669 * @module node
4670 * @submodule node-base
4671 */
4672
4673var Y_Node = Y.Node,
4674    Y_DOM = Y.DOM;
4675
4676/**
4677 * Returns a new dom node using the provided markup string.
4678 * @method create
4679 * @static
4680 * @param {String} html The markup used to create the element.
4681 * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4682 * to escape html content.
4683 * @param {HTMLDocument} doc An optional document context
4684 * @return {Node} A Node instance bound to a DOM node or fragment
4685 * @for Node
4686 */
4687Y_Node.create = function(html, doc) {
4688    if (doc && doc._node) {
4689        doc = doc._node;
4690    }
4691    return Y.one(Y_DOM.create(html, doc));
4692};
4693
4694Y.mix(Y_Node.prototype, {
4695    /**
4696     * Creates a new Node using the provided markup string.
4697     * @method create
4698     * @param {String} html The markup used to create the element.
4699     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4700     * to escape html content.
4701     * @param {HTMLDocument} doc An optional document context
4702     * @return {Node} A Node instance bound to a DOM node or fragment
4703     */
4704    create: Y_Node.create,
4705
4706    /**
4707     * Inserts the content before the reference node.
4708     * @method insert
4709     * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert.
4710     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4711     * to escape html content.
4712     * @param {Int | Node | HTMLElement | String} where The position to insert at.
4713     * Possible "where" arguments
4714     * <dl>
4715     * <dt>Y.Node</dt>
4716     * <dd>The Node to insert before</dd>
4717     * <dt>HTMLElement</dt>
4718     * <dd>The element to insert before</dd>
4719     * <dt>Int</dt>
4720     * <dd>The index of the child element to insert before</dd>
4721     * <dt>"replace"</dt>
4722     * <dd>Replaces the existing HTML</dd>
4723     * <dt>"before"</dt>
4724     * <dd>Inserts before the existing HTML</dd>
4725     * <dt>"before"</dt>
4726     * <dd>Inserts content before the node</dd>
4727     * <dt>"after"</dt>
4728     * <dd>Inserts content after the node</dd>
4729     * </dl>
4730     * @chainable
4731     */
4732    insert: function(content, where) {
4733        this._insert(content, where);
4734        return this;
4735    },
4736
4737    _insert: function(content, where) {
4738        var node = this._node,
4739            ret = null;
4740
4741        if (typeof where == 'number') { // allow index
4742            where = this._node.childNodes[where];
4743        } else if (where && where._node) { // Node
4744            where = where._node;
4745        }
4746
4747        if (content && typeof content != 'string') { // allow Node or NodeList/Array instances
4748            content = content._node || content._nodes || content;
4749        }
4750        ret = Y_DOM.addHTML(node, content, where);
4751
4752        return ret;
4753    },
4754
4755    /**
4756     * Inserts the content as the firstChild of the node.
4757     * @method prepend
4758     * @param {String | Node | HTMLElement} content The content to insert.
4759     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4760     * to escape html content.
4761     * @chainable
4762     */
4763    prepend: function(content) {
4764        return this.insert(content, 0);
4765    },
4766
4767    /**
4768     * Inserts the content as the lastChild of the node.
4769     * @method append
4770     * @param {String | Node | HTMLElement} content The content to insert.
4771     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4772     * to escape html content.
4773     * @chainable
4774     */
4775    append: function(content) {
4776        return this.insert(content, null);
4777    },
4778
4779    /**
4780     * @method appendChild
4781     * @param {String | HTMLElement | Node} node Node to be appended.
4782     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4783     * to escape html content.
4784     * @return {Node} The appended node
4785     */
4786    appendChild: function(node) {
4787        return Y_Node.scrubVal(this._insert(node));
4788    },
4789
4790    /**
4791     * @method insertBefore
4792     * @param {String | HTMLElement | Node} newNode Node to be appended
4793     * @param {HTMLElement | Node} refNode Node to be inserted before.
4794     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4795     * to escape html content.
4796     * @return {Node} The inserted node
4797     */
4798    insertBefore: function(newNode, refNode) {
4799        return Y.Node.scrubVal(this._insert(newNode, refNode));
4800    },
4801
4802    /**
4803     * Appends the node to the given node.
4804     * @example
4805     *      // appendTo returns the node that has been created beforehand
4806     *      Y.Node.create('<p></p>').appendTo('body').set('text', 'hello world!');
4807     * @method appendTo
4808     * @param {Node | HTMLElement | String}
4808 node The node to append to.
4809     *  If `node` is a string it will be considered as a css selector and only the first matching node will be used.
4810     * @chainable
4811     */
4812    appendTo: function(node) {
4813        Y.one(node).append(this);
4814        return this;
4815    },
4816
4817    // This method is deprecated, and is intentionally left undocumented.
4818    // Use `setHTML` instead.
4819    setContent: function(content) {
4820        this._insert(content, 'replace');
4821        return this;
4822    },
4823
4824    // This method is deprecated, and is intentionally left undocumented.
4825    // Use `getHTML` instead.
4826    getContent: function() {
4827        var node = this;
4828
4829        if (node._node.nodeType === 11) { // 11 === Node.DOCUMENT_FRAGMENT_NODE
4830            // "this", when it is a document fragment, must be cloned because
4831            // the nodes contained in the fragment actually disappear once
4832            // the fragment is appended anywhere
4833            node = node.create("<div/>").append(node.cloneNode(true));
4834        }
4835
4836        return node.get("innerHTML");
4837    }
4838});
4839
4840/**
4841 * Replaces the node's current html content with the content provided.
4842 * Note that this passes to innerHTML and is not escaped.
4843 * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4844 * to escape html content or `set('text')` to add as text.
4845 * @method setHTML
4846 * @param {String | Node | HTMLElement | NodeList | HTMLCollection} content The content to insert
4847 * @chainable
4848 */
4849Y.Node.prototype.setHTML = Y.Node.prototype.setContent;
4850
4851/**
4852 * Returns the node's current html content (e.g. innerHTML)
4853 * @method getHTML
4854 * @return {String} The html content
4855 */
4856Y.Node.prototype.getHTML = Y.Node.prototype.getContent;
4857
4858Y.NodeList.importMethod(Y.Node.prototype, [
4859    /**
4860     * Called on each Node instance
4861     * @for NodeList
4862     * @method append
4863     * @see Node.append
4864     */
4865    'append',
4866
4867    /**
4868     * Called on each Node instance
4869     * @for NodeList
4870     * @method insert
4871     * @see Node.insert
4872     */
4873    'insert',
4874
4875    /**
4876     * Called on each Node instance
4877     * @for NodeList
4878     * @method appendChild
4879     * @see Node.appendChild
4880     */
4881    'appendChild',
4882
4883    /**
4884     * Called on each Node instance
4885     * @for NodeList
4886     * @method insertBefore
4887     * @see Node.insertBefore
4888     */
4889    'insertBefore',
4890
4891    /**
4892     * Called on each Node instance
4893     * @for NodeList
4894     * @method prepend
4895     * @see Node.prepend
4896     */
4897    'prepend',
4898
4899    'setContent',
4900
4901    'getContent',
4902
4903    /**
4904     * Called on each Node instance
4905     * Note that this passes to innerHTML and is not escaped.
4906     * Use <a href="../classes/Escape.html#method_html">`Y.Escape.html()`</a>
4907     * to escape html content or `set('text')` to add as text.
4908     * @for NodeList
4909     * @method setHTML
4910     * @see Node.setHTML
4911     */
4912    'setHTML',
4913
4914    /**
4915     * Called on each Node instance
4916     * @for NodeList
4917     * @method getHTML
4918     * @see Node.getHTML
4919     */
4920    'getHTML'
4921]);
4922/**
4923 * @module node
4924 * @submodule node-base
4925 */
4926
4927var Y_Node = Y.Node,
4928    Y_DOM = Y.DOM;
4929
4930/**
4931 * Static collection of configuration attributes for special handling
4932 * @property ATTRS
4933 * @static
4934 * @type object
4935 */
4936Y_Node.ATTRS = {
4937    /**
4938     * Allows for getting and setting the text of an element.
4939     * Formatting is preserved and special characters are treated literally.
4940     * @config text
4941     * @type String
4942     */
4943    text: {
4944        getter: function() {
4945            return Y_DOM.getText(this._node);
4946        },
4947
4948        setter: function(content) {
4949            Y_DOM.setText(this._node, content);
4950            return content;
4951        }
4952    },
4953
4954    /**
4955     * Allows for getting and setting the text of an element.
4956     * Formatting is preserved and special characters are treated literally.
4957     * @config for
4958     * @type String
4959     */
4960    'for': {
4961        getter: function() {
4962            return Y_DOM.getAttribute(this._node, 'for');
4963        },
4964
4965        setter: function(val) {
4966            Y_DOM.setAttribute(this._node, 'for', val);
4967            return val;
4968        }
4969    },
4970
4971    'options': {
4972        getter: function() {
4973            return this._node.getElementsByTagName('option');
4974        }
4975    },
4976
4977    /**
4978     * Returns a NodeList instance of all HTMLElement children.
4979     * @readOnly
4980     * @config children
4981     * @type NodeList
4982     */
4983    'children': {
4984        getter: function() {
4985            var node = this._node,
4986                children = node.children,
4987                childNodes, i, len;
4988
4989            if (!children || (Y.UA.ie && Y.UA.ie < 9)) {
4990                childNodes = node.childNodes;
4991                children = [];
4992
4993                for (i = 0, len = childNodes.length; i < len; ++i) {
4994                    if (childNodes[i].tagName && (childNodes[i].nodeType === 1)) {
4995                        children[children.length] = childNodes[i];
4996                    }
4997                }
4998            }
4999            return Y.all(children);
5000        }
5001    },
5002
5003    value: {
5004        getter: function() {
5005            return Y_DOM.getValue(this._node);
5006        },
5007
5008        setter: function(val) {
5009            Y_DOM.setValue(this._node, val);
5010            return val;
5011        }
5012    }
5013};
5014
5015Y.Node.importMethod(Y.DOM, [
5016    /**
5017     * Allows setting attributes on DOM nodes, normalizing in some cases.
5018     * This passes through to the DOM node, allowing for custom attributes.
5019     * @method setAttribute
5020     * @for Node
5021     * @for NodeList
5022     * @chainable
5023     * @param {string} name The attribute name
5024     * @param {string} value The value to set
5025     */
5026    'setAttribute',
5027    /**
5028     * Allows getting attributes on DOM nodes, normalizing in some cases.
5029     * This passes through to the DOM node, allowing for custom attributes.
5030     * @method getAttribute
5031     * @for Node
5032     * @for NodeList
5033     * @param {string} name The attribute name
5034     * @return {string} The attribute value
5035     */
5036    'getAttribute'
5037
5038]);
5039/**
5040 * @module node
5041 * @submodule node-base
5042 */
5043
5044var Y_Node = Y.Node;
5045var Y_NodeList = Y.NodeList;
5046/**
5047 * List of events that route to DOM events
5048 * @static
5049 * @property DOM_EVENTS
5050 * @for Node
5051 */
5052
5053Y_Node.DOM_EVENTS = {
5054    abort: 1,
5055    beforeunload: 1,
5056    blur: 1,
5057    change: 1,
5058    click: 1,
5059    close: 1,
5060    command: 1,
5061    contextmenu: 1,
5062    copy: 1,
5063    cut: 1,
5064    dblclick: 1,
5065    DOMMouseScroll: 1,
5066    drag: 1,
5067    dragstart: 1,
5068    dragenter: 1,
5069    dragover: 1,
5070    dragleave: 1,
5071    dragend: 1,
5072    drop: 1,
5073    error: 1,
5074    focus: 1,
5075    key: 1,
5076    keydown: 1,
5077    keypress: 1,
5078    keyup: 1,
5079    load: 1,
5080    message: 1,
5081    mousedown: 1,
5082    mouseenter: 1,
5083    mouseleave: 1,
5084    mousemove: 1,
5085    mousemultiwheel: 1,
5086    mouseout: 1,
5087    mouseover: 1,
5088    mouseup: 1,
5089    mousewheel: 1,
5090    orientationchange: 1,
5091    paste: 1,
5092    reset: 1,
5093    resize: 1,
5094    select: 1,
5095    selectstart: 1,
5096    submit: 1,
5097    scroll: 1,
5098    textInput: 1,
5099    unload: 1,
5100    invalid: 1
5101};
5102
5103// Add custom event adaptors to this list.  This will make it so
5104// that delegate, key, available, contentready, etc all will
5105// be available through Node.on
5106Y.mix(Y_Node.DOM_EVENTS, Y.Env.evt.plugins);
5107
5108Y.augment(Y_Node, Y.EventTarget);
5109
5110Y.mix(Y_Node.prototype, {
5111    /**
5112     * Removes event listeners from the node and (optionally) its subtree
5113     * @method purge
5114     * @param {Boolean} recurse (optional) Whether or not to remove listeners from the
5115     * node's subtree
5116     * @param {String} type (optional) Only remove listeners of the specified type
5117     * @chainable
5118     *
5119     */
5120    purge: function(recurse, type) {
5121        Y.Event.purgeElement(this._node, recurse, type);
5122        return this;
5123    }
5124
5125});
5126
5127Y.mix(Y.NodeList.prototype, {
5128    _prepEvtArgs: function(type, fn, context) {
5129        // map to Y.on/after signature (type, fn, nodes, context, arg1, arg2, etc)
5130        var args = Y.Array(arguments, 0, true);
5131
5132        if (args.length < 2) { // type only (event hash) just add nodes
5133            args[2] = this._nodes;
5134        } else {
5135            args.splice(2, 0, this._nodes);
5136        }
5137
5138        args[3] = context || this;
5138 // default to NodeList instance as context
5139
5140        return args;
5141    },
5142
5143    /**
5144    Subscribe a callback function for each `Node` in the collection to execute
5145    in response to a DOM event.
5146
5147    NOTE: Generally, the `on()` method should be avoided on `NodeLists`, in
5148    favor of using event delegation from a parent Node.  See the Event user
5149    guide for details.
5150
5151    Most DOM events are associated with a preventable default behavior, such as
5152    link clicks navigating to a new page.  Callbacks are passed a
5153    `DOMEventFacade` object as their first argument (usually called `e`) that
5154    can be used to prevent this default behavior with `e.preventDefault()`. See
5155    the `DOMEventFacade` API for all available properties and methods on the
5156    object.
5157
5158    By default, the `this` object will be the `NodeList` that the subscription
5159    came from, <em>not the `Node` that received the event</em>.  Use
5160    `e.currentTarget` to refer to the `Node`.
5161
5162    Returning `false` from a callback is supported as an alternative to calling
5163    `e.preventDefault(); e.stopPropagation();`.  However, it is recommended to
5164    use the event methods.
5165
5166    @example
5167
5168        Y.all(".sku").on("keydown", function (e) {
5169            if (e.keyCode === 13) {
5170                e.preventDefault();
5171
5172                // Use e.currentTarget to refer to the individual Node
5173                var item = Y.MyApp.searchInventory( e.currentTarget.get('value') );
5174                // etc ...
5175            }
5176        });
5177
5178    @method on
5179    @param {String} type The name of the event
5180    @param {Function} fn The callback to execute in response to the event
5181    @param {Object} [context] Override `this` object in callback
5182    @param {Any} [arg*] 0..n additional arguments to supply to the subscriber
5183    @return {EventHandle} A subscription handle capable of detaching that
5184                          subscription
5185    @for NodeList
5186    **/
5187    on: function(type, fn, context) {
5188        return Y.on.apply(Y, this._prepEvtArgs.apply(this, arguments));
5189    },
5190
5191    /**
5192     * Applies an one-time event listener to each Node bound to the NodeList.
5193     * @method once
5194     * @param {String} type The event being listened for
5195     * @param {Function} fn The handler to call when the event fires
5196     * @param {Object} context The context to call the handler with.
5197     * Default is the NodeList instance.
5198     * @return {EventHandle} A subscription handle capable of detaching that
5199     *                    subscription
5200     * @for NodeList
5201     */
5202    once: function(type, fn, context) {
5203        return Y.once.apply(Y, this._prepEvtArgs.apply(this, arguments));
5204    },
5205
5206    /**
5207     * Applies an event listener to each Node bound to the NodeList.
5208     * The handler is called only after all on() handlers are called
5209     * and the event is not prevented.
5210     * @method after
5211     * @param {String} type The event being listened for
5212     * @param {Function} fn The handler to call when the event fires
5213     * @param {Object} context The context to call the handler with.
5214     * Default is the NodeList instance.
5215     * @return {EventHandle} A subscription handle capable of detaching that
5216     *                    subscription
5217     * @for NodeList
5218     */
5219    after: function(type, fn, context) {
5220        return Y.after.apply(Y, this._prepEvtArgs.apply(this, arguments));
5221    },
5222
5223    /**
5224     * Applies an one-time event listener to each Node bound to the NodeList
5225     * that will be called only after all on() handlers are called and the
5226     * event is not prevented.
5227     *
5228     * @method onceAfter
5229     * @param {String} type The event being listened for
5230     * @param {Function} fn The handler to call when the event fires
5231     * @param {Object} context The context to call the handler with.
5232     * Default is the NodeList instance.
5233     * @return {EventHandle} A subscription handle capable of detaching that
5234     *                    subscription
5235     * @for NodeList
5236     */
5237    onceAfter: function(type, fn, context) {
5238        return Y.onceAfter.apply(Y, this._prepEvtArgs.apply(this, arguments));
5239    }
5240});
5241
5242Y_NodeList.importMethod(Y.Node.prototype, [
5243    /**
5244      * Called on each Node instance
5245      * @method detach
5246      * @see Node.detach
5247      * @for NodeList
5248      */
5249    'detach',
5250
5251    /** Called on each Node instance
5252      * @method detachAll
5253      * @see Node.detachAll
5254      * @for NodeList
5255      */
5256    'detachAll'
5257]);
5258
5259/**
5260Subscribe a callback function to execute in response to a DOM event or custom
5261event.
5262
5263Most DOM events are associated with a preventable default behavior such as
5264link clicks navigating to a new page.  Callbacks are passed a `DOMEventFacade`
5265object as their first argument (usually called `e`) that can be used to
5266prevent this default behavior with `e.preventDefault()`. See the
5267`DOMEventFacade` API for all available properties and methods on the object.
5268
5269If the event name passed as the first parameter is not a whitelisted DOM event,
5270it will be treated as a custom event subscriptions, allowing
5271`node.fire('customEventName')` later in the code.  Refer to the Event user guide
5272for the full DOM event whitelist.
5273
5274By default, the `this` object in the callback will refer to the subscribed
5275`Node`.
5276
5277Returning `false` from a callback is supported as an alternative to calling
5278`e.preventDefault(); e.stopPropagation();`.  However, it is recommended to use
5279the event methods.
5280
5281@example
5282
5283    Y.one("#my-form").on("submit", function (e) {
5284        e.preventDefault();
5285
5286        // proceed with ajax form submission instead...
5287    });
5288
5289@method on
5290@param {String} type The name of the event
5291@param {Function} fn The callback to execute in response to the event
5292@param {Object} [context] Override `this` object in callback
5293@param {Any} [arg*] 0..n additional arguments to supply to the subscriber
5294@return {EventHandle} A subscription handle capable of detaching that
5295                      subscription
5296@for Node
5297**/
5298
5299Y.mix(Y.Node.ATTRS, {
5300    offsetHeight: {
5301        setter: function(h) {
5302            Y.DOM.setHeight(this._node, h);
5303            return h;
5304        },
5305
5306        getter: function() {
5307            return this._node.offsetHeight;
5308        }
5309    },
5310
5311    offsetWidth: {
5312        setter: function(w) {
5313            Y.DOM.setWidth(this._node, w);
5314            return w;
5315        },
5316
5317        getter: function() {
5318            return this._node.offsetWidth;
5319        }
5320    }
5321});
5322
5323Y.mix(Y.Node.prototype, {
5324    sizeTo: function(w, h) {
5325        var node;
5326        if (arguments.length < 2) {
5327            node = Y.one(w);
5328            w = node.get('offsetWidth');
5329            h = node.get('offsetHeight');
5330        }
5331
5332        this.setAttrs({
5333            offsetWidth: w,
5334            offsetHeight: h
5335        });
5336    }
5337});
5338
5339if (!Y.config.doc.documentElement.hasAttribute) { // IE < 8
5340    Y.Node.prototype.hasAttribute = function(attr) {
5341        if (attr === 'value') {
5342            if (this.get('value') !== "") { // IE < 8 fails to populate specified when set in HTML
5343                return true;
5344            }
5345        }
5346        return !!(this._node.attributes[attr] &&
5347                this._node.attributes[attr].specified);
5348    };
5349}
5350
5351// IE throws an error when calling focus() on an element that's invisible, not
5352// displayed, or disabled.
5353Y.Node.prototype.focus = function () {
5354    try {
5355        this._node.focus();
5356    } catch (e) {
5357    }
5358
5359    return this;
5360};
5361
5362// IE throws error when setting input.type = 'hidden',
5363// input.setAttribute('type', 'hidden') and input.attributes.type.value = 'hidden'
5364Y.Node.ATTRS.type = {
5365    setter: function(val) {
5366        if (val === 'hidden') {
5367            try {
5368                this._node.type = 'hidden';
5369            } catch(e) {
5370                this._node.style.display = 'none';
5371                this._inputType = 'hidden';
5372            }
5373        } else {
5374            try { // IE errors when changing the type from "hidden'
5375                this._node.type = val;
5376            } catch (e) {
5377            }
5378        }
5379        return val;
5380    },
5381
5382    getter: function() {
5383        return this._inputType || this._node.type;
5384    },
5385
5386    _bypassProxy: true // don't update DOM when using with Attribute
5387};
5388
5389if (Y.config.doc.createElement('form').elements.nodeType) {
5390    // IE: elements collection is also FORM node which trips up scrubVal.
5391    Y.Node.ATTRS.elements = {
5392            getter: function() {
5393                return this.all('input, textarea, button, select');
5394            }
5395    };
5396}
5397/**
5398 * Provides methods for managing custom Node data.
5399 *
5400 * @module node
5401 * @main node
5402 * @submodule node-data
5403 */
5404
5405Y.mix(Y.Node.prototype, {
5406    _initData: function() {
5407        if (! ('_data' in this)) {
5408            this._data = {};
5409        }
5410    },
5411
5412    /**
5413    * @method getData
5414    * @for Node
5415    * @description Retrieves arbitrary data stored on a Node instance.
5416    * If no data is associated with the Node, it will attempt to retrieve
5417    * a value from the corresponding HTML data attribute. (e.g. node.getData('foo')
5418    * will check node.getAttribute('data-foo')).
5419    * @param {string} name Optional name of the data field to retrieve.
5420    * If no name is given, all data is returned.
5421    * @return {any | Object} Whatever is stored at the given field,
5422    * or an object hash of all fields.
5423    */
5424    getData: function(name) {
5425        this._initData();
5426        var data = this._data,
5427            ret = data;
5428
5429        if (arguments.length) { // single field
5430            if (name in data) {
5431                ret = data[name];
5432            } else { // initialize from HTML attribute
5433                ret = this._getDataAttribute(name);
5434            }
5435        } else if (typeof data == 'object' && data !== null) { // all fields
5436            ret = {};
5437            Y.Object.each(data, function(v, n) {
5438                ret[n] = v;
5439            });
5440
5441            ret = this._getDataAttributes(ret);
5442        }
5443
5444        return ret;
5445
5446    },
5447
5448    _getDataAttributes: function(ret) {
5449        ret = ret || {};
5450        var i = 0,
5451            attrs = this._node.attributes,
5452            len = attrs.length,
5453            prefix = this.DATA_PREFIX,
5454            prefixLength = prefix.length,
5455            name;
5456
5457        while (i < len) {
5458            name = attrs[i].name;
5459            if (name.indexOf(prefix) === 0) {
5460                name = name.substr(prefixLength);
5461                if (!(name in ret)) { // only merge if not already stored
5462                    ret[name] = this._getDataAttribute(name);
5463                }
5464            }
5465
5466            i += 1;
5467        }
5468
5469        return ret;
5470    },
5471
5472    _getDataAttribute: function(name) {
5473        name = this.DATA_PREFIX + name;
5474
5475        var node = this._node,
5476            attrs = node.attributes,
5477            data = attrs && attrs[name] && attrs[name].value;
5478
5479        return data;
5480    },
5481
5482    /**
5483    * @method setData
5484    * @for Node
5485    * @description Stores arbitrary data on a Node instance.
5486    * This is not stored with the DOM node.
5487    * @param {string} name The name of the field to set. If no val
5488    * is given, name is treated as the data and overrides any existing data.
5489    * @param {any} val The value to be assigned to the field.
5490    * @chainable
5491    */
5492    setData: function(name, val) {
5493        this._initData();
5494        if (arguments.length > 1) {
5495            this._data[name] = val;
5496        } else {
5497            this._data = name;
5498        }
5499
5500       return this;
5501    },
5502
5503    /**
5504    * @method clearData
5505    * @for Node
5506    * @description Clears internally stored data.
5507    * @param {string} name The name of the field to clear. If no name
5508    * is given, all data is cleared.
5509    * @chainable
5510    */
5511    clearData: function(name) {
5512        if ('_data' in this) {
5513            if (typeof name != 'undefined') {
5514                delete this._data[name];
5515            } else {
5516                delete this._data;
5517            }
5518        }
5519
5520        return this;
5521    }
5522});
5523
5524Y.mix(Y.NodeList.prototype, {
5525    /**
5526    * @method getData
5527    * @for NodeList
5528    * @description Retrieves arbitrary data stored on each Node instance
5529    * bound to the NodeList.
5530    * @see Node
5531    * @param {string} name Optional name of the data field to retrieve.
5532    * If no name is given, all data is returned.
5533    * @return {Array} An array containing all of the data for each Node instance.
5534    * or an object hash of all fields.
5535    */
5536    getData: function(name) {
5537        var args = (arguments.length) ? [name] : [];
5538        return this._invoke('getData', args, true);
5539    },
5540
5541    /**
5542    * @method setData
5543    * @for NodeList
5544    * @description Stores arbitrary data on each Node instance bound to the
5545    *  NodeList. This is not stored with the DOM node.
5546    * @param {string} name The name of the field to set. If no name
5547    * is given, name is treated as the data and overrides any existing data.
5548    * @param {any} val The value to be assigned to the field.
5549    * @chainable
5550    */
5551    setData: function(name, val) {
5552        var args = (arguments.length > 1) ? [name, val] : [name];
5553        return this._invoke('setData', args);
5554    },
5555
5556    /**
5557    * @method clearData
5558    * @for NodeList
5559    * @description Clears data on all Node instances bound to the NodeList.
5560    * @param {string} name The name of the field to clear. If no name
5561    * is given, all data is cleared.
5562    * @chainable
5563    */
5564    clearData: function(name) {
5565        var args = (arguments.length) ? [name] : [];
5566        return this._invoke('clearData', [name]);
5567    }
5568});
5569
5570
5571}, 'patched-v3.18.3', {"requires": ["event-base", "node-core", "dom-base", "dom-style"]});
5572
5573YUI.add('node-core', function (Y, NAME) {
5574
5575/**
5576 * The Node Utility provides a DOM-like interface for interacting with DOM nodes.
5577 * @module node
5578 * @main node
5579 * @submodule node-core
5580 */
5581
5582/**
5583 * The Node class provides a wrapper for manipulating DOM Nodes.
5584 * Node properties can be accessed via the set/get methods.
5585 * Use `Y.one()` to retrieve Node instances.
5586 *
5587 * <strong>NOTE:</strong> Node properties are accessed using
5588 * the <code>set</code> and <code>get</code> methods.
5589 *
5590 * @class Node
5591 * @constructor
5592 * @param {HTMLElement} node the DOM node to be mapped to the Node instance.
5593 * @uses EventTarget
5594 */
5595
5596// "globals"
5597var DOT = '.',
5598    NODE_NAME = 'nodeName',
5599    NODE_TYPE = 'nodeType',
5600    OWNER_DOCUMENT = 'ownerDocument',
5601    TAG_NAME = 'tagName',
5602    UID = '_yuid',
5603    EMPTY_OBJ = {},
5604
5605    _slice = Array.prototype.slice,
5606
5607    Y_DOM = Y.DOM,
5608
5609    Y_Node = function(node) {
5610        if (!this.getDOMNode && !Y.instanceOf(this, Y_Node)) { // support optional "new"
5611            return new Y_Node(node);
5612        }
5613
5614        if (typeof node == 'string') {
5615            node = Y_Node._fromString(node);
5616            if (!node) {
5617                return null; // NOTE: return
5618            }
5619        }
5620
5621        var uid = (node.nodeType !== 9) ? node.uniqueID : node[UID];
5622
5623        if (uid && Y_Node._instances[uid] && Y_Node._instances[uid]._node !== node) {
5624            node[UID] = null; // unset existing uid to prevent collision (via clone or hack)
5625        }
5626
5627        uid = uid || Y.stamp(node);
5628        if (!uid) { // stamp failed; likely IE non-HTMLElement
5629            uid = Y.guid();
5630        }
5631
5632        this[UID] = uid;
5633
5634        /**
5635         * The underlying DOM node bound to the Y.Node instance
5636         * @property _node
5637         * @type HTMLElement
5638         * @private
5639         */
5640        this._node = node;
5641
5642        this._stateProxy = node; // when augmented with Attribute
5643
5644        if (this._initPlugins) { // when augmented with Plugin.Host
5645            this._initPlugins();
5646        }
5647    },
5648
5649    // used with previous/next/ancestor tests
5650    _wrapFn = function(fn) {
5651        var ret = null;
5652        if (fn) {
5653            ret = (typeof fn == 'string') ?
5654            function(n) {
5655                return Y.Selector.test(n, fn);
5656            } :
5657            function(n) {
5658                return fn(Y.one(n));
5659            };
5660        }
5661
5662        return ret;
5663    };
5664// end "globals"
5665
5666Y_Node.ATTRS = {};
5667Y_Node.DOM_EVENTS = {};
5668
5669Y_Node._fromString = function(node) {
5670    if (node) {
5671        if (node.indexOf('doc') === 0) { // doc OR document
5672            node = Y.config.doc;
5673        } else if (node.indexOf('win') === 0) { // win OR window
5674            node = Y.config.win;
5675        } else {
5676            node = Y.Selector.query(node, null, true);
5677        }
5678    }
5679
5680    return node || null;
5681};
5682
5683/**
5684 * The name of the component
5685 * @static
5686 * @type String
5687 * @property NAME
5688 */
5689Y_Node.NAME = 'node';
5690
5691/*
5692 * The pattern used to identify ARIA attributes
5693 */
5694Y_Node.re_aria = /^(?:role$|aria-)/;
5695
5696Y_Node.SHOW_TRANSITION = 'fadeIn';
5697Y_Node.HIDE_TRANSITION = 'fadeOut';
5698
5699/**
5700 * A list of Node instances that have been created
5701 * @private
5702 * @type Object
5703 * @property _instances
5704 * @static
5705 *
5706 */
5707Y_Node._instances = {};
5708
5709/**
5710 * Retrieves the DOM node bound to a Node instance
5711 * @method getDOMNode
5712 * @static
5713 *
5714 * @param {Node|HTMLElement} node The Node instance or an HTMLElement
5715 * @return {HTMLElement} The DOM node bound to the Node instance.  If a DOM node is passed
5716 * as the node argument, it is simply returned.
5717 */
5718Y_Node.getDOMNode = function(node) {
5719    if (node) {
5720        return (node.nodeType) ? node : node._node || null;
5721    }
5722    return null;
5723};
5724
5725/**
5726 * Checks Node return values and wraps DOM Nodes as Y.Node instances
5727 * and DOM Collections / Arrays as Y.NodeList instances.
5728 * Other return values just pass thru.  If undefined is returned (e.g. no return)
5729 * then the Node instance is returned for chainability.
5730 * @method scrubVal
5731 * @static
5732 *
5733 * @param {HTMLElement|HTMLElement[]|Node} node The Node instance or an HTMLElement
5734 * @return {Node | NodeList | Any} Depends on what is returned from the DOM node.
5735 */
5736Y_Node.scrubVal = function(val, node) {
5737    if (val) { // only truthy values are risky
5738         if (typeof val == 'object' || typeof val == 'function') { // safari nodeList === function
5739            if (NODE_TYPE in val || Y_DOM.isWindow(val)) {// node || window
5740                val = Y.one(val);
5741            } else if ((val.item && !val._nodes) || // dom collection or Node instance
5742                    (val[0] && val[0][NODE_TYPE])) { // array of DOM Nodes
5743                val = Y.all(val);
5744            }
5745        }
5746    } else if (typeof val === 'undefined') {
5747        val = node; // for chaining
5748    } else if (val === null) {
5749        val = null; // IE: DOM null not the same as null
5750    }
5751
5752    return val;
5753};
5754
5755/**
5756 * Adds methods to the Y.Node prototype, routing through scrubVal.
5757 * @method addMethod
5758 * @static
5759 *
5760 * @param {String} name The name of the method to add
5761 * @param {Function} fn The function that becomes the method
5762 * @param {Object} context An optional context to call the method with
5763 * (defaults to the Node instance)
5764 * @return {any} Depends on what is returned from the DOM node.
5765 */
5766Y_Node.addMethod = function(name, fn, context) {
5767    if (name && fn && typeof fn == 'function') {
5768        Y_Node.prototype[name] = function() {
5769            var args = _slice.call(arguments),
5770                node = this,
5771                ret;
5772
5773            if (args[0] && args[0]._node) {
5774                args[0] = args[0]._node;
5775            }
5776
5777            if (args[1] && args[1]._node) {
5778                args[1] = args[1]._node;
5779            }
5780            args.unshift(node._node);
5781
5782            ret = fn.apply(context || node, args);
5783
5784            if (ret) { // scrub truthy
5785                ret = Y_Node.scrubVal(ret, node);
5786            }
5787
5788            (typeof ret != 'undefined') || (ret = node);
5789            return ret;
5790        };
5791    } else {
5792    }
5793};
5794
5795/**
5796 * Imports utility methods to be added as Y.Node methods.
5797 * @method importMethod
5798 * @static
5799 *
5800 * @param {Object} host The object that contains the method to import.
5801 * @param {String} name The name of the method to import
5802 * @param {String} altName An optional name to use in place of the host name
5803 * @param {Object} context An optional context to call the method with
5804 */
5805Y_Node.importMethod = function(host, name, altName) {
5806    if (typeof name == 'string') {
5807        altName = altName || name;
5808        Y_Node.addMethod(altName, host[name], host);
5809    } else {
5810        Y.Array.each(name, function(n) {
5811            Y_Node.importMethod(host, n);
5812        });
5813    }
5814};
5815
5816/**
5817 * Retrieves a NodeList based on the given CSS selector.
5818 * @method all
5819 *
5820 * @param {string} selector The CSS selector to test against.
5821 * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
5822 * @for YUI
5823 */
5824
5825/**
5826 * Returns a single Node instance bound to the node or the
5827 * first element matching the given selector. Returns null if no match found.
5828 * <strong>Note:</strong> For chaining purposes you may want to
5829 * use <code>Y.all</code>, which returns a NodeList when no match is found.
5830 * @method one
5831 * @param {String | HTMLElement} node a node or Selector
5832 * @return {Node | null} a Node instance or null if no match found.
5833 * @for YUI
5834 */
5835
5836/**
5837 * Returns a single Node instance bound to the node or the
5838 * first element matching the given selector. Returns null if no match found.
5839 * <strong>Note:</strong> For chaining purposes you may want to
5840 * use <code>Y.all</code>, which returns a NodeList when no match is found.
5841 * @method one
5842 * @static
5843 * @param {String | HTMLElement} node a node or Selector
5844 * @return {Node | null} a Node instance or null if no match found.
5845 * @for Node
5846 */
5847Y_Node.one = function(node) {
5848    var instance = null,
5849        cachedNode,
5850        uid;
5851
5852    if (node) {
5853        if (typeof node == 'string') {
5854            node = Y_Node._fromString(node);
5855            if (!node) {
5856                return null; // NOTE: return
5857            }
5858        } else if (node.getDOMNode && Y.instanceOf(node, Y_Node)) {
5859            return node; // NOTE: return
5860        }
5861
5862        if (node.nodeType || Y.DOM.isWindow(node)) { // avoid bad input (numbers, boolean, etc)
5863            uid = (node.uniqueID && node.nodeType !== 9) ? node.uniqueID : node._yuid;
5864            instance = Y_Node._instances[uid]; // reuse exising instances
5865            cachedNode = instance ? instance._node : null;
5866            if (!instance || (cachedNode && node !== cachedNode)) { // new Node when nodes don't match
5867                instance = new Y_Node(node);
5868                if (node.nodeType != 11) { // dont cache document fragment
5869                    Y_Node._instances[instance[UID]] = instance; // cache node
5870                }
5871            }
5872        }
5873    }
5874
5875    return instance;
5876};
5877
5878/**
5879 * The default setter for DOM properties
5880 * Called with instance context (this === the Node instance)
5881 * @method DEFAULT_SETTER
5882 * @static
5883 * @param {String} name The attribute/property being set
5884 * @param {any} val The value to be set
5885 * @return {any} The value
5886 */
5887Y_Node.DEFAULT_SETTER = function(name, val) {
5888    var node = this._stateProxy,
5889        strPath;
5890
5891    if (name.indexOf(DOT) > -1) {
5892        strPath = name;
5893        name = name.split(DOT);
5894        // only allow when defined on node
5895        Y.Object.setValue(node, name, val);
5896    } else if (typeof node[name] != 'undefined') { // pass thru DOM properties
5897        node[name] = val;
5898    }
5899
5900    return val;
5901};
5902
5903/**
5904 * The default getter for DOM properties
5905 * Called with instance context (this === the Node instance)
5906 * @method DEFAULT_GETTER
5907 * @static
5908 * @param {String} name The attribute/property to look up
5909 * @return {any} The current value
5910 */
5911Y_Node.DEFAULT_GETTER = function(name) {
5912    var node = this._stateProxy,
5913        val;
5914
5915    if (name.indexOf && name.indexOf(DOT) > -1) {
5916        val = Y.Object.getValue(node, name.split(DOT));
5917    } else if (typeof node[name] != 'undefined') { // pass thru from DOM
5918        val = node[name];
5919    }
5920
5921    return val;
5922};
5923
5924Y.mix(Y_Node.prototype, {
5925    DATA_PREFIX: 'data-',
5926
5927    /**
5928     * The method called when outputting Node instances as strings
5929     * @method toString
5930     * @return {String} A string representation of the Node instance
5931     */
5932    toString: function() {
5933        var str = this[UID] + ': not bound to a node',
5934            node = this._node,
5935            attrs, id, className;
5936
5937        if (node) {
5938            attrs = node.attributes;
5939            id = (attrs && attrs.id) ? node.getAttribute('id') : null;
5940            className = (attrs && attrs.className) ? node.getAttribute('className') : null;
5941            str = node[NODE_NAME];
5942
5943            if (id) {
5944                str += '#' + id;
5945            }
5946
5947            if (className) {
5948                str += '.' + className.replace(' ', '.');
5949            }
5950
5951            // TODO: add yuid?
5952            str += ' ' + this[UID];
5953        }
5954        return str;
5955    },
5956
5957    /**
5958     * Returns an attribute value on the Node instance.
5959     * Unless pre-configured (via `Node.ATTRS`), get hands
5960     * off to the underlying DOM node.  Only valid
5961     * attributes/properties for the node will be queried.
5962     * @method get
5963     * @param {String} attr The attribute
5964     * @return {any} The current value of the attribute
5965     */
5966    get: function(attr) {
5967        var val;
5968
5969        if (this._getAttr) { // use Attribute imple
5970            val = this._getAttr(attr);
5971        } else {
5972            val = this._get(attr);
5973        }
5974
5975        if (val) {
5976            val = Y_Node.scrubVal(val, this);
5977        } else if (val === null) {
5978            val = null; // IE: DOM null is not true null (even though they ===)
5979        }
5980        return val;
5981    },
5982
5983    /**
5984     * Helper method for get.
5985     * @method _get
5986     * @private
5987     * @param {String} attr The attribute
5988     * @return {any} The current value of the attribute
5989     */
5990    _get: function(attr) {
5991        var attrConfig = Y_Node.ATTRS[attr],
5992            val;
5993
5994        if (attrConfig && attrConfig.getter) {
5995            val = attrConfig.getter.call(this);
5996        } else if (Y_Node.re_aria.test(attr)) {
5997            val = this._node.getAttribute(attr, 2);
5998        } else {
5999            val = Y_Node.DEFAULT_GETTER.apply(this, arguments);
6000        }
6001
6002        return val;
6003    },
6004
6005    /**
6006     * Sets an attribute on the Node instance.
6007     * Unless pre-configured (via Node.ATTRS), set hands
6008     * off to the underlying DOM node.  Only valid
6009     * attributes/properties for the node will be set.
6010     * To set custom attributes use setAttribute.
6011     * @method set
6012     * @param {String} attr The attribute to be set.
6013     * @param {any} val The value to set the attribute to.
6014     * @chainable
6015     */
6016    set: function(attr, val) {
6017        var attrConfig = Y_Node.ATTRS[attr];
6018
6019        if (this._setAttr) { // use Attribute imple
6020            this._setAttr.apply(this, arguments);
6021        } else { // use setters inline
6022            if (attrConfig && attrConfig.setter) {
6023                attrConfig.setter.call(this, val, attr);
6024            } else if (Y_Node.re_aria.test(attr)) { // special case Aria
6025                this._node.setAttribute(attr, val);
6026            } else {
6027                Y_Node.DEFAULT_SETTER.apply(this, arguments);
6028            }
6029        }
6030
6031        return this;
6032    },
6033
6034    /**
6035     * Sets multiple attributes.
6036     * @method setAttrs
6037     * @param {Object} attrMap an object of name/value pairs to set
6038     * @chainable
6039     */
6040    setAttrs: function(attrMap) {
6041        if (this._setAttrs) { // use Attribute imple
6042            this._setAttrs(attrMap);
6043        } else { // use setters inline
6044            Y.Object.each(attrMap, function(v, n) {
6045                this.set(n, v);
6046            }, this);
6047        }
6048
6049        return this;
6050    },
6051
6052    /**
6053     * Returns an object containing the values for the requested attributes.
6054     * @method getAttrs
6055     * @param {Array} attrs an array of attributes to get values
6056     * @return {Object} An object with attribute name/value pairs.
6057     */
6058    getAttrs: function(attrs) {
6059        var ret = {};
6060        if (this._getAttrs) { // use Attribute imple
6061            this._getAttrs(attrs);
6062        } else { // use setters inline
6063            Y.Array.each(attrs, function(v, n) {
6064                ret[v] = this.get(v);
6065            }, this);
6066        }
6067
6068        return ret;
6069    },
6070
6071    /**
6072     * Compares nodes to determine if they match.
6073     * Node instances can be compared to each other and/or HTMLElements.
6074     * @method compareTo
6075     * @param {HTMLElement | Node} refNode The reference node to compare to the node.
6076     * @return {Boolean} True if the nodes match, false if they do not.
6077     */
6078    compareTo: function(refNode) {
6079        var node = this._node;
6080
6081        if (refNode && refNode._node) {
6082            refNode = refNode._node;
6083        }
6084        return node === refNode;
6085    },
6086
6087    /**
6088     * Determines whether the node is appended to the document.
6089     * @method inDoc
6090     * @param {Node|HTMLElement} doc optional An optional document to check against.
6091     * Defaults to current document.
6092     * @return {Boolean} Whether or not this node is appended to the document.
6093     */
6094    inDoc: function(doc) {
6095        var node = this._node;
6096
6097        if (node) {
6098            doc = (doc) ? doc._node || doc : node[OWNER_DOCUMENT];
6099            if (doc.documentElement) {
6100                return Y_DOM.contains(doc.documentElement, node);
6101            }
6102        }
6103
6104        return false;
6105    },
6106
6107    getById: function(id) {
6108        var node = this._node,
6109            ret = Y_DOM.byId(id, node[OWNER_DOCUMENT]);
6110        if (ret && Y_DOM.contains(node, ret)) {
6111            ret = Y.one(ret);
6112        } else {
6113            ret = null;
6114        }
6115        return ret;
6116    },
6117
6118   /**
6119     * Returns the nearest ancestor that passes the test applied by supplied boolean method.
6120     * @method ancestor
6121     * @param {String | Function} fn A selector string or boolean method for testing elements.
6122     * If a function is used, it receives the current node being tested as the only argument.
6123     * If fn is not passed as an argument, the parent node will be returned.
6124     * @param {Boolean} testSelf optional Whether or not to include the element in the scan
6125     * @param {String | Function} stopFn optional A selector string or boolean
6126     * method to indicate when the search should stop. The search bails when the function
6127     * returns true or the selector matches.
6128     * If a function is used, it receives the current node being tested as the only argument.
6129     * @return {Node} The matching Node instance or null if not found
6130     */
6131    ancestor: function(fn, testSelf, stopFn) {
6132        // testSelf is optional, check for stopFn as 2nd arg
6133        if (arguments.length === 2 &&
6134                (typeof testSelf == 'string' || typeof testSelf == 'function')) {
6135            stopFn = testSelf;
6136        }
6137
6138        return Y.one(Y_DOM.ancestor(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
6139    },
6140
6141   /**
6142     * Returns the ancestors that pass the test applied by supplied boolean method.
6143     * @method ancestors
6144     * @param {String | Function} fn A selector string or boolean method for testing elements.
6145     * @param {Boolean} testSelf optional Whether or not to include the element in the scan
6146     * If a function is used, it receives the current node being tested as the only argument.
6147     * @return {NodeList} A NodeList instance containing the matching elements
6148     */
6149    ancestors: function(fn, testSelf, stopFn) {
6150        if (arguments.length === 2 &&
6151                (typeof testSelf == 'string' || typeof testSelf == 'function')) {
6152            stopFn = testSelf;
6153        }
6154        return Y.all(Y_DOM.ancestors(this._node, _wrapFn(fn), testSelf, _wrapFn(stopFn)));
6155    },
6156
6157    /**
6158     * Returns the previous matching sibling.
6159     * Returns the nearest element node sibling if no method provided.
6160     * @method previous
6161     * @param {String | Function} fn A selector or boolean method for testing elements.
6162     * If a function is used, it receives the current node being tested as the only argument.
6163     * @param {Boolean} [all] Whether text nodes as well as element nodes should be returned, or
6164     * just element nodes will be returned(default)
6165     * @return {Node} Node instance or null if not found
6166     */
6167    previous: function(fn, all) {
6168        return Y.one(Y_DOM.elementByAxis(this._node, 'previousSibling', _wrapFn(fn), all));
6169    },
6170
6171    /**
6172     * Returns the next matching sibling.
6173     * Returns the nearest element node sibling if no method provided.
6174     * @method next
6175     * @param {String | Function} fn A selector or boolean method for testing elements.
6176     * If a function is used, it receives the current node being tested as the only argument.
6177     * @param {Boolean} [all] Whether text nodes as well as element nodes should be returned, or
6178     * just element nodes will be returned(default)
6179     * @return {Node} Node instance or null if not found
6180     */
6181    next: function(fn, all) {
6182        return Y.one(Y_DOM.elementByAxis(this._node, 'nextSibling', _wrapFn(fn), all));
6183    },
6184
6185    /**
6186     * Returns all matching siblings.
6187     * Returns all siblings if no method provided.
6188     * @method siblings
6189     * @param {String | Function} fn A selector or boolean method for testing elements.
6190     * If a function is used, it receives the current node being tested as the only argument.
6191     * @return {NodeList} NodeList instance bound to found siblings
6192     */
6193    siblings: function(fn) {
6194        return Y.all(Y_DOM.siblings(this._node, _wrapFn(fn)));
6195    },
6196
6197    /**
6198     * Retrieves a single Node instance, the first element matching the given
6199     * CSS selector.
6200     * Returns null if no match found.
6201     * @method one
6202     *
6203     * @param {string} selector The CSS selector to test against.
6204     * @return {Node | null} A Node instance for the matching HTMLElement or null
6205     * if no match found.
6206     */
6207    one: function(selector) {
6208        return Y.one(Y.Selector.query(selector, this._node, true));
6209    },
6210
6211    /**
6212     * Retrieves a NodeList based on the given CSS selector.
6213     * @method all
6214     *
6215     * @param {string} selector The CSS selector to test against.
6216     * @return {NodeList} A NodeList instance for the matching HTMLCollection/Array.
6217     */
6218    all: function(selector) {
6219        var nodelist;
6220
6221        if (this._node) {
6222            nodelist = Y.all(Y.Selector.query(selector, this._node));
6223            nodelist._query = selector;
6224            nodelist._queryRoot = this._node;
6225        }
6226
6227        return nodelist || Y.all([]);
6228    },
6229
6230    // TODO: allow fn test
6231    /**
6232     * Test if the supplied node matches the supplied selector.
6233     * @method test
6234     *
6235     * @param {string} selector The CSS selector to test against.
6236     * @return {boolean} Whether or not the node matches the selector.
6237     */
6238    test: function(selector) {
6239        return Y.Selector.test(this._node, selector);
6240    },
6241
6242    /**
6243     * Removes the node from its parent.
6244     * Shortcut for myNode.get('parentNode').removeChild(myNode);
6245     * @method remove
6246     * @param {Boolean} destroy whether or not to call destroy() on the node
6247     * after removal.
6248     * @chainable
6249     *
6250     */
6251    remove: function(destroy) {
6252        var node = this._node;
6253
6254        if (node && node.parentNode) {
6255            node.parentNode.removeChild(node);
6256        }
6257
6258        if (destroy) {
6259            this.destroy();
6260        }
6261
6262        return this;
6263    },
6264
6265    /**
6266     * Replace the node with the other node. This is a DOM update only
6267     * and does not change the node bound to the Node instance.
6268     * Shortcut for myNode.get('parentNode').replaceChild(newNode, myNode);
6269     * @method replace
6270     * @param {Node | HTMLElement} newNode Node to be inserted
6271     * @chainable
6272     *
6273     */
6274    replace: function(newNode) {
6275        var node = this._node;
6276        if (typeof newNode == 'string') {
6277            newNode = Y_Node.create(newNode);
6278        }
6279        node.parentNode.replaceChild(Y_Node.getDOMNode(newNode), node);
6280        return this;
6281    },
6282
6283    /**
6284     * @method replaceChild
6285     * @for Node
6286     * @param {String | HTMLElement | Node} node Node to be inserted
6287     * @param {HTMLElement | Node} refNode Node to be replaced
6288     * @return {Node} The replaced node
6289     */
6290    replaceChild: function(node, refNode) {
6291        if (typeof node == 'string') {
6292            node = Y_DOM.create(node);
6293        }
6294
6295        return Y.one(this._node.replaceChild(Y_Node.getDOMNode(node), Y_Node.getDOMNode(refNode)));
6296    },
6297
6298    /**
6299     * Nulls internal node references, removes any plugins and event listeners.
6300     * Note that destroy() will not remove the node from its parent or from the DOM. For that
6301     * functionality, call remove(true).
6302     * @method destroy
6303     * @param {Boolean} recursivePurge (optional) Whether or not to remove listeners from the
6304     * node's subtree (default is false)
6305     *
6306     */
6307    destroy: function(recursive) {
6308        var UID = Y.config.doc.uniqueID ? 'uniqueID' : '_yuid',
6309            instance;
6310
6311        this.purge(); // TODO: only remove events add via this Node
6312
6313        if (this.unplug) { // may not be a PluginHost
6314            this.unplug();
6315        }
6316
6317        this.clearData();
6318
6319        if (recursive) {
6320            Y.NodeList.each(this.all('*'), function(node) {
6321                instance = Y_Node._instances[node[UID]];
6322                if (instance) {
6323                   instance.destroy();
6324                } else { // purge in case added by other means
6325                    Y.Event.purgeElement(node);
6326                }
6327            });
6328        }
6329
6330        this._node = null;
6331        this._stateProxy = null;
6332
6333        delete Y_Node._instances[this._yuid];
6334    },
6335
6336    /**
6337     * Invokes a method on the Node instance
6338     * @method invoke
6339     * @param {String} method The name of the method to invoke
6340     * @param {any} [args*] Arguments to invoke the method with.
6341     * @return {any} Whatever the underly method returns.
6342     * DOM Nodes and Collections return values
6343     * are converted to Node/NodeList instances.
6344     *
6345     */
6346    invoke: function(method, a, b, c, d, e) {
6347        var node = this._node,
6348            ret;
6349
6350        if (a && a._node) {
6351            a = a._node;
6352        }
6353
6354        if (b && b._node) {
6355            b = b._node;
6356        }
6357
6358        ret = node[method](a, b, c, d, e);
6359        return Y_Node.scrubVal(ret, this);
6360    },
6361
6362    /**
6363    * @method swap
6364    * @description Swap DOM locations with the given node.
6365    * This does not change which DOM node each Node instance refers to.
6366    * @param {Node} otherNode The node to swap with
6367     * @chainable
6368    */
6369    swap: Y.config.doc.documentElement.swapNode ?
6370        function(otherNode) {
6371            this._node.swapNode(Y_Node.getDOMNode(otherNode));
6372        } :
6373        function(otherNode) {
6374            otherNode = Y_Node.getDOMNode(otherNode);
6375            var node = this._node,
6376                parent = otherNode.parentNode,
6377                nextSibling = otherNode.nextSibling;
6378
6379            if (nextSibling === node) {
6380                parent.insertBefore(node, otherNode);
6381            } else if (otherNode === node.nextSibling) {
6382                parent.insertBefore(otherNode, node);
6383            } else {
6384                node.parentNode.replaceChild(otherNode, node);
6385                Y_DOM.addHTML(parent, node, nextSibling);
6386            }
6387            return this;
6388        },
6389
6390
6391    hasMethod: function(method) {
6392        var node = this._node;
6393        return !!(node && method in node &&
6394                typeof node[method] != 'unknown' &&
6395            (typeof node[method] == 'function' ||
6396                String(node[method]).indexOf('function') === 1)); // IE reports as object, prepends space
6397    },
6398
6399    isFragment: function() {
6400        return (this.get('nodeType') === 11);
6401    },
6402
6403    /**
6404     * Removes and destroys all of the nodes within the node.
6405     * @method empty
6406     * @chainable
6407     */
6408    empty: function() {
6409        this.get('childNodes').remove().destroy(true);
6410        return this;
6411    },
6412
6413    /**
6414     * Returns the DOM node bound to the Node instance
6415     * @method getDOMNode
6416     * @return {HTMLElement}
6417     */
6418    getDOMNode: function() {
6419        return this._node;
6420    }
6421}, true);
6422
6423Y.Node = Y_Node;
6424Y.one = Y_Node.one;
6425/**
6426 * The NodeList module provides support for managing collections of Nodes.
6427 * @module node
6428 * @submodule node-core
6429 */
6430
6431/**
6432 * The NodeList class provides a wrapper for manipulating DOM NodeLists.
6433 * NodeList properties can be accessed via the set/get methods.
6434 * Use Y.all() to retrieve NodeList instances.
6435 *
6436 * @class NodeList
6437 * @constructor
6438 * @param nodes {String|element|Node|Array} A selector, DOM element, Node, list of DOM elements, or list of Nodes with which to populate this NodeList.
6439 */
6440
6441var NodeList = function(nodes) {
6442    var tmp = [];
6443
6444    if (nodes) {
6445        if (typeof nodes === 'string') { // selector query
6446            this._query = nodes;
6447            nodes = Y.Selector.query(nodes);
6448        } else if (nodes.nodeType || Y_DOM.isWindow(nodes)) { // domNode || window
6449            nodes = [nodes];
6450        } else if (nodes._node) { // Y.Node
6451            nodes = [nodes._node];
6452        } else if (nodes[0] && nodes[0]._node) { // allow array of Y.Nodes
6453            Y.Array.each(nodes, function(node) {
6454                if (node._node) {
6455                    tmp.push(node._node);
6456                }
6457            });
6458            nodes = tmp;
6459        } else { // array of domNodes or domNodeList (no mixed array of Y.Node/domNodes)
6460            nodes = Y.Array(nodes, 0, true);
6461        }
6462    }
6463
6464    /**
6465     * The underlying array of DOM nodes bound to the Y.NodeList instance
6466     * @property _nodes
6467     * @private
6468     */
6469    this._nodes = nodes || [];
6470};
6471
6472NodeList.NAME = 'NodeList';
6473
6474/**
6475 * Retrieves the DOM nodes bound to a NodeList instance
6476 * @method getDOMNodes
6477 * @static
6478 *
6479 * @param {NodeList} nodelist The NodeList instance
6480 * @return {Array} The array of DOM nodes bound to the NodeList
6481 */
6482NodeList.getDOMNodes = function(nodelist) {
6483    return (nodelist && nodelist._nodes) ? nodelist._nodes : nodelist;
6484};
6485
6486NodeList.each = function(instance, fn, context) {
6487    var nodes = instance._nodes;
6488    if (nodes && nodes.length) {
6489        Y.Array.each(nodes, fn, context || instance);
6490    } else {
6491    }
6492};
6493
6494NodeList.addMethod = function(name, fn, context) {
6495    if (name && fn) {
6496        NodeList.prototype[name] = function() {
6497            var ret = [],
6498                args = arguments;
6499
6500            Y.Array.each(this._nodes, function(node) {
6501                var UID = (node.uniqueID && node.nodeType !== 9 ) ? 'uniqueID' : '_yuid',
6502                    instance = Y.Node._instances[node[UID]],
6503                    ctx,
6504                    result;
6505
6506                if (!instance) {
6507                    instance = NodeList._getTempNode(node);
6508                }
6509                ctx = context || instance;
6510                result = fn.apply(ctx, args);
6511                if (result !== undefined && result !== instance) {
6512                    ret[ret.length] = result;
6513                }
6514            });
6515
6516            // TODO: remove tmp pointer
6517            return ret.length ? ret : this;
6518        };
6519    } else {
6520    }
6521};
6522
6523/**
6524 * Import the named method, or methods from the host onto NodeList.
6525 *
6526 * @method importMethod
6527 * @static
6528 * @param {Object}
6528 host The object containing the methods to copy. Typically a prototype.
6529 * @param {String|String[]} name The name, or an Array of names of the methods to import onto NodeList.
6530 * @param {String} [altName] An alternative name to use for the method added to NodeList, which may differ from the name
6531 * of the original host object. Has no effect if <em>name</em> is an array of method names.
6532 */
6533NodeList.importMethod = function(host, name, altName) {
6534    if (typeof name === 'string') {
6535        altName = altName || name;
6536        NodeList.addMethod(altName, host[name]);
6537    } else {
6538        Y.Array.each(name, function(n) {
6539            NodeList.importMethod(host, n);
6540        });
6541    }
6542};
6543
6544NodeList._getTempNode = function(node) {
6545    var tmp = NodeList._tempNode;
6546    if (!tmp) {
6547        tmp = Y.Node.create('<div></div>');
6548        NodeList._tempNode = tmp;
6549    }
6550
6551    tmp._node = node;
6552    tmp._stateProxy = node;
6553    return tmp;
6554};
6555
6556Y.mix(NodeList.prototype, {
6557    _invoke: function(method, args, getter) {
6558        var ret = (getter) ? [] : this;
6559
6560        this.each(function(node) {
6561            var val = node[method].apply(node, args);
6562            if (getter) {
6563                ret.push(val);
6564            }
6565        });
6566
6567        return ret;
6568    },
6569
6570    /**
6571     * Retrieves the Node instance at the given index.
6572     * @method item
6573     *
6574     * @param {Number} index The index of the target Node.
6575     * @return {Node} The Node instance at the given index.
6576     */
6577    item: function(index) {
6578        return Y.one((this._nodes || [])[index]);
6579    },
6580
6581    /**
6582     * Applies the given function to each Node in the NodeList.
6583     * @method each
6584     * @param {Function} fn The function to apply. It receives 3 arguments:
6585     * the current node instance, the node's index, and the NodeList instance
6586     * @param {Object} context optional An optional context to apply the function with
6587     * Default context is the current Node instance
6588     * @chainable
6589     */
6590    each: function(fn, context) {
6591        var instance = this;
6592        Y.Array.each(this._nodes, function(node, index) {
6593            node = Y.one(node);
6594            return fn.call(context || node, node, index, instance);
6595        });
6596        return instance;
6597    },
6598
6599    batch: function(fn, context) {
6600        var nodelist = this;
6601
6602        Y.Array.each(this._nodes, function(node, index) {
6603            var instance = Y.Node._instances[node[UID]];
6604            if (!instance) {
6605                instance = NodeList._getTempNode(node);
6606            }
6607
6608            return fn.call(context || instance, instance, index, nodelist);
6609        });
6610        return nodelist;
6611    },
6612
6613    /**
6614     * Executes the function once for each node until a true value is returned.
6615     * @method some
6616     * @param {Function} fn The function to apply. It receives 3 arguments:
6617     * the current node instance, the node's index, and the NodeList instance
6618     * @param {Object} context optional An optional context to execute the function from.
6619     * Default context is the current Node instance
6620     * @return {Boolean} Whether or not the function returned true for any node.
6621     */
6622    some: function(fn, context) {
6623        var instance = this;
6624        return Y.Array.some(this._nodes, function(node, index) {
6625            node = Y.one(node);
6626            context = context || node;
6627            return fn.call(context, node, index, instance);
6628        });
6629    },
6630
6631    /**
6632     * Creates a documenFragment from the nodes bound to the NodeList instance
6633     * @method toFrag
6634     * @return {Node} a Node instance bound to the documentFragment
6635     */
6636    toFrag: function() {
6637        return Y.one(Y.DOM._nl2frag(this._nodes));
6638    },
6639
6640    /**
6641     * Returns the index of the node in the NodeList instance
6642     * or -1 if the node isn't found.
6643     * @method indexOf
6644     * @param {Node | HTMLElement} node the node to search for
6645     * @return {Number} the index of the node value or -1 if not found
6646     */
6647    indexOf: function(node) {
6648        return Y.Array.indexOf(this._nodes, Y.Node.getDOMNode(node));
6649    },
6650
6651    /**
6652     * Filters the NodeList instance down to only nodes matching the given selector.
6653     * @method filter
6654     * @param {String} selector The selector to filter against
6655     * @return {NodeList} NodeList containing the updated collection
6656     * @see Selector
6657     */
6658    filter: function(selector) {
6659        return Y.all(Y.Selector.filter(this._nodes, selector));
6660    },
6661
6662
6663    /**
6664     * Creates a new NodeList containing all nodes at every n indices, where
6665     * remainder n % index equals r.
6666     * (zero-based index).
6667     * @method modulus
6668     * @param {Number} n The offset to use (return every nth node)
6669     * @param {Number} r An optional remainder to use with the modulus operation (defaults to zero)
6670     * @return {NodeList} NodeList containing the updated collection
6671     */
6672    modulus: function(n, r) {
6673        r = r || 0;
6674        var nodes = [];
6675        NodeList.each(this, function(node, i) {
6676            if (i % n === r) {
6677                nodes.push(node);
6678            }
6679        });
6680
6681        return Y.all(nodes);
6682    },
6683
6684    /**
6685     * Creates a new NodeList containing all nodes at odd indices
6686     * (zero-based index).
6687     * @method odd
6688     * @return {NodeList} NodeList containing the updated collection
6689     */
6690    odd: function() {
6691        return this.modulus(2, 1);
6692    },
6693
6694    /**
6695     * Creates a new NodeList containing all nodes at even indices
6696     * (zero-based index), including zero.
6697     * @method even
6698     * @return {NodeList} NodeList containing the updated collection
6699     */
6700    even: function() {
6701        return this.modulus(2);
6702    },
6703
6704    destructor: function() {
6705    },
6706
6707    /**
6708     * Reruns the initial query, when created using a selector query
6709     * @method refresh
6710     * @chainable
6711     */
6712    refresh: function() {
6713        var doc,
6714            nodes = this._nodes,
6715            query = this._query,
6716            root = this._queryRoot;
6717
6718        if (query) {
6719            if (!root) {
6720                if (nodes && nodes[0] && nodes[0].ownerDocument) {
6721                    root = nodes[0].ownerDocument;
6722                }
6723            }
6724
6725            this._nodes = Y.Selector.query(query, root);
6726        }
6727
6728        return this;
6729    },
6730
6731    /**
6732     * Returns the current number of items in the NodeList.
6733     * @method size
6734     * @return {Number} The number of items in the NodeList.
6735     */
6736    size: function() {
6737        return this._nodes.length;
6738    },
6739
6740    /**
6741     * Determines if the instance is bound to any nodes
6742     * @method isEmpty
6743     * @return {Boolean} Whether or not the NodeList is bound to any nodes
6744     */
6745    isEmpty: function() {
6746        return this._nodes.length < 1;
6747    },
6748
6749    toString: function() {
6750        var str = '',
6751            errorMsg = this[UID] + ': not bound to any nodes',
6752            nodes = this._nodes,
6753            node;
6754
6755        if (nodes && nodes[0]) {
6756            node = nodes[0];
6757            str += node[NODE_NAME];
6758            if (node.id) {
6759                str += '#' + node.id;
6760            }
6761
6762            if (node.className) {
6763                str += '.' + node.className.replace(' ', '.');
6764            }
6765
6766            if (nodes.length > 1) {
6767                str += '...[' + nodes.length + ' items]';
6768            }
6769        }
6770        return str || errorMsg;
6771    },
6772
6773    /**
6774     * Returns the DOM node bound to the Node instance
6775     * @method getDOMNodes
6776     * @return {Array}
6777     */
6778    getDOMNodes: function() {
6779        return this._nodes;
6780    }
6781}, true);
6782
6783NodeList.importMethod(Y.Node.prototype, [
6784     /**
6785      * Called on each Node instance. Nulls internal node references,
6786      * removes any plugins and event listeners
6787      * @method destroy
6788      * @param {Boolean} recursivePurge (optional) Whether or not to
6789      * remove listeners from the node's subtree (default is false)
6790      * @see Node.destroy
6791      */
6792    'destroy',
6793
6794     /**
6795      * Called on each Node instance. Removes and destroys all of the nodes
6796      * within the node
6797      * @method empty
6798      * @chainable
6799      * @see Node.empty
6800      */
6801    'empty',
6802
6803     /**
6804      * Called on each Node instance. Removes the node from its parent.
6805      * Shortcut for myNode.get('parentNode').removeChild(myNode);
6806      * @method remove
6807      * @param {Boolean} destroy whether or not to call destroy() on the node
6808      * after removal.
6809      * @chainable
6810      * @see Node.remove
6811      */
6812    'remove',
6813
6814     /**
6815      * Called on each Node instance. Sets an attribute on the Node instance.
6816      * Unless pre-configured (via Node.ATTRS), set hands
6817      * off to the underlying DOM node.  Only valid
6818      * attributes/properties for the node will be set.
6819      * To set custom attributes use setAttribute.
6820      * @method set
6821      * @param {String} attr The attribute to be set.
6822      * @param {any} val The value to set the attribute to.
6823      * @chainable
6824      * @see Node.set
6825      */
6826    'set'
6827]);
6828
6829// one-off implementation to convert array of Nodes to NodeList
6830// e.g. Y.all('input').get('parentNode');
6831
6832/** Called on each Node instance
6833  * @method get
6834  * @see Node
6835  */
6836NodeList.prototype.get = function(attr) {
6837    var ret = [],
6838        nodes = this._nodes,
6839        isNodeList = false,
6840        getTemp = NodeList._getTempNode,
6841        instance,
6842        val;
6843
6844    if (nodes[0]) {
6845        instance = Y.Node._instances[nodes[0]._yuid] || getTemp(nodes[0]);
6846        val = instance._get(attr);
6847        if (val && val.nodeType) {
6848            isNodeList = true;
6849        }
6850    }
6851
6852    Y.Array.each(nodes, function(node) {
6853        instance = Y.Node._instances[node._yuid];
6854
6855        if (!instance) {
6856            instance = getTemp(node);
6857        }
6858
6859        val = instance._get(attr);
6860        if (!isNodeList) { // convert array of Nodes to NodeList
6861            val = Y.Node.scrubVal(val, instance);
6862        }
6863
6864        ret.push(val);
6865    });
6866
6867    return (isNodeList) ? Y.all(ret) : ret;
6868};
6869
6870Y.NodeList = NodeList;
6871
6872Y.all = function(nodes) {
6873    return new NodeList(nodes);
6874};
6875
6876Y.Node.all = Y.all;
6877/**
6878 * @module node
6879 * @submodule node-core
6880 */
6881
6882var Y_NodeList = Y.NodeList,
6883    ArrayProto = Array.prototype,
6884    ArrayMethods = {
6885        /** Returns a new NodeList combining the given NodeList(s)
6886          * @for NodeList
6887          * @method concat
6888          * @param {NodeList | Array} valueN Arrays/NodeLists and/or values to
6889          * concatenate to the resulting NodeList
6890          * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
6891          */
6892        'concat': 1,
6893        /** Removes the last from the NodeList and returns it.
6894          * @for NodeList
6895          * @method pop
6896          * @return {Node | null} The last item in the NodeList, or null if the list is empty.
6897          */
6898        'pop': 0,
6899        /** Adds the given Node(s) to the end of the NodeList.
6900          * @for NodeList
6901          * @method push
6902          * @param {Node | HTMLElement} nodes One or more nodes to add to the end of the NodeList.
6903          */
6904        'push': 0,
6905        /** Removes the first item from the NodeList and returns it.
6906          * @for NodeList
6907          * @method shift
6908          * @return {Node | null} The first item in the NodeList, or null if the NodeList is empty.
6909          */
6910        'shift': 0,
6911        /** Returns a new NodeList comprising the Nodes in the given range.
6912          * @for NodeList
6913          * @method slice
6914          * @param {Number} begin Zero-based index at which to begin extraction.
6915          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.
6916          * @param {Number} end Zero-based index at which to end extraction. slice extracts up to but not including end.
6917          slice(1,4) extracts the second element through the fourth element (elements indexed 1, 2, and 3).
6918          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.
6919          If end is omitted, slice extracts to the end of the sequence.
6920          * @return {NodeList} A new NodeList comprised of this NodeList joined with the input.
6921          */
6922        'slice': 1,
6923        /** Changes the content of the NodeList, adding new elements while removing old elements.
6924          * @for NodeList
6925          * @method splice
6926          * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end.
6927          * @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.
6928          * {Node | HTMLElement| element1, ..., elementN
6929          The elements to add to the array. If you don't specify any elements, splice simply removes elements from the array.
6930          * @return {NodeList}
6930 The element(s) removed.
6931          */
6932        'splice': 1,
6933        /** Adds the given Node(s) to the beginning of the NodeList.
6934          * @for NodeList
6935          * @method unshift
6936          * @param {Node | HTMLElement} nodes One or more nodes to add to the NodeList.
6937          */
6938        'unshift': 0
6939    };
6940
6941
6942Y.Object.each(ArrayMethods, function(returnNodeList, name) {
6943    Y_NodeList.prototype[name] = function() {
6944        var args = [],
6945            i = 0,
6946            arg,
6947            ret;
6948
6949        while (typeof (arg = arguments[i++]) != 'undefined') { // use DOM nodes/nodeLists
6950            args.push(arg._node || arg._nodes || arg);
6951        }
6952
6953        ret = ArrayProto[name].apply(this._nodes, args);
6954
6955        if (returnNodeList) {
6956            ret = Y.all(ret);
6957        } else {
6958            ret = Y.Node.scrubVal(ret);
6959        }
6960
6961        return ret;
6962    };
6963});
6964/**
6965 * @module node
6966 * @submodule node-core
6967 */
6968
6969Y.Array.each([
6970    /**
6971     * Passes through to DOM method.
6972     * @for Node
6973     * @method removeChild
6974     * @param {HTMLElement | Node} node Node to be removed
6975     * @return {Node} The removed node
6976     */
6977    'removeChild',
6978
6979    /**
6980     * Passes through to DOM method.
6981     * @method hasChildNodes
6982     * @return {Boolean} Whether or not the node has any childNodes
6983     */
6984    'hasChildNodes',
6985
6986    /**
6987     * Passes through to DOM method.
6988     * @method cloneNode
6989     * @param {Boolean} deep Whether or not to perform a deep clone, which includes
6990     * subtree and attributes
6991     * @return {Node} The clone
6992     */
6993    'cloneNode',
6994
6995    /**
6996     * Passes through to DOM method.
6997     * @method hasAttribute
6998     * @param {String} attribute The attribute to test for
6999     * @return {Boolean} Whether or not the attribute is present
7000     */
7001    'hasAttribute',
7002
7003    /**
7004     * Passes through to DOM method.
7005     * @method scrollIntoView
7006     * @chainable
7007     */
7008    'scrollIntoView',
7009
7010    /**
7011     * Passes through to DOM method.
7012     * @method getElementsByTagName
7013     * @param {String} tagName The tagName to collect
7014     * @return {NodeList} A NodeList representing the HTMLCollection
7015     */
7016    'getElementsByTagName',
7017
7018    /**
7019     * Passes through to DOM method.
7020     * @method focus
7021     * @chainable
7022     */
7023    'focus',
7024
7025    /**
7026     * Passes through to DOM method.
7027     * @method blur
7028     * @chainable
7029     */
7030    'blur',
7031
7032    /**
7033     * Passes through to DOM method.
7034     * Only valid on FORM elements
7035     * @method submit
7036     * @chainable
7037     */
7038    'submit',
7039
7040    /**
7041     * Passes through to DOM method.
7042     * Only valid on FORM elements
7043     * @method reset
7044     * @chainable
7045     */
7046    'reset',
7047
7048    /**
7049     * Passes through to DOM method.
7050     * @method select
7051     * @chainable
7052     */
7053     'select',
7054
7055    /**
7056     * Passes through to DOM method.
7057     * Only valid on TABLE elements
7058     * @method createCaption
7059     * @chainable
7060     */
7061    'createCaption'
7062
7063], function(method) {
7064    Y.Node.prototype[method] = function(arg1, arg2, arg3) {
7065        var ret = this.invoke(method, arg1, arg2, arg3);
7066        return ret;
7067    };
7068});
7069
7070/**
7071 * Passes through to DOM method.
7072 * @method removeAttribute
7073 * @param {String} attribute The attribute to be removed
7074 * @chainable
7075 */
7076 // one-off implementation due to IE returning boolean, breaking chaining
7077Y.Node.prototype.removeAttribute = function(attr) {
7078    var node = this._node;
7079    if (node) {
7080        node.removeAttribute(attr, 0); // comma zero for IE < 8 to force case-insensitive
7081    }
7082
7083    return this;
7084};
7085
7086Y.Node.importMethod(Y.DOM, [
7087    /**
7088     * Determines whether the node is an ancestor of another HTML element in the DOM hierarchy.
7089     * @method contains
7090     * @param {Node | HTMLElement} needle The possible node or descendent
7091     * @return {Boolean} Whether or not this node is the needle its ancestor
7092     */
7093    'contains',
7094    /**
7095     * Allows setting attributes on DOM nodes, normalizing in some cases.
7096     * This passes through to the DOM node, allowing for custom attributes.
7097     * @method setAttribute
7098     * @for Node
7099     * @chainable
7100     * @param {string} name The attribute name
7101     * @param {string} value The value to set
7102     */
7103    'setAttribute',
7104    /**
7105     * Allows getting attributes on DOM nodes, normalizing in some cases.
7106     * This passes through to the DOM node, allowing for custom attributes.
7107     * @method getAttribute
7108     * @for Node
7109     * @param {string} name The attribute name
7110     * @return {string} The attribute value
7111     */
7112    'getAttribute',
7113
7114    /**
7115     * Wraps the given HTML around the node.
7116     * @method wrap
7117     * @param {String} html The markup to wrap around the node.
7118     * @chainable
7119     * @for Node
7120     */
7121    'wrap',
7122
7123    /**
7124     * Removes the node's parent node.
7125     * @method unwrap
7126     * @chainable
7127     */
7128    'unwrap',
7129
7130    /**
7131     * Applies a unique ID to the node if none exists
7132     * @method generateID
7133     * @return {String} The existing or generated ID
7134     */
7135    'generateID'
7136]);
7137
7138Y.NodeList.importMethod(Y.Node.prototype, [
7139/**
7140 * Allows getting attributes on DOM nodes, normalizing in some cases.
7141 * This passes through to the DOM node, allowing for custom attributes.
7142 * @method getAttribute
7143 * @see Node
7144 * @for NodeList
7145 * @param {string} name The attribute name
7146 * @return {string} The attribute value
7147 */
7148
7149    'getAttribute',
7150/**
7151 * Allows setting attributes on DOM nodes, normalizing in some cases.
7152 * This passes through to the DOM node, allowing for custom attributes.
7153 * @method setAttribute
7154 * @see Node
7155 * @for NodeList
7156 * @chainable
7157 * @param {string} name The attribute name
7158 * @param {string} value The value to set
7159 */
7160    'setAttribute',
7161
7162/**
7163 * Allows for removing attributes on DOM nodes.
7164 * This passes through to the DOM node, allowing for custom attributes.
7165 * @method removeAttribute
7166 * @see Node
7167 * @for NodeList
7168 * @param {string} name The attribute to remove
7169 */
7170    'removeAttribute',
7171/**
7172 * Removes the parent node from node in the list.
7173 * @method unwrap
7174 * @chainable
7175 */
7176    'unwrap',
7177/**
7178 * Wraps the given HTML around each node.
7179 * @method wrap
7180 * @param {String} html The markup to wrap around the node.
7181 * @chainable
7182 */
7183    'wrap',
7184
7185/**
7186 * Applies a unique ID to each node if none exists
7187 * @method generateID
7188 * @return {String} The existing or generated ID
7189 */
7190    'generateID'
7191]);
7192
7193
7194}, 'patched-v3.18.3', {"requires": ["dom-core", "selector"]});
7195
7196YUI.add('node-event-delegate', function (Y, NAME) {
7197
7198/**
7199 * Functionality to make the node a delegated event container
7200 * @module node
7201 * @submodule node-event-delegate
7202 */
7203
7204/**
7205 * <p>Sets up a delegation listener for an event occurring inside the Node.
7206 * The delegated event will be verified against a supplied selector or
7207 * filtering function to test if the event references at least one node that
7208 * should trigger the subscription callback.</p>
7209 *
7210 * <p>Selector string filters will trigger the callback if the event originated
7211 * from a node that matches it or is contained in a node that matches it.
7212 * Function filters are called for each Node up the parent axis to the
7213 * subscribing container node, and receive at each level the Node and the event
7214 * object.  The function should return true (or a truthy value) if that Node
7215 * should trigger the subscription callback.  Note, it is possible for filters
7216 * to match multiple Nodes for a single event.  In this case, the delegate
7217 * callback will be executed for each matching Node.</p>
7218 *
7219 * <p>For each matching Node, the callback will be executed with its 'this'
7220 * object set to the Node matched by the filter (unless a specific context was
7221 * provided during subscription), and the provided event's
7222 * <code>currentTarget</code> will also be set to the matching Node.  The
7223 * containing Node from which the subscription was originally made can be
7224 * referenced as <code>e.container</code>.
7225 *
7226 * @method delegate
7227 * @param type {String} the event type to delegate
7228 * @param fn {Function} the callback function to execute.  This function
7229 *              will be provided the event object for the delegated event.
7230 * @param spec {String|Function} a selector that must match the target of the
7231 *              event or a function to test target and its parents for a match
7232 * @param context {Object} optional argument that specifies what 'this' refers to.
7233 * @param args* {any} 0..n additional arguments to pass on to the callback function.
7234 *              These arguments will be added after the event object.
7235 * @return {EventHandle} the detach handle
7236 * @for Node
7237 */
7238Y.Node.prototype.delegate = function(type) {
7239
7240    var args = Y.Array(arguments, 0, true),
7241        index = (Y.Lang.isObject(type) && !Y.Lang.isArray(type)) ? 1 : 2;
7242
7243    args.splice(index, 0, this._node);
7244
7245    return Y.delegate.apply(Y, args);
7246};
7247
7248
7249}, 'patched-v3.18.3', {"requires": ["node-base", "event-delegate"]});
7250
7251YUI.add('node-event-simulate', function (Y, NAME) {
7252
7253/**
7254 * Adds functionality to simulate events.
7255 * @module node
7256 * @submodule node-event-simulate
7257 */
7258
7259/**
7260 * Simulates an event on the node.
7261 * @param {String} type The type of event (i.e., "click").
7262 * @param {Object} options (Optional) Extra options to copy onto the event object.
7263 * @for Node
7264 * @method simulate
7265 */
7266Y.Node.prototype.simulate = function (type, options) {
7267
7268    Y.Event.simulate(Y.Node.getDOMNode(this), type, options);
7269};
7270
7271/**
7272 * Simulates the higher user level gesture of the given name on this node.
7273 * This method generates a set of low level touch events(Apple specific gesture
7274 * events as well for the iOS platforms) asynchronously. Note that gesture
7275 * simulation is relying on `Y.Event.simulate()` method to generate
7276 * the touch events under the hood. The `Y.Event.simulate()` method
7277 * itself is a synchronous method.
7278 *
7279 * Supported gestures are `tap`, `doubletap`, `press`, `move`, `flick`, `pinch`
7280 * and `rotate`.
7281 *
7282 * The `pinch` gesture is used to simulate the pinching and spreading of two
7283 * fingers. During a pinch simulation, rotation is also possible. Essentially
7284 * `pinch` and `rotate` simulations share the same base implementation to allow
7285 * both pinching and rotation at the same time. The only difference is `pinch`
7286 * requires `start` and `end` option properties while `rotate` requires `rotation`
7287 * option property.
7288 *
7289 * The `pinch` and `rotate` gestures can be described as placing 2 fingers along a
7290 * circle. Pinching and spreading can be described by start and end circles while
7291 * rotation occurs on a single circle. If the radius of the start circle is greater
7292 * than the end circle, the gesture becomes a pinch, otherwise it is a spread spread.
7293 *
7294 * @example
7295 *
7296 *     var node = Y.one("#target");
7297 *
7298 *     // double tap example
7299 *     node.simulateGesture("doubletap", function() {
7300 *         // my callback function
7301 *     });
7302 *
7303 *     // flick example from the center of the node, move 50 pixels down for 50ms)
7304 *     node.simulateGesture("flick", {
7305 *         axis: y,
7306 *         distance: -100
7307 *         duration: 50
7308 *     }, function() {
7309 *         // my callback function
7310 *     });
7311 *
7312 *     // simulate rotating a node 75 degrees counter-clockwise
7313 *     node.simulateGesture("rotate", {
7314 *         rotation: -75
7315 *     });
7316 *
7317 *     // simulate a pinch and a rotation at the same time.
7318 *     // fingers start on a circle of radius 100 px, placed at top/bottom
7319 *     // fingers end on a circle of radius 50px, placed at right/left
7320 *     node.simulateGesture("pinch", {
7321 *         r1: 100,
7322 *         r2: 50,
7323 *         start: 0
7324 *         rotation: 90
7325 *     });
7326 *
7327 * @method simulateGesture
7328 * @param {String} name The name of the supported gesture to simulate. The
7329 *      supported gesture name is one of "tap", "doubletap", "press", "move",
7330 *      "flick", "pinch" and "rotate".
7331 * @param {Object} [options] Extra options used to define the gesture behavior:
7332 *
7333 *      Valid options properties for the `tap` gesture:
7334 *
7335 *      @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates
7336 *        where the tap should be simulated. Default is the center of the node
7337 *        element.
7338 *      @param {Number} [options.hold=10] (Optional) The hold time in milliseconds.
7339 *        This is the time between `touchstart` and `touchend` event generation.
7340 *      @param {Number} [options.times=1] (Optional) Indicates the number of taps.
7341 *      @param {Number} [options.delay=10] (Optional) The number of milliseconds
7342 *        before the next tap simulation happens. This is valid only when `times`
7343 *        is more than 1.
7344 *
7345 *      Valid options properties for the `doubletap` gesture:
7346 *
7347 *      @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates
7348 *        where the doubletap should be simulated. Default is the center of the
7349 *        node element.
7350 *
7351 *      Valid options properties for the `press` gesture:
7352 *
7353 *      @param {Array} [options.point] (Optional) Indicates the [x,y] coordinates
7354 *        where the press should be simulated. Default is the center of the node
7355 *        element.
7356 *      @param {Number} [options.hold=3000] (Optional) The hold time in milliseconds.
7357 *        This is the time between `touchstart` and `touchend` event generation.
7358 *        Default is 3000ms (3 seconds).
7359 *
7360 *      Valid options properties for the `move` gesture:
7361 *
7362 *      @param {Object} [options.path] (Optional) Indicates the path of the finger
7363 *        movement. It's an object with three optional properties: `point`,
7364 *        `xdist` and  `ydist`.
7365 *        @param {Array} [options.path.point] A starting point of the gesture.
7366 *          Default is the center of the node element.
7367 *        @param {Number} [options.path.xdist=200] A distance to move in pixels
7368 *          along the X axis. A negative distance value indicates moving left.
7369 *        @param {Number} [options.path.ydist=0] A distance to move in pixels
7370 *          along the Y axis. A negative distance value indicates moving up.
7371 *      @param {Number} [options.duration=1000] (Optional) The duration of the
7372 *        gesture in milliseconds.
7373 *
7374 *      Valid options properties for the `flick` gesture:
7375 *
7376 *      @param {Array} [options.point] (Optional) Indicates the [x, y] coordinates
7377 *        where the flick should be simulated. Default is the center of the
7378 *        node element.
7379 *      @param {String} [options.axis='x'] (Optional) Valid values are either
7380 *        "x" or "y". Indicates axis to move along. The flick can move to one of
7381 *        4 directions(left, right, up and down).
7382 *      @param {Number} [options.distance=200] (Optional) Distance to move in pixels
7383 *      @param {Number} [options.duration=1000] (Optional) The duration of the
7384 *        gesture in milliseconds. User given value could be automatically
7385 *        adjusted by the framework if it is below the minimum velocity to be
7386 *        a flick gesture.
7387 *
7388 *      Valid options properties for the `pinch` gesture:
7389 *
7390 *      @param {Array} [options.center] (Optional) The center of the circle where
7391 *        two fingers are placed. Default is the center of the node element.
7392 *      @param {Number} [options.r1] (Required) Pixel radius of the start circle
7393 *        where 2 fingers will be on when the gesture starts. The circles are
7394 *        centered at the center of the element.
7395 *      @param {Number} [options.r2] (Required) Pixel radius of the end circle
7396 *        when this gesture ends.
7397 *      @param {Number} [options.duration=1000] (Optional) The duration of the
7398 *        gesture in milliseconds.
7399 *      @param {Number} [options.start=0] (Optional) Starting degree of the first
7400 *        finger. The value is relative to the path of the north. Default is 0
7401 *        (i.e., 12:00 on a clock).
7402 *      @param {Number} [options.rotation=0] (Optional) Degrees to rotate from
7403 *        the starting degree. A negative value means rotation to the
7404 *        counter-clockwise direction.
7405 *
7406 *      Valid options properties for the `rotate` gesture:
7407 *
7408 *      @param {Array} [options.center] (Optional) The center of the circle where
7409 *        two fingers are placed. Default is the center of the node element.
7410 *      @param {Number} [options.r1] (Optional) Pixel radius of the start circle
7411 *        where 2 fingers will be on when the gesture starts. The circles are
7412 *        centered at the center of the element. Default is a fourth of the node
7413 *        element width or height, whichever is smaller.
7414 *      @param {Number} [options.r2] (Optional) Pixel radius of the end circle
7415 *        when this gesture ends. Default is a fourth of the node element width or
7416 *        height, whichever is smaller.
7417 *      @param {Number} [options.duration=1000] (Optional) The duration of the
7418 *        gesture in milliseconds.
7419 *      @param {Number} [options.start=0] (Optional) Starting degree of the first
7420 *        finger. The value is relative to the path of the north. Default is 0
7421 *        (i.e., 12:00 on a clock).
7422 *      @param {Number} [options.rotation] (Required) Degrees to rotate from
7423 *        the starting degree. A negative value means rotation to the
7424 *        counter-clockwise direction.
7425 *
7426 * @param {Function} [cb] The callback to execute when the asynchronouse gesture
7427 *      simulation is completed.
7428 *      @param {Error} cb.err An error object if the simulation is failed.
7429 * @for Node
7430 */
7431Y.Node.prototype.simulateGesture = function (name, options, cb) {
7432
7433    Y.Event.simulateGesture(this, name, options, cb);
7434};
7435
7436
7437}, 'patched-v3.18.3', {"requires": ["node-base", "event-simulate", "gesture-simulate"]});
7438
7439YUI.add('node-focusmanager', function (Y, NAME) {
7440
7441/**
7442* <p>The Focus Manager Node Plugin makes it easy to manage focus among
7443* a Node's descendants.  Primarily intended to help with widget development,
7444* the Focus Manager Node Plugin can be used to improve the keyboard
7445* accessibility of widgets.</p>
7446*
7447* <p>
7448* When designing widgets that manage a set of descendant controls (i.e. buttons
7449* in a toolbar, tabs in a tablist, menuitems in a menu, etc.) it is important to
7450* limit the number of descendants in the browser's default tab flow.  The fewer
7451* number of descendants in the default tab flow, the easier it is for keyboard
7452* users to navigate between widgets by pressing the tab key.  When a widget has
7453* focus it should provide a set of shortcut keys (typically the arrow keys)
7454* to move focus among its descendants.
7455* </p>
7456*
7457* <p>
7458* To this end, the Focus Manager Node Plugin makes it easy to define a Node's
7459* focusable descendants, define which descendant should be in the default tab
7460* flow, and define the keys that move focus among each descendant.
7461* Additionally, as the CSS
7462* <a href="http://www.w3.org/TR/CSS21/selector.html#x38"><code>:focus</code></a>
7463* pseudo class is not supported on all elements in all
7464* <a href="http://developer.yahoo.com/yui/articles/gbs/">A-Grade browsers</a>,
7465* the Focus Manager Node Plugin provides an easy, cross-browser means of
7466* styling focus.
7467* </p>
7468*
7469
7470DEPRECATED: The FocusManager Node Plugin has been deprecated as of YUI 3.9.0. This module will be removed from the library in a future version. If you require functionality similar to the one provided by this  module, consider taking a look at the various modules in the YUI Gallery <http://yuilibrary.com/gallery/>.
7471
7472* @module node-focusmanager
7473* @deprecated 3.9.0
7474*/
7475
7476	//	Frequently used strings
7477
7478var ACTIVE_DESCENDANT = "activeDescendant",
7479	ID = "id",
7480	DISABLED = "disabled",
7481	TAB_INDEX = "tabIndex",
7482	FOCUSED = "focused",
7483	FOCUS_CLASS = "focusClass",
7484	CIRCULAR = "circular",
7485	UI = "UI",
7486	KEY = "key",
7487	ACTIVE_DESCENDANT_CHANGE = ACTIVE_DESCENDANT + "Change",
7488	HOST = "host",
7489
7490	//	Collection of keys that, when pressed, cause the browser viewport
7491	//	to scroll.
7492	scrollKeys = {
7493		37: true,
7494		38: true,
7495		39: true,
7496		40: true
7497	},
7498
7499	clickableElements = {
7500		"a": true,
7501		"button": true,
7502		"input": true,
7503		"object": true
7504	},
7505
7506	//	Library shortcuts
7507
7508	Lang = Y.Lang,
7509 	UA = Y.UA,
7510
7511	/**
7512	* The NodeFocusManager class is a plugin for a Node instance.  The class is used
7513	* via the <a href="Node.html#method_plug"><code>plug</code></a> method of Node
7514	* and should not be instantiated directly.
7515	* @namespace plugin
7516	* @class NodeFocusManager
7517	*/
7518	NodeFocusManager = function () {
7519
7520		NodeFocusManager.superclass.constructor.apply(this, arguments);
7521
7522	};
7523
7524
7525NodeFocusManager.ATTRS = {
7526
7527	/**
7528	* Boolean indicating that one of the descendants is focused.
7529	*
7530	* @attribute focused
7531	* @readOnly
7532	* @default false
7533	* @type boolean
7534	*/
7535	focused: {
7536
7537		value: false,
7538		readOnly: true
7539
7540	},
7541
7542
7543	/**
7544	* String representing the CSS selector used to define the descendant Nodes
7545	* whose focus should be managed.
7546	*
7547	* @attribute descendants
7548	* @type Y.NodeList
7549	*/
7550	descendants: {
7551
7552		getter: function (value) {
7553
7554			return this.get(HOST).all(value);
7555
7556		}
7557
7558	},
7559
7560
7561	/**
7562	* <p>Node, or index of the Node, representing the descendant that is either
7563	* focused or is focusable (<code>tabIndex</code> attribute is set to 0).
7564	* The value cannot represent a disabled descendant Node.  Use a value of -1
7565	* to remove all descendant Nodes from the default tab flow.
7566	* If no value is specified, the active descendant will be inferred using
7567	* the following criteria:</p>
7568	* <ol>
7569	* <li>Examining the <code>tabIndex</code> attribute of each descendant and
7570	* using the first descendant whose <code>tabIndex</code> attribute is set
7571	* to 0</li>
7572	* <li>If no default can be inferred then the value is set to either 0 or
7573	* the index of the first enabled descendant.</li>
7574	* </ol>
7575	*
7576	* @attribute activeDescendant
7577	* @type Number
7578	*/
7579	activeDescendant: {
7580
7581		setter: function (value) {
7582
7583			var isNumber = Lang.isNumber,
7584				INVALID_VALUE = Y.Attribute.INVALID_VALUE,
7585				descendantsMap = this._descendantsMap,
7586				descendants = this._descendants,
7587				nodeIndex,
7588				returnValue,
7589				oNode;
7590
7591
7592			if (isNumber(value)) {
7593				nodeIndex = value;
7594				returnValue = nodeIndex;
7595			}
7596			else if ((value instanceof Y.Node) && descendantsMap) {
7597
7598				nodeIndex = descendantsMap[value.get(ID)];
7599
7600				if (isNumber(nodeIndex)) {
7601					returnValue = nodeIndex;
7602				}
7603				else {
7604
7605					//	The user passed a reference to a Node that wasn't one
7606					//	of the descendants.
7607					returnValue = INVALID_VALUE;
7608
7609				}
7610
7611			}
7612			else {
7613				returnValue = INVALID_VALUE;
7614			}
7615
7616
7617			if (descendants) {
7618
7619				oNode = descendants.item(nodeIndex);
7620
7621				if (oNode && oNode.get("disabled")) {
7622
7623					//	Setting the "activeDescendant" attribute to the index
7624					//	of a disabled descendant is invalid.
7625					returnValue = INVALID_VALUE;
7626
7627				}
7628
7629			}
7630
7631
7632			return returnValue;
7633
7634		}
7635
7636	},
7637
7638
7639	/**
7640	* Object literal representing the keys to be used to navigate between the
7641	* next/previous descendant.  The format for the attribute's value is
7642	* <code>{ next: "down:40", previous: "down:38" }</code>.  The value for the
7643	* "next" and "previous" properties are used to attach
7644	* <a href="event/#keylistener"><code>key</code></a> event listeners. See
7645	* the <a href="event/#keylistener">Using the key Event</a> section of
7646	* the Event documentation for more information on "key" event listeners.
7647	*
7648	* @attribute keys
7649	* @type Object
7650	*/
7651	keys: {
7652
7653		value: {
7654
7655			next: null,
7656			previous: null
7657
7658		}
7659
7660
7661	},
7662
7663
7664	/**
7665	* String representing the name of class applied to the focused active
7666	* descendant Node.  Can also be an object literal used to define both the
7667	* class name, and the Node to which the class should be applied.  If using
7668	* an object literal, the format is:
7669	* <code>{ className: "focus", fn: myFunction }</code>.  The function
7670	* referenced by the <code>fn</code> property in the object literal will be
7671	* passed a reference to the currently focused active descendant Node.
7672	*
7673	* @attribute focusClass
7674	* @type String|Object
7675	*/
7676	focusClass: { },
7677
7678
7679	/**
7680	* Boolean indicating if focus should be set to the first/last descendant
7681	* when the end or beginning of the descendants has been reached.
7682	*
7683	* @attribute circular
7684	* @type Boolean
7685	* @default true
7686	*/
7687	circular: {
7688		value: true
7689	}
7690
7691};
7692
7693Y.extend(NodeFocusManager, Y.Plugin.Base, {
7694
7695	//	Protected properties
7696
7697	//	Boolean indicating if the NodeFocusManager is active.
7698	_stopped: true,
7699
7700	//	NodeList representing the descendants selected via the
7701	//	"descendants" attribute.
7702	_descendants: null,
7703
7704	//	Object literal mapping the IDs of each descendant to its index in the
7705	//	"_descendants" NodeList.
7706	_descendantsMap: null,
7707
7708	//	Reference to the Node instance to which the focused class (defined
7709	//	by the "focusClass" attribute) is currently applied.
7710	_focusedNode: null,
7711
7712	//	Number representing the index of the last descendant Node.
7713	_lastNodeIndex: 0,
7714
7715	//	Array of handles for event handlers used for a NodeFocusManager instance.
7716	_eventHandlers: null,
7717
7718
7719
7720	//	Protected methods
7721
7722	/**
7723	* @method _initDescendants
7724	* @description Sets the <code>tabIndex</code> attribute of all of the
7725	* descendants to -1, except the active descendant, whose
7726	* <code>tabIndex</code> attribute is set to 0.
7727	* @protected
7728	*/
7729	_initDescendants: function () {
7730
7731		var descendants = this.get("descendants"),
7732			descendantsMap = {},
7733			nFirstEnabled = -1,
7734			nDescendants,
7735			nActiveDescendant = this.get(ACTIVE_DESCENDANT),
7736			oNode,
7737			sID,
7738			i = 0;
7739
7740
7741
7742		if (Lang.isUndefined(nActiveDescendant)) {
7743			nActiveDescendant = -1;
7744		}
7745
7746
7747		if (descendants) {
7748
7749			nDescendants = descendants.size();
7750
7751
7752            for (i = 0; i < nDescendants; i++) {
7753
7754                oNode = descendants.item(i);
7755
7756                if (nFirstEnabled === -1 && !oNode.get(DISABLED)) {
7757                    nFirstEnabled = i;
7758                }
7759
7760
7761                //	If the user didn't specify a value for the
7762                //	"activeDescendant" attribute try to infer it from
7763                //	the markup.
7764
7765                //	Need to pass "2" when using "getAttribute" for IE to get
7766                //	the attribute value as it is set in the markup.
7767                //	Need to use "parseInt" because IE always returns the
7768                //	value as a number, whereas all other browsers return
7769                //	the attribute as a string when accessed
7770                //	via "getAttribute".
7771
7772                if (nActiveDescendant < 0 &&
7773                        parseInt(oNode.getAttribute(TAB_INDEX, 2), 10) === 0) {
7774
7775                    nActiveDescendant = i;
7776
7777                }
7778
7779                if (oNode) {
7780                    oNode.set(TAB_INDEX, -1);
7781                }
7782
7783                sID = oNode.get(ID);
7784
7785                if (!sID) {
7786                    sID = Y.guid();
7787                    oNode.set(ID, sID);
7788                }
7789
7790                descendantsMap[sID] = i;
7791
7792            }
7793
7794
7795            //	If the user didn't specify a value for the
7796            //	"activeDescendant" attribute and no default value could be
7797            //	determined from the markup, then default to 0.
7798
7799            if (nActiveDescendant < 0) {
7800                nActiveDescendant = 0;
7801            }
7802
7803
7804            oNode = descendants.item(nActiveDescendant);
7805
7806            //	Check to make sure the active descendant isn't disabled,
7807            //	and fall back to the first enabled descendant if it is.
7808
7809            if (!oNode || oNode.get(DISABLED)) {
7810                oNode = descendants.item(nFirstEnabled);
7811                nActiveDescendant = nFirstEnabled;
7812            }
7813
7814            this._lastNodeIndex = nDescendants - 1;
7815            this._descendants = descendants;
7816            this._descendantsMap = descendantsMap;
7817
7818            this.set(ACTIVE_DESCENDANT, nActiveDescendant);
7819
7820            //	Need to set the "tabIndex" attribute here, since the
7821            //	"activeDescendantChange" event handler used to manage
7822            //	the setting of the "tabIndex" attribute isn't wired up yet.
7823
7824            if (oNode) {
7825                oNode.set(TAB_INDEX, 0);
7826            }
7827
7828		}
7829
7830	},
7831
7832
7833	/**
7834	* @method _isDescendant
7835	* @description Determines if the specified Node instance is a descendant
7836	* managed by the Focus Manager.
7837	* @param node {Node} Node instance to be checked.
7838	* @return {Boolean} Boolean indicating if the specified Node instance is a
7839	* descendant managed by the Focus Manager.
7840	* @protected
7841	*/
7842	_isDescendant: function (node) {
7843
7844		return (node.get(ID) in this._descendantsMap);
7845
7846	},
7847
7848
7849	/**
7850	* @method _removeFocusClass
7851	* @description Removes the class name representing focus (as specified by
7852	* the "focusClass" attribute) from the Node instance to which it is
7853	* currently applied.
7854	* @protected
7855	*/
7856	_removeFocusClass: function () {
7857
7858		var oFocusedNode = this._focusedNode,
7859			focusClass = this.get(FOCUS_CLASS),
7860			sClassName;
7861
7862		if (focusClass) {
7863			sClassName = Lang.isString(focusClass) ?
7864				focusClass : focusClass.className;
7865		}
7866
7867		if (oFocusedNode && sClassName) {
7868			oFocusedNode.removeClass(sClassName);
7869		}
7870
7871	},
7872
7873
7874	/**
7875	* @method _detachKeyHandler
7876	* @description Detaches the "key" event handlers used to support the "keys"
7877	* attribute.
7878	* @protected
7879	*/
7880	_detachKeyHandler: function () {
7881
7882		var prevKeyHandler = this._prevKeyHandler,
7883			nextKeyHandler = this._nextKeyHandler;
7884
7885		if (prevKeyHandler) {
7886			prevKeyHandler.detach();
7887		}
7888
7889		if (nextKeyHandler) {
7890			nextKeyHandler.detach();
7891		}
7892
7893	},
7894
7895
7896	/**
7897	* @method _preventScroll
7898	* @description Prevents the viewport from scolling when the user presses
7899	* the up, down, left, or right key.
7900	* @protected
7901	*/
7902	_preventScroll: function (event) {
7903
7904		if (scrollKeys[event.keyCode] && this._isDescendant(event.target)) {
7905			event.preventDefault();
7906		}
7907
7908	},
7909
7910
7911	/**
7912	* @method _fireClick
7913	* @description Fires the click event if the enter key is pressed while
7914	* focused on an HTML element that is not natively clickable.
7915	* @protected
7916	*/
7917	_fireClick: function (event) {
7918
7919		var oTarget = event.target,
7920			sNodeName = oTarget.get("nodeName").toLowerCase();
7921
7922		if (event.keyCode === 13 && (!clickableElements[sNodeName] ||
7923				(sNodeName === "a" && !oTarget.getAttribute("href")))) {
7924
7925
7926			oTarget.simulate("click");
7927
7928		}
7929
7930	},
7931
7932
7933	/**
7934	* @method _attachKeyHandler
7935	* @description Attaches the "key" event handlers used to support the "keys"
7936	* attribute.
7937	* @protected
7938	*/
7939	_attachKeyHandler: function () {
7940
7941		this._detachKeyHandler();
7942
7943		var sNextKey = this.get("keys.next"),
7944			sPrevKey = this.get("keys.previous"),
7945			oNode = this.get(HOST),
7946			aHandlers = this._eventHandlers;
7947
7948		if (sPrevKey) {
7949 			this._prevKeyHandler =
7950				Y.on(KEY, Y.bind(this._focusPrevious, this), oNode, sPrevKey);
7951		}
7952
7953		if (sNextKey) {
7954 			this._nextKeyHandler =
7955				Y.on(KEY, Y.bind(this._focusNext, this), oNode, sNextKey);
7956		}
7957
7958
7959		//	In Opera it is necessary to call the "preventDefault" method in
7960		//	response to the user pressing the arrow keys in order to prevent
7961		//	the viewport from scrolling when the user is moving focus among
7962		//	the focusable descendants.
7963
7964		if (UA.opera) {
7965			aHandlers.push(oNode.on("keypress", this._preventScroll, this));
7966		}
7967
7968
7969		//	For all browsers except Opera: HTML elements that are not natively
7970		//	focusable but made focusable via the tabIndex attribute don't
7971		//	fire a click event when the user presses the enter key.  It is
7972		//	possible to work around this problem by simplying dispatching a
7973		//	click event in response to the user pressing the enter key.
7974
7975		if (!UA.opera) {
7976			aHandlers.push(oNode.on("keypress", this._fireClick, this));
7977		}
7978
7979	},
7980
7981
7982	/**
7983	* @method _detachEventHandlers
7984	* @description Detaches all event handlers used by the Focus Manager.
7985	* @protected
7986	*/
7987	_detachEventHandlers: function () {
7988
7989		this._detachKeyHandler();
7990
7991		var aHandlers = this._eventHandlers;
7992
7993		if (aHandlers) {
7994
7995			Y.Array.each(aHandlers, function (handle) {
7996				handle.detach();
7997			});
7998
7999			this._eventHandlers = null;
8000
8001		}
8002
8003	},
8004
8005
8006	/**
8007	* @method _detachEventHandlers
8008	* @description Attaches all event handlers used by the Focus Manager.
8009	* @protected
8010	*/
8011	_attachEventHandlers: function () {
8012
8013		var descendants = this._descendants,
8014			aHandlers,
8015			oDocument,
8016			handle;
8017
8018		if (descendants && descendants.size()) {
8019
8020			aHandlers = this._eventHandlers || [];
8021			oDocument = this.get(HOST).get("ownerDocument");
8022
8023
8024			if (aHandlers.length === 0) {
8025
8026
8027				aHandlers.push(oDocument.on("focus", this._onDocFocus, this));
8028
8029				aHandlers.push(oDocument.on("mousedown",
8030					this._onDocMouseDown, this));
8031
8032				aHandlers.push(
8033						this.after("keysChange", this._attachKeyHandler));
8034
8035				aHandlers.push(
8036						this.after("descendantsChange", this._initDescendants));
8037
8038				aHandlers.push(
8039						this.after(ACTIVE_DESCENDANT_CHANGE,
8040								this._afterActiveDescendantChange));
8041
8042
8043				//	For performance: defer attaching all key-related event
8044				//	handlers until the first time one of the specified
8045				//	descendants receives focus.
8046
8047				handle = this.after("focusedChange", Y.bind(function (event) {
8048
8049					if (event.newVal) {
8050
8051
8052						this._attachKeyHandler();
8053
8054						//	Detach this "focusedChange" handler so that the
8055						//	key-related handlers only get attached once.
8056
8057						handle.detach();
8058
8059					}
8060
8061				}, this));
8062
8063				aHandlers.push(handle);
8064
8065			}
8066
8067
8068			this._eventHandlers = aHandlers;
8069
8070		}
8071
8072	},
8073
8074
8075	//	Protected event handlers
8076
8077	/**
8078	* @method _onDocMouseDown
8079	* @description "mousedown" event handler for the owner document of the
8080	* Focus Manager's Node.
8081	* @protected
8082	* @param event {Object} Object representing the DOM event.
8083	*/
8084	_onDocMouseDown: function (event) {
8085
8086		var oHost = this.get(HOST),
8087			oTarget = event.target,
8088			bChildNode = oHost.contains(oTarget),
8089			node,
8090
8091			getFocusable = function (node) {
8092
8093				var returnVal = false;
8094
8095				if (!node.compareTo(oHost)) {
8096
8097					returnVal = this._isDescendant(node) ? node :
8098									getFocusable.call(this, node.get("parentNode"));
8099
8100				}
8101
8102				return returnVal;
8103
8104			};
8105
8106
8107		if (bChildNode) {
8108
8109			//	Check to make sure that the target isn't a child node of one
8110			//	of the focusable descendants.
8111
8112			node = getFocusable.call(this, oTarget);
8113
8114			if (node) {
8115				oTarget = node;
8116			}
8117			else if (!node && this.get(FOCUSED)) {
8118
8119				//	The target was a non-focusable descendant of the root
8120				//	node, so the "focused" attribute should be set to false.
8121
8122	 			this._set(FOCUSED, false);
8123	 			this._onDocFocus(event);
8124
8125			}
8126
8127		}
8128
8129
8130		if (bChildNode && this._isDescendant(oTarget)) {
8131
8132			//	Fix general problem in Webkit: mousing down on a button or an
8133			//	anchor element doesn't focus it.
8134
8135			//	For all browsers: makes sure that the descendant that
8136			//	was the target of the mousedown event is now considered the
8137			//	active descendant.
8138
8139			this.focus(oTarget);
8140		}
8141		else if (UA.webkit && this.get(FOCUSED) &&
8142			(!bChildNode || (bChildNode && !this._isDescendant(oTarget)))) {
8143
8144			//	Fix for Webkit:
8145
8146			//	Document doesn't receive focus in Webkit when the user mouses
8147			//	down on it, so the "focused" attribute won't get set to the
8148			//	correct value.
8149
8150			//	The goal is to force a blur if the user moused down on
8151			//	either: 1) A descendant node, but not one that managed by
8152			//	the FocusManager, or 2) an element outside of the
8153			//	FocusManager
8154
8155 			this._set(FOCUSED, false);
8156 			this._onDocFocus(event);
8157
8158		}
8159
8160	},
8161
8162
8163	/**
8164	* @method _onDocFocus
8165	* @description "focus" event handler for the owner document of the
8166	* Focus Manager's Node.
8167	* @protected
8168	* @param event {Object} Object representing the DOM event.
8169	*/
8170	_onDocFocus: function (event) {
8171
8172		var oTarget = this._focusTarget || event.target,
8173			bFocused = this.get(FOCUSED),
8174			focusClass = this.get(FOCUS_CLASS),
8175			oFocusedNode = this._focusedNode,
8176			bInCollection;
8177
8178		if (this._focusTarget) {
8179			this._focusTarget = null;
8180		}
8181
8182
8183		if (this.get(HOST).contains(oTarget)) {
8184
8185			//	The target is a descendant of the root Node.
8186
8187			bInCollection = this._isDescendant(oTarget);
8188
8189			if (!bFocused && bInCollection) {
8190
8191				//	The user has focused a focusable descendant.
8192
8193				bFocused = true;
8194
8195			}
8196			else if (bFocused && !bInCollection) {
8197
8198				//	The user has focused a child of the root Node that is
8199				//	not one of the descendants managed by this Focus Manager
8200				//	so clear the currently focused descendant.
8201
8202				bFocused = false;
8203
8204			}
8205
8206		}
8207		else {
8208
8209			// The target is some other node in the document.
8210
8211			bFocused = false;
8212
8213		}
8214
8215
8216		if (focusClass) {
8217
8218			if (oFocusedNode && (!oFocusedNode.compareTo(oTarget) || !bFocused)) {
8219				this._removeFocusClass();
8220			}
8221
8222			if (bInCollection && bFocused) {
8223
8224				if (focusClass.fn) {
8225					oTarget = focusClass.fn(oTarget);
8226					oTarget.addClass(focusClass.className);
8227				}
8228				else {
8229					oTarget.addClass(focusClass);
8230				}
8231
8232				this._focusedNode = oTarget;
8233
8234			}
8235
8236		}
8237
8238
8239		this._set(FOCUSED, bFocused);
8240
8241	},
8242
8243
8244	/**
8245	* @method _focusNext
8246	* @description Keydown event handler that moves focus to the next
8247	* enabled descendant.
8248	* @protected
8249	* @param event {Object} Object representing the DOM event.
8250	* @param activeDescendant {Number} Number representing the index of the
8251	* next descendant to be focused
8252	*/
8253	_focusNext: function (event, activeDescendant) {
8254
8255		var nActiveDescendant = activeDescendant || this.get(ACTIVE_DESCENDANT),
8256			oNode;
8257
8258
8259		if (this._isDescendant(event.target) &&
8260			(nActiveDescendant <= this._lastNodeIndex)) {
8261
8262			nActiveDescendant = nActiveDescendant + 1;
8263
8264			if (nActiveDescendant === (this._lastNodeIndex + 1) &&
8265				this.get(CIRCULAR)) {
8266
8267				nActiveDescendant = 0;
8268
8269			}
8270
8271			oNode = this._descendants.item(nActiveDescendant);
8272
8273            if (oNode) {
8274
8275                if (oNode.get("disabled")) {
8276                    this._focusNext(event, nActiveDescendant);
8277                }
8278                else {
8279                    this.focus(nActiveDescendant);
8280                }
8281
8282            }
8283
8284		}
8285
8286		this._preventScroll(event);
8287
8288	},
8289
8290
8291	/**
8292	* @method _focusPrevious
8293	* @description Keydown event handler that moves focus to the previous
8294	* enabled descendant.
8295	* @protected
8296	* @param event {Object} Object representing the DOM event.
8297	* @param activeDescendant {Number} Number representing the index of the
8298	* next descendant to be focused.
8299	*/
8300	_focusPrevious: function (event, activeDescendant) {
8301
8302		var nActiveDescendant = activeDescendant || this.get(ACTIVE_DESCENDANT),
8303			oNode;
8304
8305		if (this._isDescendant(event.target) && nActiveDescendant >= 0) {
8306
8307			nActiveDescendant = nActiveDescendant - 1;
8308
8309			if (nActiveDescendant === -1 && this.get(CIRCULAR)) {
8310				nActiveDescendant = this._lastNodeIndex;
8311			}
8312
8313            oNode = this._descendants.item(nActiveDescendant);
8314
8315            if (oNode) {
8316
8317                if (oNode.get("disabled")) {
8318                    this._focusPrevious(event, nActiveDescendant);
8319                }
8320                else {
8321                    this.focus(nActiveDescendant);
8322                }
8323
8324            }
8325
8326		}
8327
8328		this._preventScroll(event);
8329
8330	},
8331
8332
8333	/**
8334	* @method _afterActiveDescendantChange
8335	* @description afterChange event handler for the
8336	* "activeDescendant" attribute.
8337	* @protected
8338	* @param event {Object} Object representing the change event.
8339	*/
8340	_afterActiveDescendantChange: function (event) {
8341
8342		var oNode = this._descendants.item(event.prevVal);
8343
8344		if (oNode) {
8345			oNode.set(TAB_INDEX, -1);
8346		}
8347
8348		oNode = this._descendants.item(event.newVal);
8349
8350		if (oNode) {
8351			oNode.set(TAB_INDEX, 0);
8352		}
8353
8354	},
8355
8356
8357
8358	//	Public methods
8359
8360    initializer: function (config) {
8361		this.start();
8362
8363    },
8364
8365	destructor: function () {
8366
8367		this.stop();
8368		this.get(HOST).focusManager = null;
8369
8370    },
8371
8372
8373	/**
8374	* @method focus
8375	* @description Focuses the active descendant and sets the
8376	* <code>focused</code> attribute to true.
8377	* @param index {Number|Node} Optional. Number representing the index of the
8378	* descendant to be set as the active descendant or Node instance
8379	* representing the descendant to be set as the active descendant.
8380	*/
8381	focus: function (index) {
8382
8383		if (Lang.isUndefined(index)) {
8384			index = this.get(ACTIVE_DESCENDANT);
8385		}
8386
8387		this.set(ACTIVE_DESCENDANT, index, { src: UI });
8388
8389		var oNode = this._descendants.item(this.get(ACTIVE_DESCENDANT));
8390
8391		if (oNode) {
8392
8393			oNode.focus();
8394
8395			//	In Opera focusing a <BUTTON> element programmatically
8396			//	will result in the document-level focus event handler
8397			//	"_onDocFocus" being called, resulting in the handler
8398			//	incorrectly setting the "focused" Attribute to false.  To fix
8399			//	this, set a flag ("_focusTarget") that the "_onDocFocus" method
8400			//	can look for to properly handle this edge case.
8401
8402			if (UA.opera && oNode.get("nodeName").toLowerCase() === "button") {
8403				this._focusTarget = oNode;
8404			}
8405
8406		}
8407
8408	},
8409
8410
8411	/**
8412	* @method blur
8413	* @description Blurs the current active descendant and sets the
8414	* <code>focused</code> attribute to false.
8415	*/
8416	blur: function () {
8417
8418		var oNode;
8419
8420		if (this.get(FOCUSED)) {
8421
8422			oNode = this._descendants.item(this.get(ACTIVE_DESCENDANT));
8423
8424			if (oNode) {
8425
8426				oNode.blur();
8427
8428				//	For Opera and Webkit:  Blurring an element in either browser
8429				//	doesn't result in another element (such as the document)
8430				//	being focused.  Therefore, the "_onDocFocus" method
8431				//	responsible for managing the application and removal of the
8432				//	focus indicator class name is never called.
8433
8434				this._removeFocusClass();
8435
8436			}
8437
8438			this._set(FOCUSED, false, { src: UI });
8439		}
8440
8441	},
8442
8443
8444	/**
8445	* @method start
8446	* @description Enables the Focus Manager.
8447	*/
8448	start: function () {
8449
8450		if (this._stopped) {
8451
8452			this._initDescendants();
8453			this._attachEventHandlers();
8454
8455			this._stopped = false;
8456
8457		}
8458
8459	},
8460
8461
8462	/**
8463	* @method stop
8464	* @description Disables the Focus Manager by detaching all event handlers.
8465	*/
8466	stop: function () {
8467
8468		if (!this._stopped) {
8469
8470			this._detachEventHandlers();
8471
8472			this._descendants = null;
8473			this._focusedNode = null;
8474			this._lastNodeIndex = 0;
8475			this._stopped = true;
8476
8477		}
8478
8479	},
8480
8481
8482	/**
8483	* @method refresh
8484	* @description Refreshes the Focus Manager's descendants by re-executing the
8485	* CSS selector query specified by the <code>descendants</code> attribute.
8486	*/
8487	refresh: function () {
8488
8489		this._initDescendants();
8490
8491		if (!this._eventHandlers) {
8492			this._attachEventHandlers();
8493		}
8494
8495	}
8496
8497});
8498
8499
8500NodeFocusManager.NAME = "nodeFocusManager";
8501NodeFocusManager.NS = "focusManager";
8502
8503Y.namespace("Plugin");
8504Y.Plugin.NodeFocusManager = NodeFocusManager;
8505
8506
8507}, 'patched-v3.18.3', {"requires": ["attribute", "node", "plugin", "node-event-simulate", "event-key", "event-focus"]});
8508
8509YUI.add('node-pluginhost', function (Y, NAME) {
8510
8511/**
8512 * @module node
8513 * @submodule node-pluginhost
8514 */
8515
8516/**
8517 * Registers plugins to be instantiated at the class level (plugins
8518 * which should be plugged into every instance of Node by default).
8519 *
8520 * @method plug
8521 * @static
8522 * @for Node
8523 * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
8524 * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
8525 */
8526Y.Node.plug = function() {
8527    var args = Y.Array(arguments);
8528    args.unshift(Y.Node);
8529    Y.Plugin.Host.plug.apply(Y.Base, args);
8530    return Y.Node;
8531};
8532
8533/**
8534 * Unregisters any class level plugins which have been registered by the Node
8535 *
8536 * @method unplug
8537 * @static
8538 *
8539 * @param {Function | Array} plugin The plugin class, or an array of plugin classes
8540 */
8541Y.Node.unplug = function() {
8542    var args = Y.Array(arguments);
8543    args.unshift(Y.Node);
8544    Y.Plugin.Host.unplug.apply(Y.Base, args);
8545    return Y.Node;
8546};
8547
8548Y.mix(Y.Node, Y.Plugin.Host, false, null, 1);
8549
8550// run PluginHost constructor on cached Node instances
8551Y.Object.each(Y.Node._instances, function (node) {
8552    Y.Plugin.Host.apply(node);
8553});
8554
8555// allow batching of plug/unplug via NodeList
8556// doesn't use NodeList.importMethod because we need real Nodes (not tmpNode)
8557/**
8558 * Adds a plugin to each node in the NodeList.
8559 * This will instantiate the plugin and attach it to the configured namespace on each node
8560 * @method plug
8561 * @for NodeList
8562 * @param P {Function | Object |Array} Accepts the plugin class, or an
8563 * object with a "fn" property specifying the plugin class and
8564 * a "cfg" property specifying the configuration for the Plugin.
8565 * <p>
8566 * Additionally an Array can also be passed in, with the above function or
8567 * object values, allowing the user to add multiple plugins in a single call.
8568 * </p>
8569 * @param config (Optional) If the first argument is the plugin class, the second argument
8570 * can be the configuration for the plugin.
8571 * @chainable
8572 */
8573Y.NodeList.prototype.plug = function() {
8574    var args = arguments;
8575    Y.NodeList.each(this, function(node) {
8576        Y.Node.prototype.plug.apply(Y.one(node), args);
8577    });
8578    return this;
8579};
8580
8581/**
8582 * Removes a plugin from all nodes in the NodeList. This will destroy the
8583 * plugin instance and delete the namespace each node.
8584 * @method unplug
8585 * @for NodeList
8586 * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
8587 * all registered plugins are unplugged.
8588 * @chainable
8589 */
8590Y.NodeList.prototype.unplug = function() {
8591    var args = arguments;
8592    Y.NodeList.each(this, function(node) {
8593        Y.Node.prototype.unplug.apply(Y.one(node), args);
8594    });
8595    return this;
8596};
8597
8598
8599}, 'patched-v3.18.3', {"requires": ["node-base", "pluginhost"]});
8600
8601YUI.add('node-screen', function (Y, NAME) {
8602
8603/**
8604 * Extended Node interface for managing regions and screen positioning.
8605 * Adds support for positioning elements and normalizes window size and scroll detection.
8606 * @module node
8607 * @submodule node-screen
8608 */
8609
8610// these are all "safe" returns, no wrapping required
8611Y.each([
8612    /**
8613     * Returns the inner width of the viewport (exludes scrollbar).
8614     * @config winWidth
8615     * @for Node
8616     * @type {Number}
8617     */
8618    'winWidth',
8619
8620    /**
8621     * Returns the inner height of the viewport (exludes scrollbar).
8622     * @config winHeight
8623     * @type {Number}
8624     */
8625    'winHeight',
8626
8627    /**
8628     * Document width
8629     * @config docWidth
8630     * @type {Number}
8631     */
8632    'docWidth',
8633
8634    /**
8635     * Document height
8636     * @config docHeight
8637     * @type {Number}
8638     */
8639    'docHeight',
8640
8641    /**
8642     * Pixel distance the page has been scrolled horizontally
8643     * @config docScrollX
8644     * @type {Number}
8645     */
8646    'docScrollX',
8647
8648    /**
8649     * Pixel distance the page has been scrolled vertically
8650     * @config docScrollY
8651     * @type {Number}
8652     */
8653    'docScrollY'
8654    ],
8655    function(name) {
8656        Y.Node.ATTRS[name] = {
8657            getter: function() {
8658                var args = Array.prototype.slice.call(arguments);
8659                args.unshift(Y.Node.getDOMNode(this));
8660
8661                return Y.DOM[name].apply(this, args);
8662            }
8663        };
8664    }
8665);
8666
8667Y.Node.ATTRS.scrollLeft = {
8668    getter: function() {
8669        var node = Y.Node.getDOMNode(this);
8670        return ('scrollLeft' in node) ? node.scrollLeft : Y.DOM.docScrollX(node);
8671    },
8672
8673    setter: function(val) {
8674        var node = Y.Node.getDOMNode(this);
8675        if (node) {
8676            if ('scrollLeft' in node) {
8677                node.scrollLeft = val;
8678            } else if (node.document || node.nodeType === 9) {
8679                Y.DOM._getWin(node).scrollTo(val, Y.DOM.docScrollY(node)); // scroll window if win or doc
8680            }
8681        } else {
8682        }
8683    }
8684};
8685
8686Y.Node.ATTRS.scrollTop = {
8687    getter: function() {
8688        var node = Y.Node.getDOMNode(this);
8689        return ('scrollTop' in node) ? node.scrollTop : Y.DOM.docScrollY(node);
8690    },
8691
8692    setter: function(val) {
8693        var node = Y.Node.getDOMNode(this);
8694        if (node) {
8695            if ('scrollTop' in node) {
8696                node.scrollTop = val;
8697            } else if (node.document || node.nodeType === 9) {
8698                Y.DOM._getWin(node).scrollTo(Y.DOM.docScrollX(node), val); // scroll window if win or doc
8699            }
8700        } else {
8701        }
8702    }
8703};
8704
8705Y.Node.importMethod(Y.DOM, [
8706/**
8707 * Gets the current position of the node in page coordinates.
8708 * @method getXY
8709 * @for Node
8710 * @return {Array} The XY position of the node
8711*/
8712    'getXY',
8713
8714/**
8715 * Set the position of the node in page coordinates, regardless of how the node is positioned.
8716 * @method setXY
8717 * @param {Array} xy Contains X & Y values for new position (coordinates are page-based)
8718 * @chainable
8719 */
8720    'setXY',
8721
8722/**
8723 * Gets the current position of the node in page coordinates.
8724 * @method getX
8725 * @return {Number} The X position of the node
8726*/
8727    'getX',
8728
8729/**
8730 * Set the position of the node in page coordinates, regardless of how the node is positioned.
8731 * @method setX
8732 * @param {Number} x X value for new position (coordinates are page-based)
8733 * @chainable
8734 */
8735    'setX',
8736
8737/**
8738 * Gets the current position of the node in page coordinates.
8739 * @method getY
8740 * @return {Number} The Y position of the node
8741*/
8742    'getY',
8743
8744/**
8745 * Set the position of the node in page coordinates, regardless of how the node is positioned.
8746 * @method setY
8747 * @param {Number} y Y value for new position (coordinates are page-based)
8748 * @chainable
8749 */
8750    'setY',
8751
8752/**
8753 * Swaps the XY position of this node with another node.
8754 * @method swapXY
8755 * @param {Node | HTMLElement} otherNode The node to swap with.
8756 * @chainable
8757 */
8758    'swapXY'
8759]);
8760
8761/**
8762 * @module node
8763 * @submodule node-screen
8764 */
8765
8766/**
8767 * Returns a region object for the node
8768 * @config region
8769 * @for Node
8770 * @type Node
8771 */
8772Y.Node.ATTRS.region = {
8773    getter: function() {
8774        var node = this.getDOMNode(),
8775            region;
8776
8777        if (node && !node.tagName) {
8778            if (node.nodeType === 9) { // document
8779                node = node.documentElement;
8780            }
8781        }
8782        if (Y.DOM.isWindow(node)) {
8783            region = Y.DOM.viewportRegion(node);
8784        } else {
8785            region = Y.DOM.region(node);
8786        }
8787        return region;
8788    }
8789};
8790
8791/**
8792 * Returns a region object for the node's viewport
8793 * @config viewportRegion
8794 * @type Node
8795 */
8796Y.Node.ATTRS.viewportRegion = {
8797    getter: function() {
8798        return Y.DOM.viewportRegion(Y.Node.getDOMNode(this));
8799    }
8800};
8801
8802Y.Node.importMethod(Y.DOM, 'inViewportRegion');
8803
8804// these need special treatment to extract 2nd node arg
8805/**
8806 * Compares the intersection of the node with another node or region
8807 * @method intersect
8808 * @for Node
8809 * @param {Node|Object} node2 The node or region to compare with.
8810 * @param {Object} altRegion An alternate region to use (rather than this node's).
8811 * @return {Object} An object representing the intersection of the regions.
8812 */
8813Y.Node.prototype.intersect = function(node2, altRegion) {
8814    var node1 = Y.Node.getDOMNode(this);
8815    if (Y.instanceOf(node2, Y.Node)) { // might be a region object
8816        node2 = Y.Node.getDOMNode(node2);
8817    }
8818    return Y.DOM.intersect(node1, node2, altRegion);
8819};
8820
8821/**
8822 * Determines whether or not the node is within the given region.
8823 * @method inRegion
8824 * @param {Node|Object} node2 The node or region to compare with.
8825 * @param {Boolean} all Whether or not all of the node must be in the region.
8826 * @param {Object} altRegion An alternate region to use (rather than this node's).
8827 * @return {Boolean}
8827 True if in region, false if not.
8828 */
8829Y.Node.prototype.inRegion = function(node2, all, altRegion) {
8830    var node1 = Y.Node.getDOMNode(this);
8831    if (Y.instanceOf(node2, Y.Node)) { // might be a region object
8832        node2 = Y.Node.getDOMNode(node2);
8833    }
8834    return Y.DOM.inRegion(node1, node2, all, altRegion);
8835};
8836
8837
8838}, 'patched-v3.18.3', {"requires": ["dom-screen", "node-base"]});
8839
8840YUI.add('node-style', function (Y, NAME) {
8841
8842(function(Y) {
8843/**
8844 * Extended Node interface for managing node styles.
8845 * @module node
8846 * @submodule node-style
8847 */
8848
8849Y.mix(Y.Node.prototype, {
8850    /**
8851     * Sets a style property of the node.
8852     * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8853     * @method setStyle
8854     * @param {String} attr The style attribute to set.
8855     * @param {String|Number} val The value.
8856     * @chainable
8857     */
8858    setStyle: function(attr, val) {
8859        Y.DOM.setStyle(this._node, attr, val);
8860        return this;
8861    },
8862
8863    /**
8864     * Sets multiple style properties on the node.
8865     * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8866     * @method setStyles
8867     * @param {Object} hash An object literal of property:value pairs.
8868     * @chainable
8869     */
8870    setStyles: function(hash) {
8871        Y.DOM.setStyles(this._node, hash);
8872        return this;
8873    },
8874
8875    /**
8876     * Returns the style's current value.
8877     * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8878     * @method getStyle
8879     * @for Node
8880     * @param {String} attr The style attribute to retrieve.
8881     * @return {String} The current value of the style property for the element.
8882     */
8883
8884     getStyle: function(attr) {
8885        return Y.DOM.getStyle(this._node, attr);
8886     },
8887
8888    /**
8889     * Returns the computed value for the given style property.
8890     * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8891     * @method getComputedStyle
8892     * @param {String} attr The style attribute to retrieve.
8893     * @return {String} The computed value of the style property for the element.
8894     */
8895     getComputedStyle: function(attr) {
8896        return Y.DOM.getComputedStyle(this._node, attr);
8897     }
8898});
8899
8900/**
8901 * Returns an array of values for each node.
8902 * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8903 * @method getStyle
8904 * @for NodeList
8905 * @see Node.getStyle
8906 * @param {String} attr The style attribute to retrieve.
8907 * @return {Array} The current values of the style property for the element.
8908 */
8909
8910/**
8911 * Returns an array of the computed value for each node.
8912 * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8913 * @method getComputedStyle
8914 * @see Node.getComputedStyle
8915 * @param {String} attr The style attribute to retrieve.
8916 * @return {Array} The computed values for each node.
8917 */
8918
8919/**
8920 * Sets a style property on each node.
8921 * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8922 * @method setStyle
8923 * @see Node.setStyle
8924 * @param {String} attr The style attribute to set.
8925 * @param {String|Number} val The value.
8926 * @chainable
8927 */
8928
8929/**
8930 * Sets multiple style properties on each node.
8931 * Use camelCase (e.g. 'backgroundColor') for multi-word properties.
8932 * @method setStyles
8933 * @see Node.setStyles
8934 * @param {Object} hash An object literal of property:value pairs.
8935 * @chainable
8936 */
8937
8938// These are broken out to handle undefined return (avoid false positive for
8939// chainable)
8940
8941Y.NodeList.importMethod(Y.Node.prototype, ['getStyle', 'getComputedStyle', 'setStyle', 'setStyles']);
8942})(Y);
8943/**
8944 * @module node
8945 * @submodule node-base
8946 */
8947
8948var Y_Node = Y.Node;
8949
8950Y.mix(Y_Node.prototype, {
8951    /**
8952     * Makes the node visible.
8953     * If the "transition" module is loaded, show optionally
8954     * animates the showing of the node using either the default
8955     * transition effect ('fadeIn'), or the given named effect.
8956     * @method show
8957     * @for Node
8958     * @param {String} name A named Transition effect to use as the show effect.
8959     * @param {Object} config Options to use with the transition.
8960     * @param {Function} callback An optional function to run after the transition completes.
8961     * @chainable
8962     */
8963    show: function(callback) {
8964        callback = arguments[arguments.length - 1];
8965        this.toggleView(true, callback);
8966        return this;
8967    },
8968
8969    /**
8970     * The implementation for showing nodes.
8971     * Default is to remove the hidden attribute and reset the CSS style.display property.
8972     * @method _show
8973     * @protected
8974     * @chainable
8975     */
8976    _show: function() {
8977        this.removeAttribute('hidden');
8978
8979        // For back-compat we need to leave this in for browsers that
8980        // do not visually hide a node via the hidden attribute
8981        // and for users that check visibility based on style display.
8982        this.setStyle('display', '');
8983
8984    },
8985
8986    /**
8987    Returns whether the node is hidden by YUI or not. The hidden status is
8988    determined by the 'hidden' attribute and the value of the 'display' CSS
8989    property.
8990
8991    @method _isHidden
8992    @return {Boolean} `true` if the node is hidden.
8993    @private
8994    **/
8995    _isHidden: function() {
8996        return  this.hasAttribute('hidden') || Y.DOM.getComputedStyle(this._node, 'display') === 'none';
8997    },
8998
8999    /**
9000     * Displays or hides the node.
9001     * If the "transition" module is loaded, toggleView optionally
9002     * animates the toggling of the node using given named effect.
9003     * @method toggleView
9004     * @for Node
9005     * @param {Boolean} [on] An optional boolean value to force the node to be shown or hidden
9006     * @param {Function} [callback] An optional function to run after the transition completes.
9007     * @chainable
9008     */
9009    toggleView: function(on, callback) {
9010        this._toggleView.apply(this, arguments);
9011        return this;
9012    },
9013
9014    _toggleView: function(on, callback) {
9015        callback = arguments[arguments.length - 1];
9016
9017        // base on current state if not forcing
9018        if (typeof on != 'boolean') {
9019            on = (this._isHidden()) ? 1 : 0;
9020        }
9021
9022        if (on) {
9023            this._show();
9024        }  else {
9025            this._hide();
9026        }
9027
9028        if (typeof callback == 'function') {
9029            callback.call(this);
9030        }
9031
9032        return this;
9033    },
9034
9035    /**
9036     * Hides the node.
9037     * If the "transition" module is loaded, hide optionally
9038     * animates the hiding of the node using either the default
9039     * transition effect ('fadeOut'), or the given named effect.
9040     * @method hide
9041     * @param {String} name A named Transition effect to use as the show effect.
9042     * @param {Object} config Options to use with the transition.
9043     * @param {Function} callback An optional function to run after the transition completes.
9044     * @chainable
9045     */
9046    hide: function(callback) {
9047        callback = arguments[arguments.length - 1];
9048        this.toggleView(false, callback);
9049        return this;
9050    },
9051
9052    /**
9053     * The implementation for hiding nodes.
9054     * Default is to set the hidden attribute to true and set the CSS style.display to 'none'.
9055     * @method _hide
9056     * @protected
9057     * @chainable
9058     */
9059    _hide: function() {
9060        this.setAttribute('hidden', 'hidden');
9061
9062        // For back-compat we need to leave this in for browsers that
9063        // do not visually hide a node via the hidden attribute
9064        // and for users that check visibility based on style display.
9065        this.setStyle('display', 'none');
9066    }
9067});
9068
9069Y.NodeList.importMethod(Y.Node.prototype, [
9070    /**
9071     * Makes each node visible.
9072     * If the "transition" module is loaded, show optionally
9073     * animates the showing of the node using either the default
9074     * transition effect ('fadeIn'), or the given named effect.
9075     * @method show
9076     * @param {String} name A named Transition effect to use as the show effect.
9077     * @param {Object} config Options to use with the transition.
9078     * @param {Function} callback An optional function to run after the transition completes.
9079     * @for NodeList
9080     * @chainable
9081     */
9082    'show',
9083
9084    /**
9085     * Hides each node.
9086     * If the "transition" module is loaded, hide optionally
9087     * animates the hiding of the node using either the default
9088     * transition effect ('fadeOut'), or the given named effect.
9089     * @method hide
9090     * @param {String} name A named Transition effect to use as the show effect.
9091     * @param {Object} config Options to use with the transition.
9092     * @param {Function} callback An optional function to run after the transition completes.
9093     * @chainable
9094     */
9095    'hide',
9096
9097    /**
9098     * Displays or hides each node.
9099     * If the "transition" module is loaded, toggleView optionally
9100     * animates the toggling of the nodes using given named effect.
9101     * @method toggleView
9102     * @param {Boolean} [on] An optional boolean value to force the nodes to be shown or hidden
9103     * @param {Function} [callback] An optional function to run after the transition completes.
9104     * @chainable
9105     */
9106    'toggleView'
9107]);
9108
9109
9110}, 'patched-v3.18.3', {"requires": ["dom-style", "node-base"]});
9111
9112YUI.add('oop', function (Y, NAME) {
9113
9114/**
9115Adds object inheritance and manipulation utilities to the YUI instance. This
9116module is required by most YUI components.
9117
9118@module oop
9119**/
9120
9121var L            = Y.Lang,
9122    A            = Y.Array,
9123    OP           = Object.prototype,
9124    CLONE_MARKER = '_~yuim~_',
9125
9126    hasOwn   = OP.hasOwnProperty,
9127    toString = OP.toString;
9128
9129/**
9130Calls the specified _action_ method on _o_ if it exists. Otherwise, if _o_ is an
9131array, calls the _action_ method on `Y.Array`, or if _o_ is an object, calls the
9132_action_ method on `Y.Object`.
9133
9134If _o_ is an array-like object, it will be coerced to an array.
9135
9136This is intended to be used with array/object iteration methods that share
9137signatures, such as `each()`, `some()`, etc.
9138
9139@method dispatch
9140@param {Object} o Array or object to dispatch to.
9141@param {Function} f Iteration callback.
9142    @param {Mixed} f.value Value being iterated.
9143    @param {Mixed} f.key Current object key or array index.
9144    @param {Mixed} f.object Object or array being iterated.
9145@param {Object} c `this` object to bind the iteration callback to.
9146@param {Boolean} proto If `true`, prototype properties of objects will be
9147    iterated.
9148@param {String} action Function name to be dispatched on _o_. For example:
9149    'some', 'each', etc.
9150@private
9151@return {Mixed} Returns the value returned by the chosen iteration action, which
9152    varies.
9153**/
9154function dispatch(o, f, c, proto, action) {
9155    if (o && o[action] && o !== Y) {
9156        return o[action].call(o, f, c);
9157    } else {
9158        switch (A.test(o)) {
9159            case 1:
9160                return A[action](o, f, c);
9161            case 2:
9162                return A[action](Y.Array(o, 0, true), f, c);
9163            default:
9164                return Y.Object[action](o, f, c, proto);
9165        }
9166    }
9167}
9168
9169/**
9170Augments the _receiver_ with prototype properties from the _supplier_. The
9171receiver may be a constructor function or an object. The supplier must be a
9172constructor function.
9173
9174If the _receiver_ is an object, then the _supplier_ constructor will be called
9175immediately after _receiver_ is augmented, with _receiver_ as the `this` object.
9176
9177If the _receiver_ is a constructor function, then all prototype methods of
9178_supplier_ that are copied to _receiver_ will be sequestered, and the
9179_supplier_ constructor will not be called immediately. The first time any
9180sequestered method is called on the _receiver_'s prototype, all sequestered
9181methods will be immediately copied to the _receiver_'s prototype, the
9182_supplier_'s constructor will be executed, and finally the newly unsequestered
9183method that was called will be executed.
9184
9185This sequestering logic sounds like a bunch of complicated voodoo, but it makes
9186it cheap to perform frequent augmentation by ensuring that suppliers'
9187constructors are only called if a supplied method is actually used. If none of
9188the supplied methods is ever used, then there's no need to take the performance
9189hit of calling the _supplier_'s constructor.
9190
9191@method augment
9192@param {Function|Object} receiver Object or function to be augmented.
9193@param {Function} supplier Function that supplies the prototype properties with
9194  which to augment the _receiver_.
9195@param {Boolean} [overwrite=false] If `true`, properties already on the receiver
9196  will be overwritten if found on the supplier's prototype.
9197@param {String[]} [whitelist] An array of property names. If specified,
9198  only the whitelisted prototype properties will be applied to the receiver, and
9199  all others will be ignored.
9200@param {Array|any} [args] Argument or array of arguments to pass to the
9201  supplier's constructor when initializing.
9202@return {Function} Augmented object.
9203@for YUI
9204**/
9205Y.augment = function (receiver, supplier, overwrite, whitelist, args) {
9206    var rProto    = receiver.prototype,
9207        sequester = rProto && supplier,
9208        sProto    = supplier.prototype,
9209        to        = rProto || receiver,
9210
9211        copy,
9212        newPrototype,
9213        replacements,
9214        sequestered,
9215        unsequester;
9216
9217    args = args ? Y.Array(args) : [];
9218
9219    if (sequester) {
9220        newPrototype = {};
9221        replacements = {};
9222        sequestered  = {};
9223
9224        copy = function (value, key) {
9225            if (overwrite || !(key in rProto)) {
9226                if (toString.call(value) === '[object Function]') {
9227                    sequestered[key] = value;
9228
9229                    newPrototype[key] = replacements[key] = function () {
9230                        return unsequester(this, value, arguments);
9231                    };
9232                } else {
9233                    newPrototype[key] = value;
9234                }
9235            }
9236        };
9237
9238        unsequester = function (instance, fn, fnArgs) {
9239            // Unsequester all sequestered functions.
9240            for (var key in sequestered) {
9241                if (hasOwn.call(sequestered, key)
9242                        && instance[key] === replacements[key]) {
9243
9244                    instance[key] = sequestered[key];
9245                }
9246            }
9247
9248            // Execute the supplier constructor.
9249            supplier.apply(instance, args);
9250
9251            // Finally, execute the original sequestered function.
9252            return fn.apply(instance, fnArgs);
9253        };
9254
9255        if (whitelist) {
9256            Y.Array.each(whitelist, function (name) {
9257                if (name in sProto) {
9258                    copy(sProto[name], name);
9259                }
9260            });
9261        } else {
9262            Y.Object.each(sProto, copy, null, true);
9263        }
9264    }
9265
9266    Y.mix(to, newPrototype || sProto, overwrite, whitelist);
9267
9268    if (!sequester) {
9269        supplier.apply(to, args);
9270    }
9271
9272    return receiver;
9273};
9274
9275/**
9276 * Copies object properties from the supplier to the receiver. If the target has
9277 * the property, and the property is an object, the target object will be
9278 * augmented with the supplier's value.
9279 *
9280 * @method aggregate
9281 * @param {Object} receiver Object to receive the augmentation.
9282 * @param {Object} supplier Object that supplies the properties with which to
9283 *     augment the receiver.
9284 * @param {Boolean} [overwrite=false] If `true`, properties already on the receiver
9285 *     will be overwritten if found on the supplier.
9286 * @param {String[]} [whitelist] Whitelist. If supplied, only properties in this
9287 *     list will be applied to the receiver.
9288 * @return {Object} Augmented object.
9289 */
9290Y.aggregate = function(r, s, ov, wl) {
9291    return Y.mix(r, s, ov, wl, 0, true);
9292};
9293
9294/**
9295 * Utility to set up the prototype, constructor and superclass properties to
9296 * support an inheritance strategy that can chain constructors and methods.
9297 * Static members will not be inherited.
9298 *
9299 * @method extend
9300 * @param {function} r   the object to modify.
9301 * @param {function} s the object to inherit.
9302 * @param {object} px prototype properties to add/override.
9303 * @param {object} sx static properties to add/override.
9304 * @return {object} the extended object.
9305 */
9306Y.extend = function(r, s, px, sx) {
9307    if (!s || !r) {
9308        Y.error('extend failed, verify dependencies');
9309    }
9310
9311    var sp = s.prototype, rp = Y.Object(sp);
9312    r.prototype = rp;
9313
9314    rp.constructor = r;
9315    r.superclass = sp;
9316
9317    // assign constructor property
9318    if (s != Object && sp.constructor == OP.constructor) {
9319        sp.constructor = s;
9320    }
9321
9322    // add prototype overrides
9323    if (px) {
9324        Y.mix(rp, px, true);
9325    }
9326
9327    // add object overrides
9328    if (sx) {
9329        Y.mix(r, sx, true);
9330    }
9331
9332    return r;
9333};
9334
9335/**
9336 * Executes the supplied function for each item in
9337 * a collection.  Supports arrays, objects, and
9338 * NodeLists
9339 * @method each
9340 * @param {object} o the object to iterate.
9341 * @param {function} f the function to execute.  This function
9342 * receives the value, key, and object as parameters.
9343 * @param {object} c the execution context for the function.
9344 * @param {boolean} proto if true, prototype properties are
9345 * iterated on objects.
9346 * @return {YUI} the YUI instance.
9347 */
9348Y.each = function(o, f, c, proto) {
9349    return dispatch(o, f, c, proto, 'each');
9350};
9351
9352/**
9353 * Executes the supplied function for each item in
9354 * a collection.  The operation stops if the function
9355 * returns true. Supports arrays, objects, and
9356 * NodeLists.
9357 * @method some
9358 * @param {object} o the object to iterate.
9359 * @param {function} f the function to execute.  This function
9360 * receives the value, key, and object as parameters.
9361 * @param {object} c the execution context for the function.
9362 * @param {boolean} proto if true, prototype properties are
9363 * iterated on objects.
9364 * @return {boolean} true if the function ever returns true,
9365 * false otherwise.
9366 */
9367Y.some = function(o, f, c, proto) {
9368    return dispatch(o, f, c, proto, 'some');
9369};
9370
9371/**
9372Deep object/array copy. Function clones are actually wrappers around the
9373original function. Array-like objects are treated as arrays. Primitives are
9374returned untouched. Optionally, a function can be provided to handle other data
9375types, filter keys, validate values, etc.
9376
9377**Note:** Cloning a non-trivial object is a reasonably heavy operation, due to
9378the need to recursively iterate down non-primitive properties. Clone should be
9379used only when a deep clone down to leaf level properties is explicitly
9380required. This method will also
9381
9382In many cases (for example, when trying to isolate objects used as hashes for
9383configuration properties), a shallow copy, using `Y.merge()` is normally
9384sufficient. If more than one level of isolation is required, `Y.merge()` can be
9385used selectively at each level which needs to be isolated from the original
9386without going all the way to leaf properties.
9387
9388@method clone
9389@param {object} o what to clone.
9390@param {boolean} safe if true, objects will not have prototype items from the
9391    source. If false, they will. In this case, the original is initially
9392    protected, but the clone is not completely immune from changes to the source
9393    object prototype. Also, cloned prototype items that are deleted from the
9394    clone will result in the value of the source prototype being exposed. If
9395    operating on a non-safe clone, items should be nulled out rather than
9396    deleted.
9397@param {function} f optional function to apply to each item in a collection; it
9398    will be executed prior to applying the value to the new object.
9399    Return false to prevent the copy.
9400@param {object} c optional execution context for f.
9401@param {object} owner Owner object passed when clone is iterating an object.
9402    Used to set up context for cloned functions.
9403@param {object} cloned hash of previously cloned objects to avoid multiple
9404    clones.
9405@return {Array|Object} the cloned object.
9406**/
9407Y.clone = function(o, safe, f, c, owner, cloned) {
9408    var o2, marked, stamp;
9409
9410    // Does not attempt to clone:
9411    //
9412    // * Non-typeof-object values, "primitive" values don't need cloning.
9413    //
9414    // * YUI instances, cloning complex object like YUI instances is not
9415    //   advised, this is like cloning the world.
9416    //
9417    // * DOM nodes (#2528250), common host objects like DOM nodes cannot be
9418    //   "subclassed" in Firefox and old versions of IE. Trying to use
9419    //   `Object.create()` or `Y.extend()` on a DOM node will throw an error in
9420    //   these browsers.
9421    //
9422    // Instad, the passed-in `o` will be return as-is when it matches one of the
9423    // above criteria.
9424    if (!L.isObject(o) ||
9425            Y.instanceOf(o, YUI) ||
9426            (o.addEventListener || o.attachEvent)) {
9427
9428        return o;
9429    }
9430
9431    marked = cloned || {};
9432
9433    switch (L.type(o)) {
9434        case 'date':
9435            return new Date(o);
9436        case 'regexp':
9437            // if we do this we need to set the flags too
9438            // return new RegExp(o.source);
9439            return o;
9440        case 'function':
9441            // o2 = Y.bind(o, owner);
9442            // break;
9443            return o;
9444        case 'array':
9445            o2 = [];
9446            break;
9447        default:
9448
9449            // #2528250 only one clone of a given object should be created.
9450            if (o[CLONE_MARKER]) {
9451                return marked[o[CLONE_MARKER]];
9452            }
9453
9454            stamp = Y.guid();
9455
9456            o2 = (safe) ? {} : Y.Object(o);
9457
9458            o[CLONE_MARKER] = stamp;
9459            marked[stamp] = o;
9460    }
9461
9462    Y.each(o, function(v, k) {
9463        if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
9464            if (k !== CLONE_MARKER) {
9465                if (k == 'prototype') {
9466                    // skip the prototype
9467                // } else if (o[k] === o) {
9468                //     this[k] = this;
9469                } else {
9470                    this[k] =
9471                        Y.clone(v, safe, f, c, owner || o, marked);
9472                }
9473            }
9474        }
9475    }, o2);
9476
9477    if (!cloned) {
9478        Y.Object.each(marked, function(v, k) {
9479            if (v[CLONE_MARKER]) {
9480                try {
9481                    delete v[CLONE_MARKER];
9482                } catch (e) {
9483                    v[CLONE_MARKER] = null;
9484                }
9485            }
9486        }, this);
9487        marked = null;
9488    }
9489
9490    return o2;
9491};
9492
9493/**
9494 * Returns a function that will execute the supplied function in the
9495 * supplied object's context, optionally adding any additional
9496 * supplied parameters to the beginning of the arguments collection the
9497 * supplied to the function.
9498 *
9499 * @method bind
9500 * @param {Function|String} f the function to bind, or a function name
9501 * to execute on the context object.
9502 * @param {object} c the execution context.
9503 * @param {any} args* 0..n arguments to include before the arguments the
9504 * function is executed with.
9505 * @return {function} the wrapped function.
9506 */
9507Y.bind = function(f, c) {
9508    var xargs = arguments.length > 2 ?
9509            Y.Array(arguments, 2, true) : null;
9510    return function() {
9511        var fn = L.isString(f) ? c[f] : f,
9512            args = (xargs) ?
9513                xargs.concat(Y.Array(arguments, 0, true)) : arguments;
9514        return fn.apply(c || fn, args);
9515    };
9516};
9517
9518/**
9519 * Returns a function that will execute the supplied function in the
9520 * supplied object's context, optionally adding any additional
9521 * supplied parameters to the end of the arguments the function
9522 * is executed with.
9523 *
9524 * @method rbind
9525 * @param {Function|String} f the function to bind, or a function name
9526 * to execute on the context object.
9527 * @param {object} c the execution context.
9528 * @param {any} args* 0..n arguments to append to the end of
9529 * arguments collection supplied to the function.
9530 * @return {function} the wrapped function.
9531 */
9532Y.rbind = function(f, c) {
9533    var xargs = arguments.length > 2 ? Y.Array(arguments, 2, true) : null;
9534    return function() {
9535        var fn = L.isString(f) ? c[f] : f,
9536            args = (xargs) ?
9537                Y.Array(arguments, 0, true).concat(xargs) : arguments;
9538        return fn.apply(c || fn, args);
9539    };
9540};
9541
9542
9543}, 'patched-v3.18.3', {"requires": ["yui-base"]});
9544
9545YUI.add('plugin', function (Y, NAME) {
9546
9547    /**
9548     * Provides the base Plugin class, which plugin developers should extend, when creating custom plugins
9549     *
9550     * @module plugin
9551     */
9552
9553    /**
9554     * The base class for all Plugin instances.
9555     *
9556     * @class Plugin.Base
9557     * @extends Base
9558     * @param {Object} config Configuration object with property name/value pairs.
9559     */
9560    function Plugin(config) {
9561        if (! (this.hasImpl && this.hasImpl(Y.Plugin.Base)) ) {
9562            Plugin.superclass.constructor.apply(this, arguments);
9563        } else {
9564            Plugin.prototype.initializer.apply(this, arguments);
9565        }
9566    }
9567
9568    /**
9569     * Object defining the set of attributes supported by the Plugin.Base class
9570     *
9571     * @property ATTRS
9572     * @type Object
9573     * @static
9574     */
9575    Plugin.ATTRS = {
9576
9577        /**
9578         * The plugin's host object.
9579         *
9580         * @attribute host
9581         * @writeonce
9582         * @type Plugin.Host
9583         */
9584        host : {
9585            writeOnce: true
9586        }
9587    };
9588
9589    /**
9590     * The string identifying the Plugin.Base class. Plugins extending
9591     * Plugin.Base should set their own NAME value.
9592     *
9593     * @property NAME
9594     * @type String
9595     * @static
9596     */
9597    Plugin.NAME = 'plugin';
9598
9599    /**
9600     * The name of the property the the plugin will be attached to
9601     * when plugged into a Plugin Host. Plugins extending Plugin.Base,
9602     * should set their own NS value.
9603     *
9604     * @property NS
9605     * @type String
9606     * @static
9607     */
9608    Plugin.NS = 'plugin';
9609
9610    Y.extend(Plugin, Y.Base, {
9611
9612        /**
9613         * The list of event handles for event listeners or AOP injected methods
9614         * applied by the plugin to the host object.
9615         *
9616         * @property _handles
9617         * @private
9618         * @type Array
9619         * @value null
9620         */
9621        _handles: null,
9622
9623        /**
9624         * Initializer lifecycle implementation.
9625         *
9626         * @method initializer
9627         * @param {Object} config Configuration object with property name/value pairs.
9628         */
9629        initializer : function(config) {
9630            this._handles = [];
9631        },
9632
9633        /**
9634         * Destructor lifecycle implementation.
9635         *
9636         * Removes any event listeners or injected methods applied by the Plugin
9637         *
9638         * @method destructor
9639         */
9640        destructor: function() {
9641            // remove all handles
9642            if (this._handles) {
9643                for (var i = 0, l = this._handles.length; i < l; i++) {
9644                   this._handles[i].detach();
9645                }
9646            }
9647        },
9648
9649        /**
9650         * Listens for the "on" moment of events fired by the host,
9651         * or injects code "before" a given method on the host.
9652         *
9653         * @method doBefore
9654         *
9655         * @param strMethod {String} The event to listen for, or method to inject logic before.
9656         * @param fn {Function} The handler function. For events, the "on" moment listener. For methods, the function to execute before the given method is executed.
9657         * @param context {Object} An optional context to call the handler with. The default context is the plugin instance.
9658         * @return handle {EventHandle} The detach handle for the handler.
9659         */
9660        doBefore: function(strMethod, fn, context) {
9661            var host = this.get("host"), handle;
9662
9663            if (strMethod in host) { // method
9664                handle = this.beforeHostMethod(strMethod, fn, context);
9665            } else if (host.on) { // event
9666                handle = this.onHostEvent(strMethod, fn, context);
9667            }
9668
9669            return handle;
9670        },
9671
9672        /**
9673         * Listens for the "after" moment of events fired by the host,
9674         * or injects code "after" a given method on the host.
9675         *
9676         * @method doAfter
9677         *
9678         * @param strMethod {String} The event to listen for, or method to inject logic after.
9679         * @param fn {Function} The handler function. For events, the "after" moment listener. For methods, the function to execute after the given method is executed.
9680         * @param context {Object} An optional context to call the handler with. The default context is the plugin instance.
9681         * @return handle {EventHandle} The detach handle for the listener.
9682         */
9683        doAfter: function(strMethod, fn, context) {
9684            var host = this.get("host"), handle;
9685
9686            if (strMethod in host) { // method
9687                handle = this.afterHostMethod(strMethod, fn, context);
9688            } else if (host.after) { // event
9689                handle = this.afterHostEvent(strMethod, fn, context);
9690            }
9691
9692            return handle;
9693        },
9694
9695        /**
9696         * Listens for the "on" moment of events fired by the host object.
9697         *
9698         * Listeners attached through this method will be detached when the plugin is unplugged.
9699         *
9700         * @method onHostEvent
9701         * @param {String | Object} type The event type.
9702         * @param {Function} fn The listener.
9703         * @param {Object} context The execution context. Defaults to the plugin instance.
9704         * @return handle {EventHandle} The detach handle for the listener.
9705         */
9706        onHostEvent : function(type, fn, context) {
9707            var handle = this.get("host").on(type, fn, context || this);
9708            this._handles.push(handle);
9709            return handle;
9710        },
9711
9712        /**
9713         * Listens for the "on" moment of events fired by the host object one time only.
9714         * The listener is immediately detached when it is executed.
9715         *
9716         * Listeners attached through this method will be detached when the plugin is unplugged.
9717         *
9718         * @method onceHostEvent
9719         * @param {String | Object} type The event type.
9720         * @param {Function} fn The listener.
9721         * @param {Object} context The execution context. Defaults to the plugin instance.
9722         * @return handle {EventHandle} The detach handle for the listener.
9723         */
9724        onceHostEvent : function(type, fn, context) {
9725            var handle = this.get("host").once(type, fn, context || this);
9726            this._handles.push(handle);
9727            return handle;
9728        },
9729
9730        /**
9731         * Listens for the "after" moment of events fired by the host object.
9732         *
9733         * Listeners attached through this method will be detached when the plugin is unplugged.
9734         *
9735         * @method afterHostEvent
9736         * @param {String | Object} type The event type.
9737         * @param {Function} fn The listener.
9738         * @param {Object} context The execution context. Defaults to the plugin instance.
9739         * @return handle {EventHandle} The detach handle for the listener.
9740         */
9741        afterHostEvent : function(type, fn, context) {
9742            var handle = this.get("host").after(type, fn, context || this);
9743            this._handles.push(handle);
9744            return handle;
9745        },
9746
9747        /**
9748         * Listens for the "after" moment of events fired by the host object one time only.
9749         * The listener is immediately detached when it is executed.
9750         *
9751         * Listeners attached through this method will be detached when the plugin is unplugged.
9752         *
9753         * @method onceAfterHostEvent
9754         * @param {String | Object} type The event type.
9755         * @param {Function} fn The listener.
9756         * @param {Object} context The execution context. Defaults to the plugin instance.
9757         * @return handle {EventHandle} The detach handle for the listener.
9758         */
9759        onceAfterHostEvent : function(type, fn, context) {
9760            var handle = this.get("host").onceAfter(type, fn, context || this);
9761            this._handles.push(handle);
9762            return handle;
9763        },
9764
9765        /**
9766         * Injects a function to be executed before a given method on host object.
9767         *
9768         * The function will be detached when the plugin is unplugged.
9769         *
9770         * @method beforeHostMethod
9771         * @param {String} method The name of the method to inject the function before.
9772         * @param {Function} fn The function to inject.
9773         * @param {Object} context The execution context. Defaults to the plugin instance.
9774         * @return handle {EventHandle} The detach handle for the injected function.
9775         */
9776        beforeHostMethod : function(strMethod, fn, context) {
9777            var handle = Y.Do.before(fn, this.get("host"), strMethod, context || this);
9778            this._handles.push(handle);
9779            return handle;
9780        },
9781
9782        /**
9783         * Injects a function to be executed after a given method on host object.
9784         *
9785         * The function will be detached when the plugin is unplugged.
9786         *
9787         * @method afterHostMethod
9788         * @param {String} method The name of the method to inject the function after.
9789         * @param {Function} fn The function to inject.
9790         * @param {Object} context The execution context. Defaults to the plugin instance.
9791         * @return handle {EventHandle} The detach handle for the injected function.
9792         */
9793        afterHostMethod : function(strMethod, fn, context) {
9794            var handle = Y.Do.after(fn, this.get("host"), strMethod, context || this);
9795            this._handles.push(handle);
9796            return handle;
9797        },
9798
9799        toString: function() {
9800            return this.constructor.NAME + '[' + this.constructor.NS + ']';
9801        }
9802    });
9803
9804    Y.namespace("Plugin").Base = Plugin;
9805
9806
9807}, 'patched-v3.18.3', {"requires": ["base-base"]});
9808
9809YUI.add('pluginhost-base', function (Y, NAME) {
9810
9811    /**
9812     * Provides the augmentable PluginHost interface, which can be added to any class.
9813     * @module pluginhost
9814     */
9815
9816    /**
9817     * Provides the augmentable PluginHost interface, which can be added to any class.
9818     * @module pluginhost-base
9819     */
9820
9821    /**
9822     * <p>
9823     * An augmentable class, which provides the augmented class with the ability to host plugins.
9824     * It adds <a href="#method_plug">plug</a> and <a href="#method_unplug">unplug</a> methods to the augmented class, which can
9825     * be used to add or remove plugins from instances of the class.
9826     * </p>
9827     *
9828     * <p>Plugins can also be added through the constructor configuration object passed to the host class' constructor using
9829     * the "plugins" property. Supported values for the "plugins" property are those defined by the <a href="#method_plug">plug</a> method.
9830     *
9831     * For example the following code would add the AnimPlugin and IOPlugin to Overlay (the plugin host):
9832     * <xmp>
9833     * var o = new Overlay({plugins: [ AnimPlugin, {fn:IOPlugin, cfg:{section:"header"}}]});
9834     * </xmp>
9835     * </p>
9836     * <p>
9837     * Plug.Host's protected <a href="#method_initPlugins">_initPlugins</a> and <a href="#method_destroyPlugins">_destroyPlugins</a>
9838     * methods should be invoked by the host class at the appropriate point in the host's lifecyle.
9839     * </p>
9840     *
9841     * @class Plugin.Host
9842     */
9843
9844    var L = Y.Lang;
9845
9846    function PluginHost() {
9847        this._plugins = {};
9848    }
9849
9850    PluginHost.prototype = {
9851
9852        /**
9853         * Adds a plugin to the host object. This will instantiate the
9854         * plugin and attach it to the configured namespace on the host object.
9855         *
9856         * @method plug
9857         * @chainable
9858         * @param P {Function | Object |Array} Accepts the plugin class, or an
9859         * object with a "fn" property specifying the plugin class and
9860         * a "cfg" property specifying the configuration for the Plugin.
9861         * <p>
9862         * Additionally an Array can also be passed in, with the above function or
9863         * object values, allowing the user to add multiple plugins in a single call.
9864         * </p>
9865         * @param config (Optional) If the first argument is the plugin class, the second argument
9866         * can be the configuration for the plugin.
9867         * @return {Base} A reference to the host object
9868         */
9869        plug: function(Plugin, config) {
9870            var i, ln, ns;
9871
9872            if (L.isArray(Plugin)) {
9873                for (i = 0, ln = Plugin.length; i < ln; i++) {
9874                    this.plug(Plugin[i]);
9875                }
9876            } else {
9877                if (Plugin && !L.isFunction(Plugin)) {
9878                    config = Plugin.cfg;
9879                    Plugin = Plugin.fn;
9880                }
9881
9882                // Plugin should be fn by now
9883                if (Plugin && Plugin.NS) {
9884                    ns = Plugin.NS;
9885
9886                    config = config || {};
9887                    config.host = this;
9888
9889                    if (this.hasPlugin(ns)) {
9890                        // Update config
9891                        if (this[ns].setAttrs) {
9892                            this[ns].setAttrs(config);
9893                        }
9894                        else {
9895                        }
9896                    } else {
9897                        // Create new instance
9898                        this[ns] = new Plugin(config);
9899                        this._plugins[ns] = Plugin;
9900                    }
9901                }
9902                else {
9903                }
9904            }
9905            return this;
9906        },
9907
9908        /**
9909         * Removes a plugin from the host object. This will destroy the
9910         * plugin instance and delete the namespace from the host object.
9911         *
9912         * @method unplug
9913         * @param {String | Function} plugin The namespace of the plugin, or the plugin class with the static NS namespace property defined. If not provided,
9914         * all registered plugins are unplugged.
9915         * @return {Base} A reference to the host object
9916         * @chainable
9917         */
9918        unplug: function(plugin) {
9919            var ns = plugin,
9920                plugins = this._plugins;
9921
9922            if (plugin) {
9923                if (L.isFunction(plugin)) {
9924                    ns = plugin.NS;
9925                    if (ns && (!plugins[ns] || plugins[ns] !== plugin)) {
9926                        ns = null;
9927                    }
9928                }
9929
9930                if (ns) {
9931                    if (this[ns]) {
9932                        if (this[ns].destroy) {
9933                            this[ns].destroy();
9934                        }
9935                        delete this[ns];
9936                    }
9937                    if (plugins[ns]) {
9938                        delete plugins[ns];
9939                    }
9940                }
9941            } else {
9942                for (ns in this._plugins) {
9943                    if (this._plugins.hasOwnProperty(ns)) {
9944                        this.unplug(ns);
9945                    }
9946                }
9947            }
9948            return this;
9949        },
9950
9951        /**
9952         * Determines if a plugin has plugged into this host.
9953         *
9954         * @method hasPlugin
9955         * @param {String} ns The plugin's namespace
9956         * @return {Plugin} Returns a truthy value (the plugin instance) if present, or undefined if not.
9957         */
9958        hasPlugin : function(ns) {
9959            return (this._plugins[ns] && this[ns]);
9960        },
9961
9962        /**
9963         * Initializes static plugins registered on the host (using the
9964         * Base.plug static method) and any plugins passed to the
9965         * instance through the "plugins" configuration property.
9966         *
9967         * @method _initPlugins
9968         * @param {Object} config The configuration object with property name/value pairs.
9969         * @private
9970         */
9971
9972        _initPlugins: function(config) {
9973            this._plugins = this._plugins || {};
9974
9975            if (this._initConfigPlugins) {
9976                this._initConfigPlugins(config);
9977            }
9978        },
9979
9980        /**
9981         * Unplugs and destroys all plugins on the host
9982         * @method _destroyPlugins
9983         * @private
9984         */
9985        _destroyPlugins: function() {
9986            this.unplug();
9987        }
9988    };
9989
9990    Y.namespace("Plugin").Host = PluginHost;
9991
9992
9993}, 'patched-v3.18.3', {"requires": ["yui-base"]});
9994
9995YUI.add('pluginhost-config', function (Y, NAME) {
9996
9997    /**
9998     * Adds pluginhost constructor configuration and static configuration support
9999     * @submodule pluginhost-config
10000     */
10001
10002    var PluginHost = Y.Plugin.Host,
10003        L = Y.Lang;
10004
10005    /**
10006     * A protected initialization method, used by the host class to initialize
10007     * plugin configurations passed the constructor, through the config object.
10008     *
10009     * Host objects should invoke this method at the appropriate time in their
10010     * construction lifecycle.
10011     *
10012     * @method _initConfigPlugins
10013     * @param {Object} config The configuration object passed to the constructor
10014     * @protected
10015     * @for Plugin.Host
10016     */
10017    PluginHost.prototype._initConfigPlugins = function(config) {
10018
10019        // Class Configuration
10020        var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
10021            plug = [],
10022            unplug = {},
10023            constructor, i, classPlug, classUnplug, pluginClassName;
10024
10025        // TODO: Room for optimization. Can we apply statically/unplug in same pass?
10026        for (i = classes.length - 1; i >= 0; i--) {
10027            constructor = classes[i];
10028
10029            classUnplug = constructor._UNPLUG;
10030            if (classUnplug) {
10031                // subclasses over-write
10032                Y.mix(unplug, classUnplug, true);
10033            }
10034
10035            classPlug = constructor._PLUG;
10036            if (classPlug) {
10037                // subclasses over-write
10038                Y.mix(plug, classPlug, true);
10039            }
10040        }
10041
10042        for (pluginClassName in plug) {
10043            if (plug.hasOwnProperty(pluginClassName)) {
10044                if (!unplug[pluginClassName]) {
10045                    this.plug(plug[pluginClassName]);
10046                }
10047            }
10048        }
10049
10050        // User Configuration
10051        if (config && config.plugins) {
10052            this.plug(config.plugins);
10053        }
10054    };
10055
10056    /**
10057     * Registers plugins to be instantiated at the class level (plugins
10058     * which should be plugged into every instance of the class by default).
10059     *
10060     * @method plug
10061     * @static
10062     *
10063     * @param {Function} hostClass The host class on which to register the plugins
10064     * @param {Function | Array} plugin Either the plugin class, an array of plugin classes or an array of objects (with fn and cfg properties defined)
10065     * @param {Object} config (Optional) If plugin is the plugin class, the configuration for the plugin
10066     * @for Plugin.Host
10067     */
10068    PluginHost.plug = function(hostClass, plugin, config) {
10069        // Cannot plug into Base, since Plugins derive from Base [ will cause infinite recurrsion ]
10070        var p, i, l, name;
10071
10072        if (hostClass !== Y.Base) {
10073            hostClass._PLUG = hostClass._PLUG || {};
10074
10075            if (!L.isArray(plugin)) {
10076                if (config) {
10077                    plugin = {fn:plugin, cfg:config};
10078                }
10079                plugin = [plugin];
10080            }
10081
10082            for (i = 0, l = plugin.length; i < l;i++) {
10083                p = plugin[i];
10084                name = p.NAME || p.fn.NAME;
10085                hostClass._PLUG[name] = p;
10086            }
10087        }
10088    };
10089
10090    /**
10091     * Unregisters any class level plugins which have been registered by the host class, or any
10092     * other class in the hierarchy.
10093     *
10094     * @method unplug
10095     * @static
10096     *
10097     * @param {Function} hostClass The host class from which to unregister the plugins
10098     * @param {Function | Array} plugin The plugin class, or an array of plugin classes
10099     * @for Plugin.Host
10100     */
10101    PluginHost.unplug = function(hostClass, plugin) {
10102        var p, i, l, name;
10103
10104        if (hostClass !== Y.Base) {
10105            hostClass._UNPLUG = hostClass._UNPLUG || {};
10106
10107            if (!L.isArray(plugin)) {
10108                plugin = [plugin];
10109            }
10110
10111            for (i = 0, l = plugin.length; i < l; i++) {
10112                p = plugin[i];
10113                name = p.NAME;
10114                if (!hostClass._PLUG[name]) {
10115                    hostClass._UNPLUG[name] = p;
10116                } else {
10117                    delete hostClass._PLUG[name];
10118                }
10119            }
10120        }
10121    };
10122
10123
10124}, 'patched-v3.18.3', {"requires": ["pluginhost-base"]});
10125
10126YUI.add('querystring-stringify-simple', function (Y, NAME) {
10127
10128/*global Y */
10129/**
10130 * <p>Provides Y.QueryString.stringify method for converting objects to Query Strings.
10131 * This is a subset implementation of the full querystring-stringify.</p>
10132 * <p>This module provides the bare minimum functionality (encoding a hash of simple values),
10133 * without the additional support for nested data structures.  Every key-value pair is
10134 * encoded by encodeURIComponent.</p>
10135 * <p>This module provides a minimalistic way for io to handle  single-level objects
10136 * as transaction data.</p>
10137 *
10138 * @module querystring
10139 * @submodule querystring-stringify-simple
10140 */
10141
10142var QueryString = Y.namespace("QueryString"),
10143    EUC = encodeURIComponent;
10144
10145
10146QueryString.stringify = function (obj, c) {
10147    var qs = [],
10148        // Default behavior is false; standard key notation.
10149        s = c && c.arrayKey ? true : false,
10150        key, i, l;
10151
10152    for (key in obj) {
10153        if (obj.hasOwnProperty(key)) {
10154            if (Y.Lang.isArray(obj[key])) {
10155                for (i = 0, l = obj[key].length; i < l; i++) {
10156                    qs.push(EUC(s ? key + '[]' : key) + '=' + EUC(obj[key][i]));
10157                }
10158            }
10159            else {
10160                qs.push(EUC(key) + '=' + EUC(obj[key]));
10161            }
10162        }
10163    }
10164
10165    return qs.join('&');
10166};
10167
10168
10169}, 'patched-v3.18.3', {"requires": ["yui-base"]});
10170
10171YUI.add('queue-promote', function (Y, NAME) {
10172
10173/**
10174 * Adds methods promote, remove, and indexOf to Queue instances.
10175 *
10176 * @module queue-promote
10177 * @for Queue
10178 */
10179
10180Y.mix(Y.Queue.prototype, {
10181    /**
10182     * Returns the current index in the queue of the specified item
10183     *
10184     * @method indexOf
10185     * @param needle {MIXED} the item to search for
10186     * @return {Number} the index of the item or -1 if not found
10187     */
10188    indexOf : function (callback) {
10189        return Y.Array.indexOf(this._q, callback);
10190    },
10191
10192    /**
10193     * Moves the referenced item to the head of the queue
10194     *
10195     * @method promote
10196     * @param item {MIXED} an item in the queue
10197     */
10198    promote : function (callback) {
10199        var index = this.indexOf(callback);
10200
10201        if (index > -1) {
10202            this._q.unshift(this._q.splice(index,1)[0]);
10203        }
10204    },
10205
10206    /**
10207     * Removes the referenced item from the queue
10208     *
10209     * @method remove
10210     * @param item {MIXED} an item in the queue
10211     */
10212    remove : function (callback) {
10213        var index = this.indexOf(callback);
10214
10215        if (index > -1) {
10216            this._q.splice(index,1);
10217        }
10218    }
10219
10220});
10221
10222
10223}, 'patched-v3.18.3', {"requires": ["yui-base"]});
10224
10225YUI.add('selector-css2', function (Y, NAME) {
10226
10227/**
10228 * The selector module provides helper methods allowing CSS2 Selectors to be used with DOM elements.
10229 * @module dom
10230 * @submodule selector-css2
10231 * @for Selector
10232 */
10233
10234/*
10235 * Provides helper methods for collecting and filtering DOM elements.
10236 */
10237
10238var PARENT_NODE = 'parentNode',
10239    TAG_NAME = 'tagName',
10240    ATTRIBUTES = 'attributes',
10241    COMBINATOR = 'combinator',
10242    PSEUDOS = 'pseudos',
10243
10244    Selector = Y.Selector,
10245
10246    SelectorCSS2 = {
10247        _reRegExpTokens: /([\^\$\?\[\]\*\+\-\.\(\)\|\\])/,
10248        SORT_RESULTS: true,
10249
10250        // TODO: better detection, document specific
10251        _isXML: (function() {
10252            var isXML = (Y.config.doc.createElement('div').tagName !== 'DIV');
10253            return isXML;
10254        }()),
10255
10256        /**
10257         * Mapping of shorthand tokens to corresponding attribute selector
10258         * @property shorthand
10259         * @type object
10260         */
10261        shorthand: {
10262            '\\#(-?[_a-z0-9]+[-\\w\\uE000]*)': '[id=$1]',
10263            '\\.(-?[_a-z]+[-\\w\\uE000]*)': '[className~=$1]'
10264        },
10265
10266        /**
10267         * List of operators and corresponding boolean functions.
10268         * These functions are passed the attribute and the current node's value of the attribute.
10269         * @property operators
10270         * @type object
10271         */
10272        operators: {
10273            '': function(node, attr) { return Y.DOM.getAttribute(node, attr) !== ''; }, // Just test for existence of attribute
10274            '~=': '(?:^|\\s+){val}(?:\\s+|$)', // space-delimited
10275            '|=': '^{val}-?' // optional hyphen-delimited
10276        },
10277
10278        pseudos: {
10279           'first-child': function(node) {
10280                return Y.DOM._children(node[PARENT_NODE])[0] === node;
10281            }
10282        },
10283
10284        _bruteQuery: function(selector, root, firstOnly) {
10285            var ret = [],
10286                nodes = [],
10287                visited,
10288                tokens = Selector._tokenize(selector),
10289                token = tokens[tokens.length - 1],
10290                rootDoc = Y.DOM._getDoc(root),
10291                child,
10292                id,
10293                className,
10294                tagName,
10295                isUniversal;
10296
10297            if (token) {
10298                // prefilter nodes
10299                id = token.id;
10300                className = token.className;
10301                tagName = token.tagName || '*';
10302
10303                if (typeof root.getElementsByTagName !== "undefined") { // non-IE lacks DOM api on doc frags
10304                    // try ID first, unless no root.all && root not in document
10305                    // (root.all works off document, but not getElementById)
10306                    if (id && (root.all || (root.nodeType === 9 || Y.DOM.inDoc(root)))) {
10307                        nodes = Y.DOM.allById(id, root);
10308                    // try className
10309                    } else if (className) {
10310                        nodes = root.getElementsByClassName(className);
10311                    } else { // default to tagName
10312                        nodes = root.getElementsByTagName(tagName);
10313                    }
10314
10315                } else { // brute getElementsByTagName()
10316                    visited = [];
10317                    child = root.firstChild;
10318                    isUniversal = tagName === "*";
10319                    while (child) {
10320                        while (child) {
10321                            // IE 6-7 considers comment nodes as element nodes, and gives them the tagName "!".
10322                            // We can filter them out by checking if its tagName is > "@".
10323                            // This also avoids a superflous nodeType === 1 check.
10324                            if (child.tagName > "@" && (isUniversal || child.tagName === tagName)) {
10325                                nodes.push(child);
10326                            }
10327
10328                            // We may need to traverse back up the tree to find more unvisited subtrees.
10329                            visited.push(child);
10330                            child = child.firstChild;
10331                        }
10332
10333                        // Find the most recently visited node who has a next sibling.
10334                        while (visited.length > 0 && !child) {
10335                            child = visited.pop().nextSibling;
10336                        }
10337                    }
10338                }
10339
10340                if (nodes.length) {
10341                    ret = Selector._filterNodes(nodes, tokens, firstOnly);
10342                }
10343            }
10344
10345            return ret;
10346        },
10347
10348        _filterNodes: function(nodes, tokens, firstOnly) {
10349            var i = 0,
10350                j,
10351                len = tokens.length,
10352                n = len - 1,
10353                result = [],
10354                node = nodes[0],
10355                tmpNode = node,
10356                getters = Y.Selector.getters,
10357                operator,
10358                combinator,
10359                token,
10360                path,
10361                pass,
10362                value,
10363                tests,
10364                test;
10365
10366            for (i = 0; (tmpNode = node = nodes[i++]);) {
10367                n = len - 1;
10368                path = null;
10369
10370                testLoop:
10371                while (tmpNode && tmpNode.tagName) {
10372                    token = tokens[n];
10373                    tests = token.tests;
10374                    j = tests.length;
10375                    if (j && !pass) {
10376                        while ((test = tests[--j])) {
10377                            operator = test[1];
10378                            if (getters[test[0]]) {
10379                                value = getters[test[0]](tmpNode, test[0]);
10380                            } else {
10381                                value = tmpNode[test[0]];
10382                                if (test[0] === 'tagName' && !Selector._isXML) {
10383                                    value = value.toUpperCase();
10384                                }
10385                                if (typeof value != 'string' && value !== undefined && value.toString) {
10386                                    value = value.toString(); // coerce for comparison
10387                                } else if (value === undefined && tmpNode.getAttribute) {
10388                                    // use getAttribute for non-standard attributes
10389                                    value = tmpNode.getAttribute(test[0], 2); // 2 === force string for IE
10390                                }
10391                            }
10392
10393                            if ((operator === '=' && value !== test[2]) ||  // fast path for equality
10394                                (typeof operator !== 'string' && // protect against String.test monkey-patch (Moo)
10395                                operator.test && !operator.test(value)) ||  // regex test
10396                                (!operator.test && // protect against RegExp as function (webkit)
10397                                        typeof operator === 'function' && !operator(tmpNode, test[0], test[2]))) { // function test
10398
10399                                // skip non element nodes or non-matching tags
10400                                if ((tmpNode = tmpNode[path])) {
10401                                    while (tmpNode &&
10402                                        (!tmpNode.tagName ||
10403                                            (token.tagName && token.tagName !== tmpNode.tagName))
10404                                    ) {
10405                                        tmpNode = tmpNode[path];
10406                                    }
10407                                }
10408                                continue testLoop;
10409                            }
10410                        }
10411                    }
10412
10413                    n--; // move to next token
10414                    // now that we've passed the test, move up the tree by combinator
10415                    if (!pass && (combinator = token.combinator)) {
10416                        path = combinator.axis;
10417                        tmpNode = tmpNode[path];
10418
10419                        // skip non element nodes
10420                        while (tmpNode && !tmpNode.tagName) {
10421                            tmpNode = tmpNode[path];
10422                        }
10423
10424                        if (combinator.direct) { // one pass only
10425                            path = null;
10426                        }
10427
10428                    } else { // success if we made it this far
10429                        result.push(node);
10430                        if (firstOnly) {
10431                            return result;
10432                        }
10433                        break;
10434                    }
10435                }
10436            }
10437            node = tmpNode = null;
10438            return result;
10439        },
10440
10441        combinators: {
10442            ' ': {
10443                axis: 'parentNode'
10444            },
10445
10446            '>': {
10447                axis: 'parentNode',
10448                direct: true
10449            },
10450
10451
10452            '+': {
10453                axis: 'previousSibling',
10454                direct: true
10455            }
10456        },
10457
10458        _parsers: [
10459            {
10460                name: ATTRIBUTES,
10461                re: /^\uE003(-?[a-z]+[\w\-]*)+([~\|\^\$\*!=]=?)?['"]?([^\uE004'"]*)['"]?\uE004/i,
10462                fn: function(match, token) {
10463                    var operator = match[2] || '',
10464                        operators = Selector.operators,
10465                        escVal = (match[3]) ? match[3].replace(/\\/g, '') : '',
10466                        test;
10467
10468                    // add prefiltering for ID and CLASS
10469                    if ((match[1] === 'id' && operator === '=') ||
10470                            (match[1] === 'className' &&
10471                            Y.config.doc.documentElement.getElementsByClassName &&
10472                            (operator === '~=' || operator === '='))) {
10473                        token.prefilter = match[1];
10474
10475
10476                        match[3] = escVal;
10477
10478                        // escape all but ID for prefilter, which may run through QSA (via Dom.allById)
10479                        token[match[1]] = (match[1] === 'id') ? match[3] : escVal;
10480
10481                    }
10482
10483                    // add tests
10484                    if (operator in operators) {
10485                        test = operators[operator];
10486                        if (typeof test === 'string') {
10487                            match[3] = escVal.replace(Selector._reRegExpTokens, '\\$1');
10488                            test = new RegExp(test.replace('{val}', match[3]));
10489                        }
10490                        match[2] = test;
10491                    }
10492                    if (!token.last || token.prefilter !== match[1]) {
10493                        return match.slice(1);
10494                    }
10495                }
10496            },
10497            {
10498                name: TAG_NAME,
10499                re: /^((?:-?[_a-z]+[\w-]*)|\*)/i,
10500                fn: function(match, token) {
10501                    var tag = match[1];
10502
10503                    if (!Selector._isXML) {
10504                        tag = tag.toUpperCase();
10505                    }
10506
10507                    token.tagName = tag;
10508
10509                    if (tag !== '*' && (!token.last || token.prefilter)) {
10510                        return [TAG_NAME, '=', tag];
10511                    }
10512                    if (!token.prefilter) {
10513                        token.prefilter = 'tagName';
10514                    }
10515                }
10516            },
10517            {
10518                name: COMBINATOR,
10519                re: /^\s*([>+~]|\s)\s*/,
10520                fn: function(match, token) {
10521                }
10522            },
10523            {
10524                name: PSEUDOS,
10525                re: /^:([\-\w]+)(?:\uE005['"]?([^\uE005]*)['"]?\uE006)*/i,
10526                fn: function(match, token) {
10527                    var test = Selector[PSEUDOS][match[1]];
10528                    if (test) { // reorder match array and unescape special chars for tests
10529                        if (match[2]) {
10530                            match[2] = match[2].replace(/\\/g, '');
10531                        }
10532                        return [match[2], test];
10533                    } else { // selector token not supported (possibly missing CSS3 module)
10534                        return false;
10535                    }
10536                }
10537            }
10538            ],
10539
10540        _getToken: function(token) {
10541            return {
10542                tagName: null,
10543                id: null,
10544                className: null,
10545                attributes: {},
10546                combinator: null,
10547                tests: []
10548            };
10549        },
10550
10551        /*
10552            Break selector into token units per simple selector.
10553            Combinator is attached to the previous token.
10554         */
10555        _tokenize: function(selector) {
10556            selector = selector || '';
10557            selector = Selector._parseSelector(Y.Lang.trim(selector));
10558            var token = Selector._getToken(),     // one token per simple selector (left selector holds combinator)
10559                query = selector, // original query for debug report
10560                tokens = [],    // array of tokens
10561                found = false,  // whether or not any matches were found this pass
10562                match,         // the regex match
10563                test,
10564                i, parser;
10565
10566            /*
10567                Search for selector patterns, store, and strip them from the selector string
10568                until no patterns match (invalid selector) or we run out of chars.
10569
10570                Multiple attributes and pseudos are allowed, in any order.
10571                for example:
10572                    'form:first-child[type=button]:not(button)[lang|=en]'
10573            */
10574            outer:
10575            do {
10576                found = false; // reset after full pass
10577                for (i = 0; (parser = Selector._parsers[i++]);) {
10578                    if ( (match = parser.re.exec(selector)) ) { // note assignment
10579                        if (parser.name !== COMBINATOR ) {
10580                            token.selector = selector;
10581                        }
10582                        selector = selector.replace(match[0], ''); // strip current match from selector
10583                        if (!selector.length) {
10584                            token.last = true;
10585                        }
10586
10587                        if (Selector._attrFilters[match[1]]) { // convert class to className, etc.
10588                            match[1] = Selector._attrFilters[match[1]];
10589                        }
10590
10591                        test = parser.fn(match, token);
10592                        if (test === false) { // selector not supported
10593                            found = false;
10594                            break outer;
10595                        } else if (test) {
10596                            token.tests.push(test);
10597                        }
10598
10599                        if (!selector.length || parser.name === COMBINATOR) {
10600                            tokens.push(token);
10601                            token = Selector._getToken(token);
10602                            if (parser.name === COMBINATOR) {
10603                                token.combinator = Y.Selector.combinators[match[1]];
10604                            }
10605                        }
10606                        found = true;
10607                    }
10608                }
10609            } while (found && selector.length);
10610
10611            if (!found || selector.length) { // not fully parsed
10612                tokens = [];
10613            }
10614            return tokens;
10615        },
10616
10617        _replaceMarkers: function(selector) {
10618            selector = selector.replace(/\[/g, '\uE003');
10619            selector = selector.replace(/\]/g, '\uE004');
10620
10621            selector = selector.replace(/\(/g, '\uE005');
10622            selector = selector.replace(/\)/g, '\uE006');
10623            return selector;
10624        },
10625
10626        _replaceShorthand: function(selector) {
10627            var shorthand = Y.Selector.shorthand,
10628                re;
10629
10630            for (re in shorthand) {
10631                if (shorthand.hasOwnProperty(re)) {
10632                    selector = selector.replace(new RegExp(re, 'gi'), shorthand[re]);
10633                }
10634            }
10635
10636            return selector;
10637        },
10638
10639        _parseSelector: function(selector) {
10640            var replaced = Y.Selector._replaceSelector(selector),
10641                selector = replaced.selector;
10642
10643            // replace shorthand (".foo, #bar") after pseudos and attrs
10644            // to avoid replacing unescaped chars
10645            selector = Y.Selector._replaceShorthand(selector);
10646
10647            selector = Y.Selector._restore('attr', selector, replaced.attrs);
10648            selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
10649
10650            // replace braces and parens before restoring escaped chars
10651            // to avoid replacing ecaped markers
10652            selector = Y.Selector._replaceMarkers(selector);
10653            selector = Y.Selector._restore('esc', selector, replaced.esc);
10654
10655            return selector;
10656        },
10657
10658        _attrFilters: {
10659            'class': 'className',
10660            'for': 'htmlFor'
10661        },
10662
10663        getters: {
10664            href: function(node, attr) {
10665                return Y.DOM.getAttribute(node, attr);
10666            },
10667
10668            id: function(node, attr) {
10669                return Y.DOM.getId(node);
10670            }
10671        }
10672    };
10673
10674Y.mix(Y.Selector, SelectorCSS2, true);
10675Y.Selector.getters.src = Y.Selector.getters.rel = Y.Selector.getters.href;
10676
10677// IE wants class with native queries
10678if (Y.Selector.useNative && Y.config.doc.querySelector) {
10679    Y.Selector.shorthand['\\.(-?[_a-z]+[-\\w]*)'] = '[class~=$1]';
10680}
10681
10682
10683}, 'patched-v3.18.3', {"requires": ["selector-native"]});
10684
10685YUI.add('selector-css3', function (Y, NAME) {
10686
10687/**
10688 * The selector css3 module provides support for css3 selectors.
10689 * @module dom
10690 * @submodule selector-css3
10691 * @for Selector
10692 */
10693
10694/*
10695    an+b = get every _a_th node starting at the _b_th
10696    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
10697    1n+b =  get every element starting from b ("1" may may be omitted, e.g. "1n+0" or "n+0" or "n")
10698    an+0 = get every _a_th element, "0" may be omitted
10699*/
10700
10701Y.Selector._reNth = /^(?:([\-]?\d*)(n){1}|(odd|even)$)*([\-+]?\d*)$/;
10702
10703Y.Selector._getNth = function(node, expr, tag, reverse) {
10704    Y.Selector._reNth.test(expr);
10705    var a = parseInt(RegExp.$1, 10), // include every _a_ elements (zero means no repeat, just first _a_)
10706        n = RegExp.$2, // "n"
10707        oddeven = RegExp.$3, // "odd" or "even"
10708        b = parseInt(RegExp.$4, 10) || 0, // start scan from element _b_
10709        result = [],
10710        siblings = Y.DOM._children(node.parentNode, tag),
10711        op;
10712
10713    if (oddeven) {
10714        a = 2; // always every other
10715        op = '+';
10716        n = 'n';
10717        b = (oddeven === 'odd') ? 1 : 0;
10718    } else if ( isNaN(a) ) {
10719        a = (n) ? 1 : 0; // start from the first or no repeat
10720    }
10721
10722    if (a === 0) { // just the first
10723        if (reverse) {
10724            b = siblings.length - b + 1;
10725        }
10726
10727        if (siblings[b - 1] === node) {
10728            return true;
10729        } else {
10730            return false;
10731        }
10732
10733    } else if (a < 0) {
10734        reverse = !!reverse;
10735        a = Math.abs(a);
10736    }
10737
10738    if (!reverse) {
10739        for (var i = b - 1, len = siblings.length; i < len; i += a) {
10740            if ( i >= 0 && siblings[i] === node ) {
10741                return true;
10742            }
10743        }
10744    } else {
10745        for (var i = siblings.length - b, len = siblings.length; i >= 0; i -= a) {
10746            if ( i < len && siblings[i] === node ) {
10747                return true;
10748            }
10749        }
10750    }
10751    return false;
10752};
10753
10754Y.mix(Y.Selector.pseudos, {
10755    'root': function(node) {
10756        return node === node.ownerDocument.documentElement;
10757    },
10758
10759    'nth-child': function(node, expr) {
10760        return Y.Selector._getNth(node, expr);
10761    },
10762
10763    'nth-last-child': function(node, expr) {
10764        return Y.Selector._getNth(node, expr, null, true);
10765    },
10766
10767    'nth-of-type': function(node, expr) {
10768        return Y.Selector._getNth(node, expr, node.tagName);
10769    },
10770
10771    'nth-last-of-type': function(node, expr) {
10772        return Y.Selector._getNth(node, expr, node.tagName, true);
10773    },
10774
10775    'last-child': function(node) {
10776        var children = Y.DOM._children(node.parentNode);
10777        return children[children.length - 1] === node;
10778    },
10779
10780    'first-of-type': function(node) {
10781        return Y.DOM._children(node.parentNode, node.tagName)[0] === node;
10782    },
10783
10784    'last-of-type': function(node) {
10785        var children = Y.DOM._children(node.parentNode, node.tagName);
10786        return children[children.length - 1] === node;
10787    },
10788
10789    'only-child': function(node) {
10790        var children = Y.DOM._children(node.parentNode);
10791        return children.length === 1 && children[0] === node;
10792    },
10793
10794    'only-of-type': function(node) {
10795        var children = Y.DOM._children(node.parentNode, node.tagName);
10796        return children.length === 1 && children[0] === node;
10797    },
10798
10799    'empty': function(node) {
10800        return node.childNodes.length === 0;
10801    },
10802
10803    'not': function(node, expr) {
10804        return !Y.Selector.test(node, expr);
10805    },
10806
10807    'contains': function(node, expr) {
10808        var text = node.innerText || node.textContent || '';
10809        return text.indexOf(expr) > -1;
10810    },
10811
10812    'checked': function(node) {
10813        return (node.checked === true || node.selected === true);
10814    },
10815
10816    enabled: function(node) {
10817        return (node.disabled !== undefined && !node.disabled);
10818    },
10819
10820    disabled: function(node) {
10821        return (node.disabled);
10822    }
10823});
10824
10825Y.mix(Y.Selector.operators, {
10826    '^=': '^{val}', // Match starts with value
10827    '$=': '{val}$', // Match ends with value
10828    '*=': '{val}' // Match contains value as substring
10829});
10830
10831Y.Selector.combinators['~'] = {
10832    axis: 'previousSibling'
10833};
10834
10835
10836}, 'patched-v3.18.3', {"requires": ["selector-native", "selector-css2"]});
10837
10838YUI.add('selector-native', function (Y, NAME) {
10839
10840(function(Y) {
10841/**
10842 * The selector-native module provides support for native querySelector
10843 * @module dom
10844 * @submodule selector-native
10845 * @for Selector
10846 */
10847
10848/**
10849 * Provides support for using CSS selectors to query the DOM
10850 * @class Selector
10851 * @static
10852 * @for Selector
10853 */
10854
10855Y.namespace('Selector'); // allow native module to standalone
10856
10857var COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
10858    OWNER_DOCUMENT = 'ownerDocument';
10859
10860var Selector = {
10861    _types: {
10862        esc: {
10863            token: '\uE000',
10864            re: /\\[:\[\]\(\)#\.\'\>+~"]/gi
10865        },
10866
10867        attr: {
10868            token: '\uE001',
10869            re: /(\[[^\]]*\])/g
10870        },
10871
10872        pseudo: {
10873            token: '\uE002',
10874            re: /(\([^\)]*\))/g
10875        }
10876    },
10877
10878    /**
10879     *  Use the native version of `querySelectorAll`, if it exists.
10880     *
10881     * @property useNative
10882     * @default true
10883     * @static
10884     */
10885    useNative: true,
10886
10887    _escapeId: function(id) {
10888        if (id) {
10889            id = id.replace(/([:\[\]\(\)#\.'<>+~"])/g,'\\$1');
10890        }
10891        return id;
10892    },
10893
10894    _compare: ('sourceIndex' in Y.config.doc.documentElement) ?
10895        function(nodeA, nodeB) {
10896            var a = nodeA.sourceIndex,
10897                b = nodeB.sourceIndex;
10898
10899            if (a === b) {
10900                return 0;
10901            } else if (a > b) {
10902                return 1;
10903            }
10904
10905            return -1;
10906
10907        } : (Y.config.doc.documentElement[COMPARE_DOCUMENT_POSITION] ?
10908        function(nodeA, nodeB) {
10909            if (nodeA[COMPARE_DOCUMENT_POSITION](nodeB) & 4) {
10910                return -1;
10911            } else {
10912                return 1;
10913            }
10914        } :
10915        function(nodeA, nodeB) {
10916            var rangeA, rangeB, compare;
10917            if (nodeA && nodeB) {
10918                rangeA = nodeA[OWNER_DOCUMENT].createRange();
10919                rangeA.setStart(nodeA, 0);
10920                rangeB = nodeB[OWNER_DOCUMENT].createRange();
10921                rangeB.setStart(nodeB, 0);
10922                compare = rangeA.compareBoundaryPoints(1, rangeB); // 1 === Range.START_TO_END
10923            }
10924
10925            return compare;
10926
10927    }),
10928
10929    _sort: function(nodes) {
10930        if (nodes) {
10931            nodes = Y.Array(nodes, 0, true);
10932            if (nodes.sort) {
10933                nodes.sort(Selector._compare);
10934            }
10935        }
10936
10937        return nodes;
10938    },
10939
10940    _deDupe: function(nodes) {
10941        var ret = [],
10942            i, node;
10943
10944        for (i = 0; (node = nodes[i++]);) {
10945            if (!node._found) {
10946                ret[ret.length] = node;
10947                node._found = true;
10948            }
10949        }
10950
10951        for (i = 0; (node = ret[i++]);) {
10952            node._found = null;
10953            node.removeAttribute('_found');
10954        }
10955
10956        return ret;
10957    },
10958
10959    /**
10960     * Retrieves a set of nodes based on a given CSS selector.
10961     * @method query
10962     *
10963     * @param {String} selector A CSS selector.
10964     * @param {HTMLElement} root optional A node to start the query from. Defaults to `Y.config.doc`.
10965     * @param {Boolean} firstOnly optional Whether or not to return only the first match.
10966     * @return {HTMLElement[]} The array of nodes that matched the given selector.
10967     * @static
10968     */
10969    query: function(selector, root, firstOnly, skipNative) {
10970        root = root || Y.config.doc;
10971        var ret = [],
10972            useNative = (Y.Selector.useNative && Y.config.doc.querySelector && !skipNative),
10973            queries = [[selector, root]],
10974            query,
10975            result,
10976            i,
10977            fn = (useNative) ? Y.Selector._nativeQuery : Y.Selector._bruteQuery;
10978
10979        if (selector && fn) {
10980            // split group into seperate queries
10981            if (!skipNative && // already done if skipping
10982                    (!useNative || root.tagName)) { // split native when element scoping is needed
10983                queries = Selector._splitQueries(selector, root);
10984            }
10985
10986            for (i = 0; (query = queries[i++]);) {
10987                result = fn(query[0], query[1], firstOnly);
10988                if (!firstOnly) { // coerce DOM Collection to Array
10989                    result = Y.Array(result, 0, true);
10990                }
10991                if (result) {
10992                    ret = ret.concat(result);
10993                }
10994            }
10995
10996            if (queries.length > 1) { // remove dupes and sort by doc order
10997                ret = Selector._sort(Selector._deDupe(ret));
10998            }
10999        }
11000
11001        return (firstOnly) ? (ret[0] || null) : ret;
11002
11003    },
11004
11005    _replaceSelector: function(selector) {
11006        var esc = Y.Selector._parse('esc', selector), // pull escaped colon, brackets, etc.
11007            attrs,
11008            pseudos;
11009
11010        // first replace escaped chars, which could be present in attrs or pseudos
11011        selector = Y.Selector._replace('esc', selector);
11012
11013        // then replace pseudos before attrs to avoid replacing :not([foo])
11014        pseudos = Y.Selector._parse('pseudo', selector);
11015        selector = Selector._replace('pseudo', selector);
11016
11017        attrs = Y.Selector._parse('attr', selector);
11018        selector = Y.Selector._replace('attr', selector);
11019
11020        return {
11021            esc: esc,
11022            attrs: attrs,
11023            pseudos: pseudos,
11024            selector: selector
11025        };
11026    },
11027
11028    _restoreSelector: function(replaced) {
11029        var selector = replaced.selector;
11030        selector = Y.Selector._restore('attr', selector, replaced.attrs);
11031        selector = Y.Selector._restore('pseudo', selector, replaced.pseudos);
11032        selector = Y.Selector._restore('esc', selector, replaced.esc);
11033        return selector;
11034    },
11035
11036    _replaceCommas: function(selector) {
11037        var replaced = Y.Selector._replaceSelector(selector),
11038            selector = replaced.selector;
11039
11040        if (selector) {
11041            selector = selector.replace(/,/g, '\uE007');
11042            replaced.selector = selector;
11043            selector = Y.Selector._restoreSelector(replaced);
11044        }
11045        return selector;
11046    },
11047
11048    // allows element scoped queries to begin with combinator
11049    // e.g. query('> p', document.body) === query('body > p')
11050    _splitQueries: function(selector, node) {
11051        if (selector.indexOf(',') > -1) {
11052            selector = Y.Selector._replaceCommas(selector);
11053        }
11054
11055        var groups = selector.split('\uE007'), // split on replaced comma token
11056            queries = [],
11057            prefix = '',
11058            id,
11059            i,
11060            len;
11061
11062        if (node) {
11063            // enforce for element scoping
11064            if (node.nodeType === 1) { // Elements only
11065                id = Y.Selector._escapeId(Y.DOM.getId(node));
11066
11067                if (!id) {
11068                    id = Y.guid();
11069                    Y.DOM.setId(node, id);
11070                }
11071
11072                prefix = '[id="' + id + '"] ';
11073            }
11074
11075            for (i = 0, len = groups.length; i < len; ++i) {
11076                selector =  prefix + groups[i];
11077                queries.push([selector, node]);
11078            }
11079        }
11080
11081        return queries;
11082    },
11083
11084    _nativeQuery: function(selector, root, one) {
11085        if (
11086            (Y.UA.webkit || Y.UA.opera) &&          // webkit (chrome, safari) and Opera
11087            selector.indexOf(':checked') > -1 &&    // fail to pick up "selected"  with ":checked"
11088            (Y.Selector.pseudos && Y.Selector.pseudos.checked)
11089        ) {
11090            return Y.Selector.query(selector, root, one, true); // redo with skipNative true to try brute query
11091        }
11092        try {
11093            return root['querySelector' + (one ? '' : 'All')](selector);
11094        } catch(e) { // fallback to brute if available
11095            return Y.Selector.query(selector, root, one, true); // redo with skipNative true
11096        }
11097    },
11098
11099    /**
11100     * Filters out nodes that do not match the given CSS selector.
11101     * @method filter
11102     *
11103     * @param {HTMLElement[]} nodes An array of nodes.
11104     * @param {String} selector A CSS selector to test each node against.
11105     * @return {HTMLElement[]} The nodes that matched the given CSS selector.
11106     * @static
11107     */
11108    filter: function(nodes, selector) {
11109        var ret = [],
11110            i, node;
11111
11112        if (nodes && selector) {
11113            for (i = 0; (node = nodes[i++]);) {
11114                if (Y.Selector.test(node, selector)) {
11115                    ret[ret.length] = node;
11116                }
11117            }
11118        } else {
11119        }
11120
11121        return ret;
11122    },
11123
11124    /**
11125     * Determines whether or not the given node matches the given CSS selector.
11126     * @method test
11127     *
11128     * @param {HTMLElement} node A node to test.
11129     * @param {String} selector A CSS selector to test the node against.
11130     * @param {HTMLElement} root optional A node to start the query from. Defaults to the parent document of the node.
11131     * @return {Boolean} Whether or not the given node matched the given CSS selector.
11132     * @static
11133     */
11134    test: function(node, selector, root) {
11135        var defaultId,
11136            ret = false,
11137            useFrag = false,
11138            groups,
11139            parent,
11140            item,
11141            items,
11142            frag,
11143            id,
11144            i, j, group;
11145
11146        if (node && node.tagName) { // only test HTMLElements
11147
11148            if (typeof selector == 'function') { // test with function
11149                ret = selector.call(node, node);
11150            } else { // test with query
11151                // we need a root if off-doc
11152                groups = selector.split(',');
11153                if (!root && !Y.DOM.inDoc(node)) {
11154                    parent = node.parentNode;
11155                    if (parent) {
11156                        root = parent;
11157                    } else { // only use frag when no parent to query
11158                        frag = node[OWNER_DOCUMENT].createDocumentFragment();
11159                        frag.appendChild(node);
11160                        root = frag;
11161                        useFrag = true;
11162                    }
11163                }
11164                root = root || node[OWNER_DOCUMENT];
11165
11166                id = Y.Selector._escapeId(Y.DOM.getId(node));
11167                if (!id) {
11168                    defaultId = true;
11169                    id = Y.guid();
11170                    Y.DOM.setId(node, id);
11171                }
11172
11173                for (i = 0; (group = groups[i++]);) { // TODO: off-dom test
11174                    group += '[id="' + id + '"]';
11175                    items = Y.Selector.query(group, root);
11176
11177                    for (j = 0; item = items[j++];) {
11178                        if (item === node) {
11179                            ret = true;
11180                            break;
11181                        }
11182                    }
11183                    if (ret) {
11184                        break;
11185                    }
11186                }
11187
11188                if (useFrag) { // cleanup
11189                    frag.removeChild(node);
11190                }
11191
11192                if (defaultId) {
11193                    node.removeAttribute('id');
11194                }
11195            };
11196        }
11197
11198        return ret;
11199    },
11200
11201    /**
11202     * A convenience method to emulate Y.Node's aNode.ancestor(selector).
11203     * @method ancestor
11204     *
11205     * @param {HTMLElement} node A node to start the query from.
11206     * @param {String} selector A CSS selector to test the node against.
11207     * @param {Boolean} testSelf optional Whether or not to include the node in the scan.
11208     * @return {HTMLElement} The ancestor node matching the selector, or null.
11209     * @static
11210     */
11211    ancestor: function (node, selector, testSelf) {
11212        return Y.DOM.ancestor(node, function(n) {
11213            return Y.Selector.test(n, selector);
11214        }, testSelf);
11215    },
11216
11217    _parse: function(name, selector) {
11218        return selector.match(Y.Selector._types[name].re);
11219    },
11220
11221    _replace: function(name, selector) {
11222        var o = Y.Selector._types[name];
11223        return selector.replace(o.re, o.token);
11224    },
11225
11226    _restore: function(name, selector, items) {
11227        if (items) {
11228            var token = Y.Selector._types[name].token,
11229                i, len;
11230            for (i = 0, len = items.length; i < len; ++i) {
11231                selector = selector.replace(token, items[i]);
11232            }
11233        }
11234        return selector;
11235    }
11236};
11237
11238Y.mix(Y.Selector, Selector, true);
11239
11240})(Y);
11241
11242
11243}, 'patched-v3.18.3', {"requires": ["dom-base"]});
11244
11245YUI.add('selector', function (Y, NAME) {
11246
11247
11248
11249}, 'patched-v3.18.3', {"requires": ["selector-native"]});
11250
11251YUI.add('widget-base', function (Y, NAME) {
11252
11253/**
11254 * Provides the base Widget class, with HTML Parser support
11255 *
11256 * @module widget
11257 * @main widget
11258 */
11259
11260/**
11261 * Provides the base Widget class
11262 *
11263 * @module widget
11264 * @submodule widget-base
11265 */
11266var L = Y.Lang,
11267    Node = Y.Node,
11268
11269    ClassNameManager = Y.ClassNameManager,
11270
11271    _getClassName = ClassNameManager.getClassName,
11272    _getWidgetClassName,
11273
11274    _toInitialCap = Y.cached(function(str) {
11275        return str.substring(0, 1).toUpperCase() + str.substring(1);
11276    }),
11277
11278    // K-Weight, IE GC optimizations
11279    CONTENT = "content",
11280    VISIBLE = "visible",
11281    HIDDEN = "hidden",
11282    DISABLED = "disabled",
11283    FOCUSED = "focused",
11284    WIDTH = "width",
11285    HEIGHT = "height",
11286    BOUNDING_BOX = "boundingBox",
11287    CONTENT_BOX = "contentBox",
11288    PARENT_NODE = "parentNode",
11289    OWNER_DOCUMENT = "ownerDocument",
11290    AUTO = "auto",
11291    SRC_NODE = "srcNode",
11292    BODY = "body",
11293    TAB_INDEX = "tabIndex",
11294    ID = "id",
11295    RENDER = "render",
11296    RENDERED = "rendered",
11297    DESTROYED = "destroyed",
11298    STRINGS = "strings",
11299    DIV = "<div></div>",
11300    CHANGE = "Change",
11301    LOADING = "loading",
11302
11303    _UISET = "_uiSet",
11304
11305    EMPTY_STR = "",
11306    EMPTY_FN = function() {},
11307
11308    TRUE = true,
11309    FALSE = false,
11310
11311    UI,
11312    ATTRS = {},
11313    UI_ATTRS = [VISIBLE, DISABLED, HEIGHT, WIDTH, FOCUSED, TAB_INDEX],
11314
11315    WEBKIT = Y.UA.webkit,
11316
11317    // Widget nodeid-to-instance map.
11318    _instances = {};
11319
11320/**
11321 * A base class for widgets, providing:
11322 * <ul>
11323 *    <li>The render lifecycle method, in addition to the init and destroy
11324 *        lifecycle methods provide by Base</li>
11325 *    <li>Abstract methods to support consistent MVC structure across
11326 *        widgets: renderer, renderUI, bindUI, syncUI</li>
11327 *    <li>Support for common widget attributes, such as boundingBox, contentBox, visible,
11328 *        disabled, focused, strings</li>
11329 * </ul>
11330 *
11331 * @param config {Object} Object literal specifying widget configuration properties.
11332 *
11333 * @class Widget
11334 * @constructor
11335 * @extends Base
11336 */
11337function Widget(config) {
11338
11339    // kweight
11340    var widget = this,
11341        parentNode,
11342        render,
11343        constructor = widget.constructor;
11344
11345    widget._strs = {};
11346    widget._cssPrefix = constructor.CSS_PREFIX || _getClassName(constructor.NAME.toLowerCase());
11347
11348    // We need a config for HTML_PARSER to work.
11349    config = config || {};
11350
11351    Widget.superclass.constructor.call(widget, config);
11352
11353    render = widget.get(RENDER);
11354
11355    if (render) {
11356        // Render could be a node or boolean
11357        if (render !== TRUE) {
11358            parentNode = render;
11359        }
11360        widget.render(parentNode);
11361    }
11362}
11363
11364/**
11365 * Static property provides a string to identify the class.
11366 * <p>
11367 * Currently used to apply class identifiers to the bounding box
11368 * and to classify events fired by the widget.
11369 * </p>
11370 *
11371 * @property NAME
11372 * @type String
11373 * @static
11374 */
11375Widget.NAME = "widget";
11376
11377/**
11378 * Constant used to identify state changes originating from
11379 * the DOM (as opposed to the JavaScript model).
11380 *
11381 * @property UI_SRC
11382 * @type String
11383 * @static
11384 * @final
11385 */
11386UI = Widget.UI_SRC = "ui";
11387
11388/**
11389 * Static property used to define the default attribute
11390 * configuration for the Widget.
11391 *
11392 * @property ATTRS
11393 * @type Object
11394 * @static
11395 */
11396Widget.ATTRS = ATTRS;
11397
11398// Trying to optimize kweight by setting up attrs this way saves about 0.4K min'd
11399
11400/**
11401 * @attribute id
11402 * @writeOnce
11403 * @default Generated using guid()
11404 * @type String
11405 */
11406
11407ATTRS[ID] = {
11408    valueFn: "_guid",
11409    writeOnce: TRUE
11410};
11411
11412/**
11413 * Flag indicating whether or not this Widget
11414 * has been through the render lifecycle phase.
11415 *
11416 * @attribute rendered
11417 * @readOnly
11418 * @default false
11419 * @type boolean
11420 */
11421ATTRS[RENDERED] = {
11422    value:FALSE,
11423    readOnly: TRUE
11424};
11425
11426/**
11427 * @attribute boundingBox
11428 * @description The outermost DOM node for the Widget, used for sizing and positioning
11429 * of a Widget as well as a containing element for any decorator elements used
11430 * for skinning.
11431 * @type String | Node
11432 * @writeOnce
11433 */
11434ATTRS[BOUNDING_BOX] = {
11435    valueFn:"_defaultBB",
11436    setter: "_setBB",
11437    writeOnce: TRUE
11438};
11439
11440/**
11441 * @attribute contentBox
11442 * @description A DOM node that is a direct descendant of a Widget's bounding box that
11443 * houses its content.
11444 * @type String | Node
11445 * @writeOnce
11446 */
11447ATTRS[CONTENT_BOX] = {
11448    valueFn:"_defaultCB",
11449    setter: "_setCB",
11450    writeOnce: TRUE
11451};
11452
11453/**
11454 * @attribute tabIndex
11455 * @description Number (between -32767 to 32767) indicating the widget's
11456 * position in the default tab flow.  The value is used to set the
11457 * "tabIndex" attribute on the widget's bounding box.  Negative values allow
11458 * the widget to receive DOM focus programmatically (by calling the focus
11459 * method), while being removed from the default tab flow.  A value of
11460 * null removes the "tabIndex" attribute from the widget's bounding box.
11461 * @type Number
11462 * @default null
11463 */
11464ATTRS[TAB_INDEX] = {
11465    value: null,
11466    validator: "_validTabIndex"
11467};
11468
11469/**
11470 * @attribute focused
11471 * @description Boolean indicating if the Widget, or one of its descendants,
11472 * has focus.
11473 * @readOnly
11474 * @default false
11475 * @type boolean
11476 */
11477ATTRS[FOCUSED] = {
11478    value: FALSE,
11479    readOnly:TRUE
11480};
11481
11482/**
11483 * @attribute disabled
11484 * @description Boolean indicating if the Widget should be disabled. The disabled implementation
11485 * is left to the specific classes extending widget.
11486 * @default false
11487 * @type boolean
11488 */
11489ATTRS[DISABLED] = {
11490    value: FALSE
11491};
11492
11493/**
11494 * @attribute visible
11495 * @description Boolean indicating whether or not the Widget is visible.
11496 * @default TRUE
11497 * @type boolean
11498 */
11499ATTRS[VISIBLE] = {
11500    value: TRUE
11501};
11502
11503/**
11504 * @attribute height
11505 * @description String with units, or number, representing the height of the Widget. If a number is provided,
11506 * the default unit, defined by the Widgets DEF_UNIT, property is used.
11507 * @default EMPTY_STR
11508 * @type {String | Number}
11509 */
11510ATTRS[HEIGHT] = {
11511    value: EMPTY_STR
11512};
11513
11514/**
11515 * @attribute width
11516 * @description String with units, or number, representing the width of the Widget. If a number is provided,
11517 * the default unit, defined by the Widgets DEF_UNIT, property is used.
11518 * @default EMPTY_STR
11519 * @type {String | Number}
11520 */
11521ATTRS[WIDTH] = {
11522    value: EMPTY_STR
11523};
11524
11525/**
11526 * @attribute strings
11527 * @description Collection of strings used to label elements of the Widget's UI.
11528 * @default null
11529 * @type Object
11530 */
11531ATTRS[STRINGS] = {
11532    value: {},
11533    setter: "_strSetter",
11534    getter: "_strGetter"
11535};
11536
11537/**
11538 * Whether or not to render the widget automatically after init, and optionally, to which parent node.
11539 *
11540 * @attribute render
11541 * @type boolean | Node
11542 * @writeOnce
11543 */
11544ATTRS[RENDER] = {
11545    value:FALSE,
11546    writeOnce:TRUE
11547};
11548
11549/**
11550 * The css prefix which the static Widget.getClassName method should use when constructing class names
11551 *
11552 * @property CSS_PREFIX
11553 * @type String
11554 * @default Widget.NAME.toLowerCase()
11555 * @private
11556 * @static
11557 */
11558Widget.CSS_PREFIX = _getClassName(Widget.NAME.toLowerCase());
11559
11560/**
11561 * Generate a standard prefixed classname for the Widget, prefixed by the default prefix defined
11562 * by the <code>Y.config.classNamePrefix</code> attribute used by <code>ClassNameManager</code> and
11563 * <code>Widget.NAME.toLowerCase()</code> (e.g. "yui-widget-xxxxx-yyyyy", based on default values for
11564 * the prefix and widget class name).
11565 * <p>
11566 * The instance based version of this method can be used to generate standard prefixed classnames,
11567 * based on the instances NAME, as opposed to Widget.NAME. This method should be used when you
11568 * need to use a constant class name across different types instances.
11569 * </p>
11570 * @method getClassName
11571 * @param {String*}
11571 args* 0..n strings which should be concatenated, using the default separator defined by ClassNameManager, to create the class name
11572 */
11573Widget.getClassName = function() {
11574    // arguments needs to be array'fied to concat
11575    return _getClassName.apply(ClassNameManager, [Widget.CSS_PREFIX].concat(Y.Array(arguments), true));
11576};
11577
11578_getWidgetClassName = Widget.getClassName;
11579
11580/**
11581 * Returns the widget instance whose bounding box contains, or is, the given node.
11582 * <p>
11583 * In the case of nested widgets, the nearest bounding box ancestor is used to
11584 * return the widget instance.
11585 * </p>
11586 * @method getByNode
11587 * @static
11588 * @param node {Node | String} The node for which to return a Widget instance. If a selector
11589 * string is passed in, which selects more than one node, the first node found is used.
11590 * @return {Widget} Widget instance, or null if not found.
11591 */
11592Widget.getByNode = function(node) {
11593    var widget,
11594        widgetMarker = _getWidgetClassName();
11595
11596    node = Node.one(node);
11597    if (node) {
11598        node = node.ancestor("." + widgetMarker, true);
11599        if (node) {
11600            widget = _instances[Y.stamp(node, true)];
11601        }
11602    }
11603
11604    return widget || null;
11605};
11606
11607Y.extend(Widget, Y.Base, {
11608
11609    /**
11610     * Returns a class name prefixed with the the value of the
11611     * <code>YUI.config.classNamePrefix</code> attribute + the instances <code>NAME</code> property.
11612     * Uses <code>YUI.config.classNameDelimiter</code> attribute to delimit the provided strings.
11613     * e.g.
11614     * <code>
11615     * <pre>
11616     *    // returns "yui-slider-foo-bar", for a slider instance
11617     *    var scn = slider.getClassName('foo','bar');
11618     *
11619     *    // returns "yui-overlay-foo-bar", for an overlay instance
11620     *    var ocn = overlay.getClassName('foo','bar');
11621     * </pre>
11622     * </code>
11623     *
11624     * @method getClassName
11625     * @param {String} [classnames*] One or more classname bits to be joined and prefixed
11626     */
11627    getClassName: function () {
11628        return _getClassName.apply(ClassNameManager, [this._cssPrefix].concat(Y.Array(arguments), true));
11629    },
11630
11631    /**
11632     * Initializer lifecycle implementation for the Widget class. Registers the
11633     * widget instance, and runs through the Widget's HTML_PARSER definition.
11634     *
11635     * @method initializer
11636     * @protected
11637     * @param  config {Object} Configuration object literal for the widget
11638     */
11639    initializer: function(config) {
11640
11641        var bb = this.get(BOUNDING_BOX);
11642
11643        if (bb instanceof Node) {
11644            this._mapInstance(Y.stamp(bb));
11645        }
11646
11647        /**
11648         * Notification event, which widget implementations can fire, when
11649         * they change the content of the widget. This event has no default
11650         * behavior and cannot be prevented, so the "on" or "after"
11651         * moments are effectively equivalent (with on listeners being invoked before
11652         * after listeners).
11653         *
11654         * @event widget:contentUpdate
11655         * @preventable false
11656         * @param {EventFacade} e The Event Facade
11657         */
11658    },
11659
11660    /**
11661     * Utility method used to add an entry to the boundingBox id to instance map.
11662     *
11663     * This method can be used to populate the instance with lazily created boundingBox Node references.
11664     *
11665     * @method _mapInstance
11666     * @param {String} The boundingBox id
11667     * @protected
11668     */
11669    _mapInstance : function(id) {
11670        _instances[id] = this;
11671    },
11672
11673    /**
11674     * Destructor lifecycle implementation for the Widget class. Purges events attached
11675     * to the bounding box and content box, removes them from the DOM and removes
11676     * the Widget from the list of registered widgets.
11677     *
11678     * @method destructor
11679     * @protected
11680     */
11681    destructor: function() {
11682
11683        var boundingBox = this.get(BOUNDING_BOX),
11684            bbGuid;
11685
11686        if (boundingBox instanceof Node) {
11687            bbGuid = Y.stamp(boundingBox,true);
11688
11689            if (bbGuid in _instances) {
11690                delete _instances[bbGuid];
11691            }
11692
11693            this._destroyBox();
11694        }
11695    },
11696
11697    /**
11698     * <p>
11699     * Destroy lifecycle method. Fires the destroy
11700     * event, prior to invoking destructors for the
11701     * class hierarchy.
11702     *
11703     * Overrides Base's implementation, to support arguments to destroy
11704     * </p>
11705     * <p>
11706     * Subscribers to the destroy
11707     * event can invoke preventDefault on the event object, to prevent destruction
11708     * from proceeding.
11709     * </p>
11710     * @method destroy
11711     * @param destroyAllNodes {Boolean} If true, all nodes contained within the Widget are
11712     * removed and destroyed. Defaults to false due to potentially high run-time cost.
11713     * @return {Widget} A reference to this object
11714     * @chainable
11715     */
11716    destroy: function(destroyAllNodes) {
11717        this._destroyAllNodes = destroyAllNodes;
11718        return Widget.superclass.destroy.apply(this);
11719    },
11720
11721    /**
11722     * Removes and destroys the widgets rendered boundingBox, contentBox,
11723     * and detaches bound UI events.
11724     *
11725     * @method _destroyBox
11726     * @protected
11727     */
11728    _destroyBox : function() {
11729
11730        var boundingBox = this.get(BOUNDING_BOX),
11731            contentBox = this.get(CONTENT_BOX),
11732            deep = this._destroyAllNodes,
11733            same;
11734
11735        same = boundingBox && boundingBox.compareTo(contentBox);
11736
11737        if (this.UI_EVENTS) {
11738            this._destroyUIEvents();
11739        }
11740
11741        this._unbindUI(boundingBox);
11742
11743        if (contentBox) {
11744            if (deep) {
11745                contentBox.empty();
11746            }
11747            contentBox.remove(TRUE);
11748        }
11749
11750        if (!same) {
11751            if (deep) {
11752                boundingBox.empty();
11753            }
11754            boundingBox.remove(TRUE);
11755        }
11756    },
11757
11758    /**
11759     * Establishes the initial DOM for the widget. Invoking this
11760     * method will lead to the creating of all DOM elements for
11761     * the widget (or the manipulation of existing DOM elements
11762     * for the progressive enhancement use case).
11763     * <p>
11764     * This method should only be invoked once for an initialized
11765     * widget.
11766     * </p>
11767     * <p>
11768     * It delegates to the widget specific renderer method to do
11769     * the actual work.
11770     * </p>
11771     *
11772     * @method render
11773     * @chainable
11774     * @final
11775     * @param  parentNode {Object | String} Optional. The Node under which the
11776     * Widget is to be rendered. This can be a Node instance or a CSS selector string.
11777     * <p>
11778     * If the selector string returns more than one Node, the first node will be used
11779     * as the parentNode. NOTE: This argument is required if both the boundingBox and contentBox
11780     * are not currently in the document. If it's not provided, the Widget will be rendered
11781     * to the body of the current document in this case.
11782     * </p>
11783     */
11784    render: function(parentNode) {
11785
11786        if (!this.get(DESTROYED) && !this.get(RENDERED)) {
11787             /**
11788              * Lifecycle event for the render phase, fired prior to rendering the UI
11789              * for the widget (prior to invoking the widget's renderer method).
11790              * <p>
11791              * Subscribers to the "on" moment of this event, will be notified
11792              * before the widget is rendered.
11793              * </p>
11794              * <p>
11795              * Subscribers to the "after" moment of this event, will be notified
11796              * after rendering is complete.
11797              * </p>
11798              *
11799              * @event render
11800              * @preventable _defRenderFn
11801              * @param {EventFacade} e The Event Facade
11802              */
11803            this.publish(RENDER, {
11804                queuable:FALSE,
11805                fireOnce:TRUE,
11806                defaultTargetOnly:TRUE,
11807                defaultFn: this._defRenderFn
11808            });
11809
11810            this.fire(RENDER, {parentNode: (parentNode) ? Node.one(parentNode) : null});
11811        }
11812        return this;
11813    },
11814
11815    /**
11816     * Default render handler
11817     *
11818     * @method _defRenderFn
11819     * @protected
11820     * @param {EventFacade} e The Event object
11821     * @param {Node} parentNode The parent node to render to, if passed in to the <code>render</code> method
11822     */
11823    _defRenderFn : function(e) {
11824        this._parentNode = e.parentNode;
11825
11826        this.renderer();
11827        this._set(RENDERED, TRUE);
11828
11829        this._removeLoadingClassNames();
11830    },
11831
11832    /**
11833     * Creates DOM (or manipulates DOM for progressive enhancement)
11834     * This method is invoked by render() and is not chained
11835     * automatically for the class hierarchy (unlike initializer, destructor)
11836     * so it should be chained manually for subclasses if required.
11837     *
11838     * @method renderer
11839     * @protected
11840     */
11841    renderer: function() {
11842        // kweight
11843        var widget = this;
11844
11845        widget._renderUI();
11846        widget.renderUI();
11847
11848        widget._bindUI();
11849        widget.bindUI();
11850
11851        widget._syncUI();
11852        widget.syncUI();
11853    },
11854
11855    /**
11856     * Configures/Sets up listeners to bind Widget State to UI/DOM
11857     *
11858     * This method is not called by framework and is not chained
11859     * automatically for the class hierarchy.
11860     *
11861     * @method bindUI
11862     * @protected
11863     */
11864    bindUI: EMPTY_FN,
11865
11866    /**
11867     * Adds nodes to the DOM
11868     *
11869     * This method is not called by framework and is not chained
11870     * automatically for the class hierarchy.
11871     *
11872     * @method renderUI
11873     * @protected
11874     */
11875    renderUI: EMPTY_FN,
11876
11877    /**
11878     * Refreshes the rendered UI, based on Widget State
11879     *
11880     * This method is not called by framework and is not chained
11881     * automatically for the class hierarchy.
11882     *
11883     * @method syncUI
11884     * @protected
11885     *
11886     */
11887    syncUI: EMPTY_FN,
11888
11889    /**
11890     * @method hide
11891     * @description Hides the Widget by setting the "visible" attribute to "false".
11892     * @chainable
11893     */
11894    hide: function() {
11895        return this.set(VISIBLE, FALSE);
11896    },
11897
11898    /**
11899     * @method show
11900     * @description Shows the Widget by setting the "visible" attribute to "true".
11901     * @chainable
11902     */
11903    show: function() {
11904        return this.set(VISIBLE, TRUE);
11905    },
11906
11907    /**
11908     * @method focus
11909     * @description Causes the Widget to receive the focus by setting the "focused"
11910     * attribute to "true".
11911     * @chainable
11912     */
11913    focus: function () {
11914        return this._set(FOCUSED, TRUE);
11915    },
11916
11917    /**
11918     * @method blur
11919     * @description Causes the Widget to lose focus by setting the "focused" attribute
11920     * to "false"
11921     * @chainable
11922     */
11923    blur: function () {
11924        return this._set(FOCUSED, FALSE);
11925    },
11926
11927    /**
11928     * @method enable
11929     * @description Set the Widget's "disabled" attribute to "false".
11930     * @chainable
11931     */
11932    enable: function() {
11933        return this.set(DISABLED, FALSE);
11934    },
11935
11936    /**
11937     * @method disable
11938     * @description Set the Widget's "disabled" attribute to "true".
11939     * @chainable
11940     */
11941    disable: function() {
11942        return this.set(DISABLED, TRUE);
11943    },
11944
11945    /**
11946     * @method _uiSizeCB
11947     * @protected
11948     * @param {boolean} expand
11949     */
11950    _uiSizeCB : function(expand) {
11951        this.get(CONTENT_BOX).toggleClass(_getWidgetClassName(CONTENT, "expanded"), expand);
11952    },
11953
11954    /**
11955     * Helper method to collect the boundingBox and contentBox and append to the provided parentNode, if not
11956     * already a child. The owner document of the boundingBox, or the owner document of the contentBox will be used
11957     * as the document into which the Widget is rendered if a parentNode is node is not provided. If both the boundingBox and
11958     * the contentBox are not currently in the document, and no parentNode is provided, the widget will be rendered
11959     * to the current document's body.
11960     *
11961     * @method _renderBox
11962     * @private
11963     * @param {Node} parentNode The parentNode to render the widget to. If not provided, and both the boundingBox and
11964     * the contentBox are not currently in the document, the widget will be rendered to the current document's body.
11965     */
11966    _renderBox: function(parentNode) {
11967
11968        // TODO: Performance Optimization [ More effective algo to reduce Node refs, compares, replaces? ]
11969
11970        var widget = this, // kweight
11971            contentBox = widget.get(CONTENT_BOX),
11972            boundingBox = widget.get(BOUNDING_BOX),
11973            srcNode = widget.get(SRC_NODE),
11974            defParentNode = widget.DEF_PARENT_NODE,
11975
11976            doc = (srcNode && srcNode.get(OWNER_DOCUMENT)) || boundingBox.get(OWNER_DOCUMENT) || contentBox.get(OWNER_DOCUMENT);
11977
11978        // If srcNode (assume it's always in doc), have contentBox take its place (widget render responsible for re-use of srcNode contents)
11979        if (srcNode && !srcNode.compareTo(contentBox) && !contentBox.inDoc(doc)) {
11980            srcNode.replace(contentBox);
11981        }
11982
11983        if (!boundingBox.compareTo(contentBox.get(PARENT_NODE)) && !boundingBox.compareTo(contentBox)) {
11984            // If contentBox box is already in the document, have boundingBox box take it's place
11985            if (contentBox.inDoc(doc)) {
11986                contentBox.replace(boundingBox);
11987            }
11988            boundingBox.appendChild(contentBox);
11989        }
11990
11991        parentNode = parentNode || (defParentNode && Node.one(defParentNode));
11992
11993        if (parentNode) {
11994            parentNode.appendChild(boundingBox);
11995        } else if (!boundingBox.inDoc(doc)) {
11996            Node.one(BODY).insert(boundingBox, 0);
11997        }
11998    },
11999
12000    /**
12001     * Setter for the boundingBox attribute
12002     *
12003     * @method _setBB
12004     * @private
12005     * @param {Node|String} node
12006     * @return Node
12007     */
12008    _setBB: function(node) {
12009        return this._setBox(this.get(ID), node, this.BOUNDING_TEMPLATE, true);
12010    },
12011
12012    /**
12013     * Setter for the contentBox attribute
12014     *
12015     * @method _setCB
12016     * @private
12017     * @param {Node|String}
12017 node
12018     * @return Node
12019     */
12020    _setCB: function(node) {
12021        return (this.CONTENT_TEMPLATE === null) ? this.get(BOUNDING_BOX) : this._setBox(null, node, this.CONTENT_TEMPLATE, false);
12022    },
12023
12024    /**
12025     * Returns the default value for the boundingBox attribute.
12026     *
12027     * For the Widget class, this will most commonly be null (resulting in a new
12028     * boundingBox node instance being created), unless a srcNode was provided
12029     * and CONTENT_TEMPLATE is null, in which case it will be srcNode.
12030     * This behavior was introduced in patched-v3.18.3 to accomodate single-box widgets
12031     * whose BB & CB both point to srcNode (e.g. Y.Button).
12032     *
12033     * @method _defaultBB
12034     * @protected
12035     */
12036    _defaultBB : function() {
12037        var node = this.get(SRC_NODE),
12038            nullCT = (this.CONTENT_TEMPLATE === null);
12039
12040        return ((node && nullCT) ? node : null);
12041    },
12042
12043    /**
12044     * Returns the default value for the contentBox attribute.
12045     *
12046     * For the Widget class, this will be the srcNode if provided, otherwise null (resulting in
12047     * a new contentBox node instance being created)
12048     *
12049     * @method _defaultCB
12050     * @protected
12051     */
12052    _defaultCB : function(node) {
12053        return this.get(SRC_NODE) || null;
12054    },
12055
12056    /**
12057     * Helper method to set the bounding/content box, or create it from
12058     * the provided template if not found.
12059     *
12060     * @method _setBox
12061     * @private
12062     *
12063     * @param {String} id The node's id attribute
12064     * @param {Node|String} node The node reference
12065     * @param {String} template HTML string template for the node
12066     * @param {boolean} isBounding true if this is the boundingBox, false if it's the contentBox
12067     * @return {Node} The node
12068     */
12069    _setBox : function(id, node, template, isBounding) {
12070
12071        node = Node.one(node);
12072
12073        if (!node) {
12074            node = Node.create(template);
12075
12076            if (isBounding) {
12077                this._bbFromTemplate = true;
12078            } else {
12079                this._cbFromTemplate = true;
12080            }
12081        }
12082
12083        if (!node.get(ID)) {
12084            node.set(ID, id || Y.guid());
12085        }
12086
12087        return node;
12088    },
12089
12090    /**
12091     * Initializes the UI state for the Widget's bounding/content boxes.
12092     *
12093     * @method _renderUI
12094     * @protected
12095     */
12096    _renderUI: function() {
12097        this._renderBoxClassNames();
12098        this._renderBox(this._parentNode);
12099    },
12100
12101    /**
12102     * Applies standard class names to the boundingBox and contentBox
12103     *
12104     * @method _renderBoxClassNames
12105     * @protected
12106     */
12107    _renderBoxClassNames : function() {
12108        var classes = this._getClasses(),
12109            cl,
12110            boundingBox = this.get(BOUNDING_BOX),
12111            i;
12112
12113        boundingBox.addClass(_getWidgetClassName());
12114
12115        // Start from Widget Sub Class
12116        for (i = classes.length-3; i >= 0; i--) {
12117            cl = classes[i];
12118            boundingBox.addClass(cl.CSS_PREFIX || _getClassName(cl.NAME.toLowerCase()));
12119        }
12120
12121        // Use instance based name for content box
12122        this.get(CONTENT_BOX).addClass(this.getClassName(CONTENT));
12123    },
12124
12125    /**
12126     * Removes class names representative of the widget's loading state from
12127     * the boundingBox.
12128     *
12129     * @method _removeLoadingClassNames
12130     * @protected
12131     */
12132    _removeLoadingClassNames: function () {
12133
12134        var boundingBox = this.get(BOUNDING_BOX),
12135            contentBox = this.get(CONTENT_BOX),
12136            instClass = this.getClassName(LOADING),
12137            widgetClass = _getWidgetClassName(LOADING);
12138
12139        boundingBox.removeClass(widgetClass)
12140                   .removeClass(instClass);
12141
12142        contentBox.removeClass(widgetClass)
12143                  .removeClass(instClass);
12144    },
12145
12146    /**
12147     * Sets up DOM and CustomEvent listeners for the widget.
12148     *
12149     * @method _bindUI
12150     * @protected
12151     */
12152    _bindUI: function() {
12153        this._bindAttrUI(this._UI_ATTRS.BIND);
12154        this._bindDOM();
12155    },
12156
12157    /**
12158     * @method _unbindUI
12159     * @protected
12160     */
12161    _unbindUI : function(boundingBox) {
12162        this._unbindDOM(boundingBox);
12163    },
12164
12165    /**
12166     * Sets up DOM listeners, on elements rendered by the widget.
12167     *
12168     * @method _bindDOM
12169     * @protected
12170     */
12171    _bindDOM : function() {
12172        var oDocument = this.get(BOUNDING_BOX).get(OWNER_DOCUMENT),
12173            focusHandle = Widget._hDocFocus;
12174
12175        // Shared listener across all Widgets.
12176        if (!focusHandle) {
12177            focusHandle = Widget._hDocFocus = oDocument.on("focus", this._onDocFocus, this);
12178            focusHandle.listeners = {
12179                count: 0
12180            };
12181        }
12182
12183        focusHandle.listeners[Y.stamp(this, true)] = true;
12184        focusHandle.listeners.count++;
12185
12186        //	Fix for Webkit:
12187        //	Document doesn't receive focus in Webkit when the user mouses
12188        //	down on it, so the "focused" attribute won't get set to the
12189        //	correct value. Keeping this instance based for now, potential better performance.
12190        //  Otherwise we'll end up looking up widgets from the DOM on every mousedown.
12191        if (WEBKIT){
12192            this._hDocMouseDown = oDocument.on("mousedown", this._onDocMouseDown, this);
12193        }
12194    },
12195
12196    /**
12197     * @method _unbindDOM
12198     * @protected
12199     */
12200    _unbindDOM : function(boundingBox) {
12201
12202        var focusHandle = Widget._hDocFocus,
12203            yuid = Y.stamp(this, true),
12204            focusListeners,
12205            mouseHandle = this._hDocMouseDown;
12206
12207        if (focusHandle) {
12208
12209            focusListeners = focusHandle.listeners;
12210
12211            if (focusListeners[yuid]) {
12212                delete focusListeners[yuid];
12213                focusListeners.count--;
12214            }
12215
12216            if (focusListeners.count === 0) {
12217                focusHandle.detach();
12218                Widget._hDocFocus = null;
12219            }
12220        }
12221
12222        if (WEBKIT && mouseHandle) {
12223            mouseHandle.detach();
12224        }
12225    },
12226
12227    /**
12228     * Updates the widget UI to reflect the attribute state.
12229     *
12230     * @method _syncUI
12231     * @protected
12232     */
12233    _syncUI: function() {
12234        this._syncAttrUI(this._UI_ATTRS.SYNC);
12235    },
12236
12237    /**
12238     * Sets the height on the widget's bounding box element
12239     *
12240     * @method _uiSetHeight
12241     * @protected
12242     * @param {String | Number} val
12243     */
12244    _uiSetHeight: function(val) {
12245        this._uiSetDim(HEIGHT, val);
12246        this._uiSizeCB((val !== EMPTY_STR && val !== AUTO));
12247    },
12248
12249    /**
12250     * Sets the width on the widget's bounding box element
12251     *
12252     * @method _uiSetWidth
12253     * @protected
12254     * @param {String | Number} val
12255     */
12256    _uiSetWidth: function(val) {
12257        this._uiSetDim(WIDTH, val);
12258    },
12259
12260    /**
12261     * @method _uiSetDim
12262     * @private
12263     * @param {String} dim The dimension - "width" or "height"
12264     * @param {Number | String} val The value to set
12265     */
12266    _uiSetDim: function(dimension, val) {
12267        this.get(BOUNDING_BOX).setStyle(dimension, L.isNumber(val) ? val + this.DEF_UNIT : val);
12268    },
12269
12270    /**
12271     * Sets the visible state for the UI
12272     *
12273     * @method _uiSetVisible
12274     * @protected
12275     * @param {boolean} val
12276     */
12277    _uiSetVisible: function(val) {
12278        this.get(BOUNDING_BOX).toggleClass(this.getClassName(HIDDEN), !val);
12279    },
12280
12281    /**
12282     * Sets the disabled state for the UI
12283     *
12284     * @method _uiSetDisabled
12285     * @protected
12286     * @param {boolean} val
12287     */
12288    _uiSetDisabled: function(val) {
12289        this.get(BOUNDING_BOX).toggleClass(this.getClassName(DISABLED), val);
12290    },
12291
12292    /**
12293     * Sets the focused state for the UI
12294     *
12295     * @method _uiSetFocused
12296     * @protected
12297     * @param {boolean} val
12298     * @param {string} src String representing the source that triggered an update to
12299     * the UI.
12300     */
12301    _uiSetFocused: function(val, src) {
12302         var boundingBox = this.get(BOUNDING_BOX);
12303         boundingBox.toggleClass(this.getClassName(FOCUSED), val);
12304
12305         if (src !== UI) {
12306            if (val) {
12307                boundingBox.focus();
12308            } else {
12309                boundingBox.blur();
12310            }
12311         }
12312    },
12313
12314    /**
12315     * Set the tabIndex on the widget's rendered UI
12316     *
12317     * @method _uiSetTabIndex
12318     * @protected
12319     * @param Number
12320     */
12321    _uiSetTabIndex: function(index) {
12322        var boundingBox = this.get(BOUNDING_BOX);
12323
12324        if (L.isNumber(index)) {
12325            boundingBox.set(TAB_INDEX, index);
12326        } else {
12327            boundingBox.removeAttribute(TAB_INDEX);
12328        }
12329    },
12330
12331    /**
12332     * @method _onDocMouseDown
12333     * @description "mousedown" event handler for the owner document of the
12334     * widget's bounding box.
12335     * @protected
12336     * @param {EventFacade} evt The event facade for the DOM focus event
12337     */
12338    _onDocMouseDown: function (evt) {
12339        if (this._domFocus) {
12340            this._onDocFocus(evt);
12341        }
12342    },
12343
12344    /**
12345     * DOM focus event handler, used to sync the state of the Widget with the DOM
12346     *
12347     * @method _onDocFocus
12348     * @protected
12349     * @param {EventFacade} evt The event facade for the DOM focus event
12350     */
12351    _onDocFocus: function (evt) {
12352        var widget = Widget.getByNode(evt.target),
12353            activeWidget = Widget._active;
12354
12355        if (activeWidget && (activeWidget !== widget)) {
12356            activeWidget._domFocus = false;
12357            activeWidget._set(FOCUSED, false, {src:UI});
12358
12359            Widget._active = null;
12360        }
12361
12362        if (widget) {
12363            widget._domFocus = true;
12364            widget._set(FOCUSED, true, {src:UI});
12365
12366            Widget._active = widget;
12367        }
12368    },
12369
12370    /**
12371     * Generic toString implementation for all widgets.
12372     *
12373     * @method toString
12374     * @return {String} The default string value for the widget [ displays the NAME of the instance, and the unique id ]
12375     */
12376    toString: function() {
12377        // Using deprecated name prop for kweight squeeze.
12378        return this.name + "[" + this.get(ID) + "]";
12379    },
12380
12381    /**
12382     * Default unit to use for dimension values
12383     *
12384     * @property DEF_UNIT
12385     * @type String
12386     */
12387    DEF_UNIT : "px",
12388
12389    /**
12390     * Default node to render the bounding box to. If not set,
12391     * will default to the current document body.
12392     *
12393     * @property DEF_PARENT_NODE
12394     * @type String | Node
12395     */
12396    DEF_PARENT_NODE : null,
12397
12398    /**
12399     * Property defining the markup template for content box. If your Widget doesn't
12400     * need the dual boundingBox/contentBox structure, set CONTENT_TEMPLATE to null,
12401     * and contentBox and boundingBox will both point to the same Node.
12402     *
12403     * @property CONTENT_TEMPLATE
12404     * @type String
12405     */
12406    CONTENT_TEMPLATE : DIV,
12407
12408    /**
12409     * Property defining the markup template for bounding box.
12410     *
12411     * @property BOUNDING_TEMPLATE
12412     * @type String
12413     */
12414    BOUNDING_TEMPLATE : DIV,
12415
12416    /**
12417     * @method _guid
12418     * @protected
12419     */
12420    _guid : function() {
12421        return Y.guid();
12422    },
12423
12424    /**
12425     * @method _validTabIndex
12426     * @protected
12427     * @param {Number} tabIndex
12428     */
12429    _validTabIndex : function (tabIndex) {
12430        return (L.isNumber(tabIndex) || L.isNull(tabIndex));
12431    },
12432
12433    /**
12434     * Binds after listeners for the list of attributes provided
12435     *
12436     * @method _bindAttrUI
12437     * @private
12438     * @param {Array} attrs
12439     */
12440    _bindAttrUI : function(attrs) {
12441        var i,
12442            l = attrs.length;
12443
12444        for (i = 0; i < l; i++) {
12445            this.after(attrs[i] + CHANGE, this._setAttrUI);
12446        }
12447    },
12448
12449    /**
12450     * Invokes the _uiSet&#61;ATTR NAME&#62; method for the list of attributes provided
12451     *
12452     * @method _syncAttrUI
12453     * @private
12454     * @param {Array} attrs
12455     */
12456    _syncAttrUI : function(attrs) {
12457        var i, l = attrs.length, attr;
12458        for (i = 0; i < l; i++) {
12459            attr = attrs[i];
12460            this[_UISET + _toInitialCap(attr)](this.get(attr));
12461        }
12462    },
12463
12464    /**
12465     * @method _setAttrUI
12466     * @private
12467     * @param {EventFacade} e
12468     */
12469    _setAttrUI : function(e) {
12470        if (e.target === this) {
12471            this[_UISET + _toInitialCap(e.attrName)](e.newVal, e.src);
12472        }
12473    },
12474
12475    /**
12476     * The default setter for the strings attribute. Merges partial sets
12477     * into the full string set, to allow users to partial sets of strings
12478     *
12479     * @method _strSetter
12480     * @protected
12481     * @param {Object} strings
12482     * @return {String} The full set of strings to set
12483     */
12484    _strSetter : function(strings) {
12485        return Y.merge(this.get(STRINGS), strings);
12486    },
12487
12488    /**
12489     * Helper method to get a specific string value
12490     *
12491     * @deprecated Used by deprecated WidgetLocale implementations.
12492     * @method getString
12493     * @param {String} key
12494     * @return {String} The string
12495     */
12496    getString : function(key) {
12497        return this.get(STRINGS)[key];
12498    },
12499
12500    /**
12501     * Helper method to get the complete set of strings for the widget
12502     *
12503     * @deprecated  Used by deprecated WidgetLocale implementations.
12504     * @method getStrings
12505     * @param {String} key
12506     * @return {String} The strings
12507     */
12508    getStrings : function() {
12509        return this.get(STRINGS);
12510    },
12511
12512    /**
12513     * The lists of UI attributes to bind and sync for widget's _bindUI and _syncUI implementations
12514     *
12515     * @property _UI_ATTRS
12516     * @type Object
12517     * @private
12518     */
12519    _UI_ATTRS : {
12520        BIND: UI_ATTRS,
12521        SYNC: UI_ATTRS
12522    }
12523});
12524
12525Y.Widget = Widget;
12526
12527
12528}, 'patched-v3.18.3', {
12529    "requires": [
12530        "attribute",
12531        "base-base",
12532        "base-pluginhost",
12533        "classnamemanager",
12534        "event-focus",
12535        "node-base",
12536        "node-style"
12537    ],
12538    "skinnable": true
12539});
12540
12541YUI.add('widget-htmlparser', function (Y, NAME) {
12542
12543/**
12544 * Adds HTML Parser support to the base Widget class
12545 *
12546 * @module widget
12547 * @submodule widget-htmlparser
12548 * @for Widget
12549 */
12550
12551var Widget = Y.Widget,
12552    Node = Y.Node,
12553    Lang = Y.Lang,
12554
12555    SRC_NODE = "srcNode",
12556    CONTENT_BOX = "contentBox";
12557
12558/**
12559 * Object hash, defining how attribute values are to be parsed from
12560 * markup contained in the widget's content box. e.g.:
12561 * <pre>
12562 *   {
12563 *       // Set single Node references using selector syntax
12564 *       // (selector is run through node.one)
12565 *       titleNode: "span.yui-title",
12566 *       // Set NodeList references using selector syntax
12567 *       // (array indicates selector is to be run through node.all)
12568 *       listNodes: ["li.yui-item"],
12569 *       // Set other attribute types, using a parse function.
12570 *       // Context is set to the widget instance.
12571 *       label: function(contentBox) {
12572 *           return contentBox.one("span.title").get("innerHTML");
12573 *       }
12574 *   }
12575 * </pre>
12576 *
12577 * @property HTML_PARSER
12578 * @type Object
12579 * @static
12580 */
12581Widget.HTML_PARSER = {};
12582
12583/**
12584 * The build configuration for the Widget class.
12585 * <p>
12586 * Defines the static fields which need to be aggregated,
12587 * when this class is used as the main class passed to
12588 * the <a href="Base.html#method_build">Base.build</a> method.
12589 * </p>
12590 * @property _buildCfg
12591 * @type Object
12592 * @static
12593 * @final
12594 * @private
12595 */
12596Widget._buildCfg = {
12597    aggregates : ["HTML_PARSER"]
12598};
12599
12600/**
12601 * The DOM node to parse for configuration values, passed to the Widget's HTML_PARSER definition
12602 *
12603 * @attribute srcNode
12604 * @type String | Node
12605 * @writeOnce
12606 */
12607Widget.ATTRS[SRC_NODE] = {
12608    value: null,
12609    setter: Node.one,
12610    getter: "_getSrcNode",
12611    writeOnce: true
12612};
12613
12614Y.mix(Widget.prototype, {
12615
12616    /**
12617     * @method _getSrcNode
12618     * @protected
12619     * @return {Node} The Node to apply HTML_PARSER to
12620     */
12621    _getSrcNode : function(val) {
12622        return val || this.get(CONTENT_BOX);
12623    },
12624
12625    /**
12626     * Implement the BaseCore _preAddAttrs method hook, to add
12627     * the srcNode and related attributes, so that HTML_PARSER
12628     * (which relies on `this.get("srcNode")`) can merge in it's
12629     * results before the rest of the attributes are added.
12630     *
12631     * @method _preAddAttrs
12632     * @protected
12633     *
12634     * @param attrs {Object} The full hash of statically defined ATTRS
12635     * attributes being added for this instance
12636     *
12637     * @param userVals {Object} The hash of user values passed to
12638     * the constructor
12639     *
12640     * @param lazy {boolean} Whether or not to add the attributes lazily
12641     */
12642    _preAddAttrs : function(attrs, userVals, lazy) {
12643
12644        var preAttrs = {
12645            id : attrs.id,
12646            boundingBox : attrs.boundingBox,
12647            contentBox : attrs.contentBox,
12648            srcNode : attrs.srcNode || Y.Object(Widget.ATTRS[SRC_NODE])
12649        };
12650
12651        this.addAttrs(preAttrs, userVals, lazy);
12652
12653        delete attrs.boundingBox;
12654        delete attrs.contentBox;
12655        delete attrs.srcNode;
12656        delete attrs.id;
12657
12658        if (this._applyParser) {
12659            this._applyParser(userVals);
12660        }
12661    },
12662
12663    /**
12664     * @method _applyParsedConfig
12665     * @protected
12666     * @return {Object} The merged configuration literal
12667     */
12668    _applyParsedConfig : function(node, cfg, parsedCfg) {
12669        return (parsedCfg) ? Y.mix(cfg, parsedCfg, false) : cfg;
12670    },
12671
12672    /**
12673     * Utility method used to apply the <code>HTML_PARSER</code> configuration for the
12674     * instance, to retrieve config data values.
12675     *
12676     * @method _applyParser
12677     * @protected
12678     * @param config {Object} User configuration object (will be populated with values from Node)
12679     */
12680    _applyParser : function(config) {
12681
12682        var widget = this,
12683            srcNode = this._getNodeToParse(),
12684            schema = widget._getHtmlParser(),
12685            parsedConfig,
12686            val;
12687
12688        if (schema && srcNode) {
12689            Y.Object.each(schema, function(v, k, o) {
12690                val = null;
12691
12692                if (Lang.isFunction(v)) {
12693                    val = v.call(widget, srcNode);
12694                } else {
12695                    if (Lang.isArray(v)) {
12696                        val = srcNode.all(v[0]);
12697                        if (val.isEmpty()) {
12698                            val = null;
12699                        }
12700                    } else {
12701                        val = srcNode.one(v);
12702                    }
12703                }
12704
12705                if (val !== null && val !== undefined) {
12706                    parsedConfig = parsedConfig || {};
12707                    parsedConfig[k] = val;
12708                }
12709            });
12710        }
12711        config = widget._applyParsedConfig(srcNode, config, parsedConfig);
12712    },
12713
12714    /**
12715     * Determines whether we have a node reference which we should try and parse.
12716     *
12717     * The current implementation does not parse nodes generated from CONTENT_TEMPLATE,
12718     * only explicitly set srcNode, or contentBox attributes.
12719     *
12720     * @method _getNodeToParse
12721     * @return {Node} The node reference to apply HTML_PARSER to.
12722     * @private
12723     */
12724    _getNodeToParse : function() {
12725        var srcNode = this.get("srcNode");
12726        return (!this._cbFromTemplate) ? srcNode : null;
12727    },
12728
12729    /**
12730     * Gets the HTML_PARSER definition for this instance, by merging HTML_PARSER
12731     * definitions across the class hierarchy.
12732     *
12733     * @private
12734     * @method _getHtmlParser
12735     * @return {Object} HTML_PARSER definition for this instance
12736     */
12737    _getHtmlParser : function() {
12738        // Removed caching for kweight. This is a private method
12739        // and only called once so don't need to cache HTML_PARSER
12740        var classes = this._getClasses(),
12741            parser = {},
12742            i, p;
12743
12744        for (i = classes.length - 1; i >= 0; i--) {
12745            p = classes[i].HTML_PARSER;
12746            if (p) {
12747                Y.mix(parser, p, true);
12748            }
12749        }
12750        return parser;
12751    }
12752});
12753
12754
12755}, 'patched-v3.18.3', {"requires": ["widget-base"]});
12756
12757YUI.add('widget-skin', function (Y, NAME) {
12758
12759/**
12760 * Provides skin related utlility methods.
12761 *
12762 * @module widget
12763 * @submodule widget-skin
12764 */
12765var BOUNDING_BOX = "boundingBox",
12766    CONTENT_BOX = "contentBox",
12767    SKIN = "skin",
12768    _getClassName = Y.ClassNameManager.getClassName;
12769
12770/**
12771 * Returns the name of the skin that's currently applied to the widget.
12772 *
12773 * Searches up the Widget's ancestor axis for, by default, a class
12774 * yui3-skin-(name), and returns the (name) portion. Otherwise, returns null.
12775 *
12776 * This is only really useful after the widget's DOM structure is in the
12777 * document, either by render or by progressive enhancement.
12778 *
12779 * @method getSkinName
12780 * @for Widget
12781 * @param {String} [skinPrefix] The prefix which the implementation uses for the skin
12782 * ("yui3-skin-" is the default).
12783 *
12784 * NOTE: skinPrefix will be used as part of a regular expression:
12785 *
12786 *     new RegExp('\\b' + skinPrefix + '(\\S+)')
12787 *
12788 * Although an unlikely use case, literal characters which may result in an invali
12788d
12789 * regular expression should be escaped.
12790 *
12791 * @return {String} The name of the skin, or null, if a matching skin class is not found.
12792 */
12793
12794Y.Widget.prototype.getSkinName = function (skinPrefix) {
12795
12796    var root = this.get( CONTENT_BOX ) || this.get( BOUNDING_BOX ),
12797        match,
12798        search;
12799
12800    skinPrefix = skinPrefix || _getClassName(SKIN, "");
12801
12802    search = new RegExp( '\\b' + skinPrefix + '(\\S+)' );
12803
12804    if ( root ) {
12805        root.ancestor( function ( node ) {
12806            match = node.get( 'className' ).match( search );
12807            return match;
12808        } );
12809    }
12810
12811    return ( match ) ? match[1] : null;
12812};
12813
12814
12815}, 'patched-v3.18.3', {"requires": ["widget-base"]});
12816

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.