YUI.add('widget-skin', function (Y, NAME) {

/**
 * Provides skin related utlility methods.
 *
 * @module widget
 * @submodule widget-skin
 */
var BOUNDING_BOX = "boundingBox",
    CONTENT_BOX = "contentBox",
    SKIN = "skin",
    _getClassName = Y.ClassNameManager.getClassName;

/**
 * Returns the name of the skin that's currently applied to the widget.
 *
 * Searches up the Widget's ancestor axis for, by default, a class
 * yui3-skin-(name), and returns the (name) portion. Otherwise, returns null.
 *
 * This is only really useful after the widget's DOM structure is in the
 * document, either by render or by progressive enhancement.
 *
 * @method getSkinName
 * @for Widget
 * @param {String} [skinPrefix] The prefix which the implementation uses for the skin
 * ("yui3-skin-" is the default).
 *
 * NOTE: skinPrefix will be used as part of a regular expression:
 *
 *     new RegExp('\\b' + skinPrefix + '(\\S+)')
 *
 * Although an unlikely use case, literal characters which may result in an invalid
 * regular expression should be escaped.
 *
 * @return {String} The name of the skin, or null, if a matching skin class is not found.
 */

Y.Widget.prototype.getSkinName = function (skinPrefix) {

    var root = this.get( CONTENT_BOX ) || this.get( BOUNDING_BOX ),
        match,
        search;

    skinPrefix = skinPrefix || _getClassName(SKIN, "");

    search = new RegExp( '\\b' + skinPrefix + '(\\S+)' );

    if ( root ) {
        root.ancestor( function ( node ) {
            match = node.get( 'className' ).match( search );
            return match;
        } );
    }

    return ( match ) ? match[1] : null;
};


}, 'patched-v3.18.1', {"requires": ["widget-base"]});

YUI.add('widget-uievents', function (Y, NAME) {

/**
 * Support for Widget UI Events (Custom Events fired by the widget, which wrap the underlying DOM events - e.g. widget:click, widget:mousedown)
 *
 * @module widget
 * @submodule widget-uievents
 */

var BOUNDING_BOX = "boundingBox",
    Widget = Y.Widget,
    RENDER = "render",
    L = Y.Lang,
    EVENT_PREFIX_DELIMITER = ":",

    //  Map of Node instances serving as a delegation containers for a specific
    //  event type to Widget instances using that delegation container.
    _uievts = Y.Widget._uievts = Y.Widget._uievts || {};

Y.mix(Widget.prototype, {

    /**
     * Destructor logic for UI event infrastructure,
     * invoked during Widget destruction.
     *
     * @method _destroyUIEvents
     * @for Widget
     * @private
     */
    _destroyUIEvents: function() {

        var widgetGuid = Y.stamp(this, true);

        Y.each(_uievts, function (info, key) {
            if (info.instances[widgetGuid]) {
                //  Unregister this Widget instance as needing this delegated
                //  event listener.
                delete info.instances[widgetGuid];

                //  There are no more Widget instances using this delegated
                //  event listener, so detach it.

                if (Y.Object.isEmpty(info.instances)) {
                    info.handle.detach();

                    if (_uievts[key]) {
                        delete _uievts[key];
                    }
                }
            }
        });
    },

    /**
     * Map of DOM events that should be fired as Custom Events by the
     * Widget instance.
     *
     * @property UI_EVENTS
     * @for Widget
     * @type Object
     */
    UI_EVENTS: Y.Node.DOM_EVENTS,

    /**
     * Returns the node on which to bind delegate listeners.
     *
     * @method _getUIEventNode
     * @for Widget
     * @protected
     */
    _getUIEventNode: function () {
        return this.get(BOUNDING_BOX);
    },

    /**
     * Binds a delegated DOM event listener of the specified type to the
     * Widget's outtermost DOM element to facilitate the firing of a Custom
     * Event of the same type for the Widget instance.
     *
     * @method _createUIEvent
     * @for Widget
     * @param type {String} String representing the name of the event
     * @private
     */
    _createUIEvent: function (type) {

        var uiEvtNode = this._getUIEventNode(),
            key = (Y.stamp(uiEvtNode) + type),
            info = _uievts[key],
            handle;

        //  For each Node instance: Ensure that there is only one delegated
        //  event listener used to fire Widget UI events.

        if (!info) {

            handle = uiEvtNode.delegate(type, function (evt) {

                var widget = Widget.getByNode(this);

                // Widget could be null if node instance belongs to
                // another Y instance.

                if (widget) {
                    if (widget._filterUIEvent(evt)) {
                        widget.fire(evt.type, { domEvent: evt });
                    }
                }

            }, "." + Y.Widget.getClassName());

            _uievts[key] = info = { instances: {}, handle: handle };
        }

        //  Register this Widget as using this Node as a delegation container.
        info.instances[Y.stamp(this)] = 1;
    },

    /**
     * This method is used to determine if we should fire
     * the UI Event or not. The default implementation makes sure
     * that for nested delegates (nested unrelated widgets), we don't
     * fire the UI event listener more than once at each level.
     *
     * <p>For example, without the additional filter, if you have nested
     * widgets, each widget will have a delegate listener. If you
     * click on the inner widget, the inner delegate listener's
     * filter will match once, but the outer will match twice
     * (based on delegate's design) - once for the inner widget,
     * and once for the outer.</p>
     *
     * @method _filterUIEvent
     * @for Widget
     * @param {DOMEventFacade} evt
     * @return {boolean} true if it's OK to fire the custom UI event, false if not.
     * @private
     *
     */
    _filterUIEvent: function(evt) {
        // Either it's hitting this widget's delegate container (and not some other widget's),
        // or the container it's hitting is handling this widget's ui events.
        return (evt.currentTarget.compareTo(evt.container) || evt.container.compareTo(this._getUIEventNode()));
    },

    /**
     * Determines if the specified event is a UI event.
     *
     * @private
     * @method _isUIEvent
     * @for Widget
     * @param type {String} String representing the name of the event
     * @return {String} Event Returns the name of the UI Event, otherwise
     * undefined.
     */
    _getUIEvent: function (type) {

        if (L.isString(type)) {
            var sType = this.parseType(type)[1],
                iDelim,
                returnVal;

            if (sType) {
                // TODO: Get delimiter from ET, or have ET support this.
                iDelim = sType.indexOf(EVENT_PREFIX_DELIMITER);
                if (iDelim > -1) {
                    sType = sType.substring(iDelim + EVENT_PREFIX_DELIMITER.length);
                }

                if (this.UI_EVENTS[sType]) {
                    returnVal = sType;
                }
            }

            return returnVal;
        }
    },

    /**
     * Sets up infrastructure required to fire a UI event.
     *
     * @private
     * @method _initUIEvent
     * @for Widget
     * @param type {String} String representing the name of the event
     * @return {String}
     */
    _initUIEvent: function (type) {
        var sType = this._getUIEvent(type),
            queue = this._uiEvtsInitQueue || {};

        if (sType && !queue[sType]) {

            this._uiEvtsInitQueue = queue[sType] = 1;

            this.after(RENDER, function() {
                this._createUIEvent(sType);
                delete this._uiEvtsInitQueue[sType];
            });
        }
    },

    //  Override of "on" from Base to facilitate the firing of Widget events
    //  based on DOM events of the same name/type (e.g. "click", "mouseover").
    //  Temporary solution until we have the ability to listen to when
    //  someone adds an event listener (bug 2528230)
    on: function (type) {
        this._initUIEvent(type);
        return Widget.superclass.on.apply(this, arguments);
    },

    //  Override of "publish" from Base to facilitate the firing of Widget events
    //  based on DOM events of the same name/type (e.g. "click", "mouseover").
    //  Temporary solution until we have the ability to listen to when
    //  someone publishes an event (bug 2528230)
    publish: function (type, config) {
        var sType = this._getUIEvent(type);
        if (sType && config && config.defaultFn) {
            this._initUIEvent(sType);
        }
        return Widget.superclass.publish.apply(this, arguments);
    }

}, true); // overwrite existing EventTarget methods


}, 'patched-v3.18.1', {"requires": ["node-event-delegate", "widget-base"]});

YUI.add('yui-throttle', function (Y, NAME) {

/**
Throttles a call to a method based on the time between calls. This method is attached
to the `Y` object and is <a href="../classes/YUI.html#method_throttle">documented there</a>.

    var fn = Y.throttle(function() {
        counter++;
    });

    for (i; i< 35000; i++) {
        out++;
        fn();
    }


@module yui
@submodule yui-throttle
*/

/*! Based on work by Simon Willison: http://gist.github.com/292562 */
/**
 * Throttles a call to a method based on the time between calls.
 * @method throttle
 * @for YUI
 * @param fn {function} The function call to throttle.
 * @param ms {Number} The number of milliseconds to throttle the method call.
 * Can set globally with Y.config.throttleTime or by call. Passing a -1 will
 * disable the throttle. Defaults to 150.
 * @return {function} Returns a wrapped function that calls fn throttled.
 * @since 3.1.0
 */
Y.throttle = function(fn, ms) {
    ms = (ms) ? ms : (Y.config.throttleTime || 150);

    if (ms === -1) {
        return function() {
            fn.apply(this, arguments);
        };
    }

    var last = Y.Lang.now();

    return function() {
        var now = Y.Lang.now();
        if (now - last > ms) {
            last = now;
            fn.apply(this, arguments);
        }
    };
};


}, 'patched-v3.18.1', {"requires": ["yui-base"]});

YUI.add('aui-base-core', function (A, NAME) {

var Y = A;
YUI.Env.aliases = YUI.Env.aliases || {};
Y.mix(YUI.Env.aliases, {
    "aui-autosize": ["aui-autosize-iframe"],
    "aui-base": ["oop","yui-throttle","aui-classnamemanager","aui-debounce","aui-base-core","aui-base-lang","aui-node-base"],
    "aui-base-deprecated": ["aui-base","aui-node","aui-component","aui-delayed-task-deprecated","aui-selector","aui-event-base"],
    "aui-button": ["aui-button-core"],
    "aui-collection": ["aui-map","aui-set","aui-linkedset"],
    "aui-color-picker-deprecated": ["aui-color-picker-base-deprecated","aui-color-picker-grid-plugin-deprecated"],
    "aui-datasource-control-deprecated": ["aui-datasource-control-base-deprecated","aui-input-text-control-deprecated"],
    "aui-datatable": ["aui-datatable-edit","aui-datatable-highlight","aui-datatable-selection","aui-datatable-property-list"],
    "aui-datatable-edit": ["datatable-base","calendar","overlay","sortable","aui-datatype","aui-toolbar","aui-form-validator","aui-datatable-base-cell-editor","aui-datatable-base-options-cell-editor","aui-datatable-cell-editor-support","aui-datatable-core","aui-datatable-checkbox-cell-editor","aui-datatable-date-cell-editor","aui-datatable-dropdown-cell-editor","aui-datatable-radio-cell-editor","aui-datatable-text-cell-editor","aui-datatable-text-area-cell-editor"],
    "aui-datepicker-deprecated": ["aui-datepicker-base-deprecated","aui-datepicker-select-deprecated"],
    "aui-event": ["aui-event-base"],
    "aui-form-deprecated": ["aui-form-base-deprecated","aui-form-combobox-deprecated","aui-form-field-deprecated","aui-form-select-deprecated","aui-form-textarea-deprecated","aui-form-textfield-deprecated"],
    "aui-io": ["aui-io-request"],
    "aui-io-deprecated": ["aui-io-request","aui-io-plugin-deprecated"],
    "aui-node": ["aui-node-base"],
    "aui-overlay-deprecated": ["aui-overlay-base-deprecated","aui-overlay-context-deprecated","aui-overlay-context-panel-deprecated","aui-overlay-manager-deprecated","aui-overlay-mask-deprecated"],
    "aui-rating": ["aui-rating-base","aui-rating-thumb"],
    "aui-resize-deprecated": ["aui-resize-base-deprecated","aui-resize-constrain-deprecated"],
    "aui-scheduler": ["event-gestures","aui-scheduler-base","aui-scheduler-event-recorder","aui-scheduler-view-agenda","aui-scheduler-view-day","aui-scheduler-view-month","aui-scheduler-view-table-dd","aui-scheduler-view-table","aui-scheduler-view-week","aui-viewport"],
    "aui-search": ["aui-search-tst"],
    "aui-sortable": ["aui-sortable-layout","aui-sortable-list"],
    "aui-surface": ["aui-surface-app","aui-surface-screen"],
    "aui-toggler": ["aui-toggler-base","aui-toggler-delegate"],
    "aui-tooltip": ["aui-tooltip-base","aui-tooltip-delegate"],
    "aui-tpl-snippets-deprecated": ["aui-tpl-snippets-base-deprecated","aui-tpl-snippets-checkbox-deprecated","aui-tpl-snippets-input-deprecated","aui-tpl-snippets-select-deprecated","aui-tpl-snippets-textarea-deprecated"],
    "aui-tree": ["aui-tree-data","aui-tree-io","aui-tree-node","aui-tree-paginator","aui-tree-view"],
    "aui-widget": ["aui-widget-cssclass","aui-widget-toolbars"],
    "aui-widget-core": ["aui-widget-cssclass"]
});
/* This file is auto-generated by (yogi loader --yes --mix --js js/aui-loader.js --json js/aui-loader.json --start ../) */

/*jshint maxlen:900, eqeqeq: false */

/**
 * YUI 3 module metadata
 * @module loader
 * @submodule loader-yui3
 */
YUI.Env[Y.version].modules = YUI.Env[Y.version].modules || {};
Y.mix(YUI.Env[Y.version].modules, {
    "aui-ace-autocomplete-base": {
        "requires": [
            "aui-ace-editor"
        ]
    },
    "aui-ace-autocomplete-freemarker": {
        "requires": [
            "aui-ace-autocomplete-templateprocessor"
        ]
    },
    "aui-ace-autocomplete-list": {
        "requires": [
            "aui-ace-autocomplete-base",
            "overlay",
            "widget-autohide"
        ],
        "skinnable": true
    },
    "aui-ace-autocomplete-plugin": {
        "requires": [
            "aui-ace-autocomplete-list",
            "plugin"
        ]
    },
    "aui-ace-autocomplete-templateprocessor": {
        "requires": [
            "aui-ace-autocomplete-base"
        ]
    },
    "aui-ace-autocomplete-velocity": {
        "requires": [
            "aui-ace-autocomplete-templateprocessor"
        ]
    },
    "aui-ace-editor": {
        "requires": [
            "aui-node",
            "aui-component"
        ]
    },
    "aui-affix": {
        "requires": [
            "base",
            "node-screen",
            "aui-node"
        ]
    },
    "aui-alert": {
        "requires": [
            "aui-aria",
            "aui-classnamemanager",
            "aui-widget-cssclass",
            "aui-widget-transition",
            "timers",
            "widget",
            "widget-stdmod"
        ],
        "skinnable": true
    },
    "aui-aria": {
        "requires": [
            "plugin",
            "aui-component"
        ]
    },
    "aui-aria-table-sortable": {
        "requires": [
            "aui-aria"
        ]
    },
    "aui-arraysort": {
        "requires": [
            "arraysort"
        ]
    },
    "aui-audio": {
        "requires": [
            "aui-aria",
            "aui-node",
            "aui-component",
            "node-event-html5",
            "querystring-stringify-simple"
        ],
        "skinnable": true
    },
    "aui-autocomplete-deprecated": {
        "requires": [
            "aui-base-deprecated",
            "aui-overlay-base-deprecated",
            "datasource",
            "dataschema",
            "aui-form-combobox-deprecated"
        ],
        "skinnable": true
    },
    "aui-autosize": {
        "use": [
            "aui-autosize-iframe"
        ]
    },
    "aui-autosize-deprecated": {
        "requires": [
            "event-valuechange",
            "plugin",
            "aui-base-deprecated"
        ],
        "skinnable": true
    },
    "aui-autosize-iframe": {
        "requires": [
            "plugin",
            "aui-component",
            "aui-timer",
            "aui-node-base"
        ]
    },
    "aui-base": {
        "use": [
            "oop",
            "yui-throttle",
            "aui-classnamemanager",
            "aui-debounce",
            "aui-base-core",
            "aui-base-lang",
            "aui-node-base"
        ]
    },
    "aui-base-core": {},
    "aui-base-deprecated": {
        "use": [
            "aui-base",
            "aui-node",
            "aui-component",
            "aui-delayed-task-deprecated",
            "aui-selector",
            "aui-event-base"
        ]
    },
    "aui-base-html5-shiv": {
        "condition": {
            "name": "aui-base-html5-shiv",
            "trigger": "node-base",
            "ua": "ie"
        }
    },
    "aui-base-lang": {},
    "aui-boolean-data-editor": {
        "requires": [
            "aui-button-switch",
            "aui-data-editor"
        ]
    },
    "aui-button": {
        "use": [
            "aui-button-core"
        ]
    },
    "aui-button-core": {
        "requires": [
            "button",
            "button-group",
            "button-plugin",
            "aui-component",
            "aui-widget-cssclass",
            "aui-widget-toggle"
        ],
        "skinnable": true
    },
    "aui-button-item-deprecated": {
        "requires": [
            "aui-base-deprecated",
            "aui-state-interaction-deprecated",
            "widget-child"
        ],
        "skinnable": true
    },
    "aui-button-search-cancel": {
        "requires": [
            "array-invoke",
            "base",
            "base-build",
            "event-focus",
            "event-move",
            "event-resize",
            "node-screen",
            "node-event-delegate",
            "aui-node-base",
            "aui-classnamemanager",
            "aui-event-input"
        ]
    },
    "aui-button-switch": {
        "requires": [
            "aui-node-base",
            "base-build",
            "event-key",
            "transition",
            "widget"
        ],
        "skinnable": true
    },
    "aui-carousel": {
        "requires": [
            "anim",
            "aui-event",
            "aui-image-viewer-base",
            "aui-image-viewer-slideshow",
            "node-event-delegate",
            "node-focusmanager"
        ],
        "skinnable": true
    },
    "aui-carousel-mobile-touch": {
        "condition": {
            "name": "aui-carousel-mobile-touch",
            "test": function(A) {
    return A.UA.mobile && A.UA.touchEnabled;
},
            "trigger": "aui-carousel"
        },
        "requires": [
            "base-build",
            "aui-carousel"
        ]
    },
    "aui-carousel-swipe": {
        "condition": {
            "name": "aui-carousel-swipe",
            "trigger": "aui-carousel",
            "ua": "touchEnabled"
        },
        "requires": [
            "aui-carousel",
            "aui-widget-swipe",
            "base-build"
        ],
        "skinnable": true
    },
    "aui-char-counter": {
        "requires": [
            "aui-aria",
            "aui-node",
            "aui-event-input",
            "aui-component"
        ]
    },
    "aui-chart-deprecated": {
        "requires": [
            "datasource",
            "json",
            "aui-swf-deprecated"
        ]
    },
    "aui-classnamemanager": {
        "requires": [
            "classnamemanager"
        ]
    },
    "aui-collection": {
        "use": [
            "aui-map",
            "aui-set",
            "aui-linkedset"
        ]
    },
    "aui-color-palette": {
        "requires": [
            "array-extras",
            "aui-palette",
            "color-base",
            "node-core",
            "aui-widget-cssclass",
            "aui-widget-toggle"
        ],
        "skinnable": true
    },
    "aui-color-picker-base": {
        "requires": [
            "aui-color-palette",
            "aui-hsva-palette-modal",
            "event-outside"
        ],
        "skinnable": true
    },
    "aui-color-picker-base-deprecated": {
        "requires": [
            "dd-drag",
            "panel",
            "slider",
            "aui-button-item-deprecated",
            "aui-color-util-deprecated",
            "aui-form-base-deprecated",
            "aui-overlay-context-deprecated"
        ],
        "skinnable": true
    },
    "aui-color-picker-deprecated": {
        "use": [
            "aui-color-picker-base-deprecated",
            "aui-color-picker-grid-plugin-deprecated"
        ]
    },
    "aui-color-picker-grid-plugin-deprecated": {
        "requires": [
            "plugin",
            "aui-color-picker-base-deprecated"
        ],
        "skinnable": true
    },
    "aui-color-picker-popover": {
        "requires": [
            "aui-color-picker-base",
            "aui-popover",
            "aui-widget-cssclass",
            "aui-widget-toggle"
        ],
        "skinnable": true
    },
    "aui-color-util-deprecated": {
        "requires": []
    },
    "aui-component": {
        "requires": [
            "aui-classnamemanager",
            "aui-widget-cssclass",
            "aui-widget-toggle",
            "base-build",
            "widget-base"
        ]
    },
    "aui-css": {
        "type": "css"
    },
    "aui-data-editor": {
        "requires": [
            "aui-classnamemanager",
            "base-build",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-data-set-deprecated": {
        "requires": [
            "oop",
            "collection",
            "base"
        ]
    },
    "aui-datasource-control-base-deprecated": {
        "requires": [
            "datasource",
            "dataschema",
            "aui-base-deprecated"
        ]
    },
    "aui-datasource-control-deprecated": {
        "use": [
            "aui-datasource-control-base-deprecated",
            "aui-input-text-control-deprecated"
        ]
    },
    "aui-datatable": {
        "use": [
            "aui-datatable-edit",
            "aui-datatable-highlight",
            "aui-datatable-selection",
            "aui-datatable-property-list"
        ]
    },
    "aui-datatable-base-cell-editor": {
        "requires": [
            "datatable-base",
            "overlay"
        ],
        "skinnable": true
    },
    "aui-datatable-base-options-cell-editor": {
        "requires": [
            "aui-datatable-base-cell-editor",
            "escape"
        ],
        "skinnable": true
    },
    "aui-datatable-body": {
        "requires": [
            "aui-classnamemanager",
            "datatable-base",
            "event-key",
            "aui-event-base"
        ]
    },
    "aui-datatable-cell-editor-support": {
        "requires": [
            "datatable-base"
        ]
    },
    "aui-datatable-checkbox-cell-editor": {
        "requires": [
            "aui-datatable-base-options-cell-editor"
        ]
    },
    "aui-datatable-core": {
        "requires": [
            "aui-datatable-body",
            "datatable-base",
            "event-key",
            "aui-event-base"
        ],
        "skinnable": true
    },
    "aui-datatable-date-cell-editor": {
        "requires": [
            "aui-datatable-base-options-cell-editor"
        ]
    },
    "aui-datatable-dropdown-cell-editor": {
        "requires": [
            "aui-datatable-base-options-cell-editor"
        ]
    },
    "aui-datatable-edit": {
        "use": [
            "datatable-base",
            "calendar",
            "overlay",
            "sortable",
            "aui-datatype",
            "aui-toolbar",
            "aui-form-validator",
            "aui-datatable-base-cell-editor",
            "aui-datatable-base-options-cell-editor",
            "aui-datatable-cell-editor-support",
            "aui-datatable-core",
            "aui-datatable-checkbox-cell-editor",
            "aui-datatable-date-cell-editor",
            "aui-datatable-dropdown-cell-editor",
            "aui-datatable-radio-cell-editor",
            "aui-datatable-text-cell-editor",
            "aui-datatable-text-area-cell-editor"
        ]
    },
    "aui-datatable-highlight": {
        "requires": [
            "aui-datatable-selection"
        ],
        "skinnable": true
    },
    "aui-datatable-property-list": {
        "requires": [
            "datatable-scroll",
            "datatable-sort",
            "aui-datatable-core",
            "aui-datatable-edit",
            "aui-datatable-highlight",
            "aui-datatable-selection",
            "aui-widget-cssclass",
            "aui-widget-toggle"
        ],
        "skinnable": true
    },
    "aui-datatable-radio-cell-editor": {
        "requires": [
            "aui-datatable-base-options-cell-editor"
        ]
    },
    "aui-datatable-selection": {
        "requires": [
            "aui-datatable-core"
        ],
        "skinnable": true
    },
    "aui-datatable-text-area-cell-editor": {
        "requires": [
            "aui-datatable-base-options-cell-editor"
        ]
    },
    "aui-datatable-text-cell-editor": {
        "requires": [
            "aui-datatable-base-options-cell-editor"
        ]
    },
    "aui-datatype": {
        "requires": [
            "datatype",
            "aui-datatype-date-parse"
        ]
    },
    "aui-datatype-date-parse": {
        "requires": [
            "aui-base-lang",
            "datatype-date-format",
            "datatype-date-parse",
            "intl"
        ]
    },
    "aui-datepicker": {
        "requires": [
            "aui-aria",
            "aui-datepicker-delegate",
            "aui-datepicker-popover",
            "base",
            "base-build",
            "calendar"
        ],
        "skinnable": true
    },
    "aui-datepicker-base-deprecated": {
        "requires": [
            "calendar",
            "aui-datatype",
            "aui-overlay-context-deprecated"
        ],
        "skinnable": true
    },
    "aui-datepicker-delegate": {
        "requires": [
            "aui-datatype-date-parse",
            "aui-event-input",
            "event-focus",
            "node-event-delegate"
        ]
    },
    "aui-datepicker-deprecated": {
        "skinnable": true,
        "use": [
            "aui-datepicker-base-deprecated",
            "aui-datepicker-select-deprecated"
        ]
    },
    "aui-datepicker-native": {
        "requires": [
            "aui-datepicker-delegate",
            "aui-node-base",
            "base",
            "base-build"
        ]
    },
    "aui-datepicker-popover": {
        "requires": [
            "aui-classnamemanager",
            "aui-popover"
        ]
    },
    "aui-datepicker-select-deprecated": {
        "requires": [
            "aui-datepicker-base-deprecated",
            "aui-button-item-deprecated"
        ],
        "skinnable": true
    },
    "aui-debounce": {},
    "aui-delayed-task-deprecated": {
        "requires": [
            "yui-base"
        ]
    },
    "aui-diagram-builder": {
        "requires": [
            "aui-aria",
            "aui-map",
            "aui-property-builder",
            "aui-diagram-builder-connector",
            "aui-property-builder-settings",
            "aui-diagram-node-condition",
            "aui-diagram-node-end",
            "aui-diagram-node-fork",
            "aui-diagram-node-join",
            "aui-diagram-node-start",
            "aui-diagram-node-state",
            "aui-diagram-node-task",
            "overlay"
        ],
        "skinnable": true
    },
    "aui-diagram-builder-connector": {
        "requires": [
            "arraylist-add",
            "arraylist-filter",
            "escape",
            "json",
            "graphics",
            "dd"
        ],
        "skinnable": true
    },
    "aui-diagram-node": {
        "requires": [
            "aui-aria",
            "aui-diagram-node-manager-base",
            "escape",
            "overlay"
        ]
    },
    "aui-diagram-node-condition": {
        "requires": [
            "aui-diagram-node-state"
        ]
    },
    "aui-diagram-node-end": {
        "requires": [
            "aui-diagram-node-state"
        ]
    },
    "aui-diagram-node-fork": {
        "requires": [
            "aui-diagram-node-state"
        ]
    },
    "aui-diagram-node-join": {
        "requires": [
            "aui-diagram-node-state"
        ]
    },
    "aui-diagram-node-manager-base": {
        "requires": [
            "base"
        ]
    },
    "aui-diagram-node-start": {
        "requires": [
            "aui-diagram-node-state"
        ]
    },
    "aui-diagram-node-state": {
        "requires": [
            "aui-diagram-node"
        ]
    },
    "aui-diagram-node-task": {
        "requires": [
            "aui-diagram-node-state"
        ]
    },
    "aui-dialog-iframe-deprecated": {
        "requires": [
            "plugin",
            "array-invoke",
            "aui-base-deprecated",
            "aui-loading-mask-deprecated"
        ],
        "skinnable": true
    },
    "aui-dropdown": {
        "requires": [
            "event-delegate",
            "event-key",
            "event-outside",
            "node-focusmanager",
            "widget",
            "widget-stack",
            "aui-classnamemanager",
            "aui-node",
            "aui-widget-cssclass",
            "aui-widget-toggle",
            "aui-widget-trigger"
        ],
        "skinnable": true
    },
    "aui-editable-deprecated": {
        "requires": [
            "aui-base-deprecated",
            "aui-form-combobox-deprecated",
            "escape",
            "event-resize"
        ],
        "skinnable": true
    },
    "aui-event": {
        "use": [
            "aui-event-base"
        ]
    },
    "aui-event-base": {
        "requires": [
            "event-base"
        ]
    },
    "aui-event-delegate-change": {
        "condition": {
            "name": "aui-event-delegate-change",
            "trigger": "event-base-ie",
            "ua": "ie"
        },
        "requires": [
            "aui-event-base",
            "event-delegate",
            "event-synthetic"
        ]
    },
    "aui-event-delegate-submit": {
        "condition": {
            "name": "aui-event-delegate-submit",
            "trigger": "event-base-ie",
            "ua": "ie"
        },
        "requires": [
            "aui-event-base",
            "event-delegate",
            "event-synthetic"
        ]
    },
    "aui-event-input": {
        "condition": {
            "name": "aui-event-input",
            "test": function(A) {
    var supportsDOMEvent = A.supportsDOMEvent,
        testFeature = A.Features.test,
        addFeature = A.Features.add;

    if (testFeature('event', 'input') === undefined) {
        addFeature('event', 'input', {
            test: function() {
                return supportsDOMEvent(document.createElement('textarea'), 'input') && (!A.UA.ie || A.UA.ie > 9);
            }
        });
    }

    return !testFeature('event', 'input');
},
            "trigger": "aui-event-base"
        },
        "requires": [
            "aui-event-base",
            "event-delegate",
            "event-synthetic",
            "timers"
        ]
    },
    "aui-form-base-deprecated": {
        "requires": [
            "io-form",
            "querystring-parse",
            "aui-base-deprecated",
            "aui-data-set-deprecated",
            "aui-form-field-deprecated"
        ]
    },
    "aui-form-builder": {
        "requires": [
            "aui-modal",
            "aui-layout",
            "aui-form-builder-field-list",
            "aui-form-builder-field-toolbar",
            "aui-form-builder-field-type",
            "aui-form-builder-field-types",
            "aui-form-builder-layout-builder",
            "aui-form-builder-page-manager",
            "aui-form-builder-settings-modal",
            "event-focus",
            "event-tap"
        ],
        "skinnable": true
    },
    "aui-form-builder-available-field-deprecated": {
        "requires": [
            "aui-property-builder-available-field"
        ]
    },
    "aui-form-builder-deprecated": {
        "requires": [
            "aui-button",
            "aui-collection",
            "aui-form-builder-available-field-deprecated",
            "aui-form-builder-field-deprecated",
            "aui-form-builder-field-button-deprecated",
            "aui-form-builder-field-checkbox-deprecated",
            "aui-form-builder-field-fieldset-deprecated",
            "aui-form-builder-field-file-upload-deprecated",
            "aui-form-builder-field-multiple-choice-deprecated",
            "aui-form-builder-field-radio-deprecated",
            "aui-form-builder-field-select-deprecated",
            "aui-form-builder-field-text-deprecated",
            "aui-form-builder-field-textarea-deprecated",
            "aui-property-builder",
            "aui-property-builder-settings",
            "aui-sortable-list",
            "aui-tabview",
            "aui-tooltip-base",
            "escape",
            "transition"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-base": {
        "requires": [
            "aui-classnamemanager",
            "aui-node-base",
            "aui-text-data-editor",
            "aui-toggler",
            "base",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-button-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-checkbox-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-choice": {
        "requires": [
            "aui-boolean-data-editor",
            "aui-options-data-editor",
            "aui-tabs-data-editor",
            "aui-form-builder-field-base",
            "aui-form-field-choice"
        ]
    },
    "aui-form-builder-field-deprecated": {
        "requires": [
            "panel",
            "aui-datatype",
            "aui-datatable-edit",
            "aui-property-builder-field-support"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-fieldset-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-file-upload-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-list": {
        "requires": [
            "aui-form-builder-field-type",
            "aui-form-builder-field-types",
            "aui-form-builder-layout-builder"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-multiple-choice-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-radio-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-select-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-sentence": {
        "requires": [
            "aui-form-builder-field-base",
            "aui-form-field"
        ]
    },
    "aui-form-builder-field-text": {
        "requires": [
            "aui-boolean-data-editor",
            "aui-radio-group-data-editor",
            "aui-form-builder-field-base",
            "aui-form-field-text"
        ]
    },
    "aui-form-builder-field-text-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-textarea-deprecated": {
        "requires": [
            "aui-form-builder-field-deprecated"
        ]
    },
    "aui-form-builder-field-toolbar": {
        "requires": [
            "aui-classnamemanager",
            "base",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-type": {
        "requires": [
            "base",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-types": {
        "requires": [
            "aui-classnamemanager",
            "aui-form-builder-field-types-modal",
            "base",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-builder-field-types-modal": {
        "requires": [
            "aui-modal"
        ],
        "skinnable": true
    },
    "aui-form-builder-layout-builder": {
        "requires": [
            "aui-classnamemanager",
            "aui-layout-builder",
            "aui-modal",
            "base",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-builder-page-manager": {
        "requires": [
            "aui-pagination",
            "aui-popover",
            "aui-tabview",
            "base",
            "event-valuechange",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-builder-settings-modal": {
        "requires": [
            "aui-classnamemanager",
            "aui-modal",
            "base",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-form-combobox-deprecated": {
        "requires": [
            "aui-form-textarea-deprecated",
            "aui-toolbar"
        ],
        "skinnable": true
    },
    "aui-form-deprecated": {
        "use": [
            "aui-form-base-deprecated",
            "aui-form-combobox-deprecated",
            "aui-form-field-deprecated",
            "aui-form-select-deprecated",
            "aui-form-textarea-deprecated",
            "aui-form-textfield-deprecated"
        ]
    },
    "aui-form-field": {
        "requires": [
            "aui-classnamemanager",
            "aui-node-base",
            "base-build"
        ],
        "skinnable": true
    },
    "aui-form-field-choice": {
        "requires": [
            "aui-form-field-required"
        ],
        "skinnable": true
    },
    "aui-form-field-deprecated": {
        "requires": [
            "aui-base-deprecated",
            "aui-component"
        ]
    },
    "aui-form-field-required": {
        "requires": [
            "aui-form-field"
        ]
    },
    "aui-form-field-text": {
        "requires": [
            "aui-form-field-required"
        ],
        "skinnable": true
    },
    "aui-form-select-deprecated": {
        "requires": [
            "aui-form-field-deprecated"
        ]
    },
    "aui-form-textarea-deprecated": {
        "requires": [
            "node-pluginhost",
            "aui-autosize-deprecated",
            "aui-form-textfield-deprecated"
        ]
    },
    "aui-form-textfield-deprecated": {
        "requires": [
            "aui-form-field-deprecated"
        ]
    },
    "aui-form-validator": {
        "requires": [
            "escape",
            "selector-css3",
            "node-event-delegate",
            "aui-node",
            "aui-component",
            "aui-event-input"
        ]
    },
    "aui-hsv-palette": {
        "requires": [
            "aui-classnamemanager",
            "aui-widget-cssclass",
            "aui-widget-toggle",
            "aui-event-input",
            "base-build",
            "clickable-rail",
            "color-hsv",
            "dd-constrain",
            "slider",
            "widget"
        ],
        "skinnable": true
    },
    "aui-hsva-palette": {
        "requires": [
            "aui-hsv-palette"
        ],
        "skinnable": true
    },
    "aui-hsva-palette-modal": {
        "requires": [
            "aui-hsva-palette",
            "aui-modal"
        ],
        "skinnable": true
    },
    "aui-image-cropper": {
        "requires": [
            "resize-base",
            "resize-constrain",
            "dd-constrain",
            "aui-node-base",
            "aui-component"
        ],
        "skinnable": true
    },
    "aui-image-viewer": {
        "requires": [
            "widget",
            "widget-modality",
            "widget-position",
            "widget-position-align",
            "widget-position-constrain",
            "widget-stack",
            "widget-stdmod",
            "aui-event",
            "aui-image-viewer-base",
            "aui-image-viewer-multiple",
            "aui-image-viewer-slideshow",
            "aui-node-base",
            "aui-widget-cssclass",
            "aui-widget-toggle"
        ],
        "skinnable": true
    },
    "aui-image-viewer-base": {
        "requires": [
            "anim",
            "aui-aria",
            "aui-classnamemanager",
            "aui-node",
            "aui-widget-responsive",
            "base-build",
            "imageloader",
            "node-base",
            "widget",
            "widget-stack"
        ],
        "skinnable": true
    },
    "aui-image-viewer-media": {
        "requires": [
            "plugin",
            "aui-component",
            "aui-image-viewer"
        ]
    },
    "aui-image-viewer-multiple": {
        "requires": [
            "base-build",
            "node-base",
            "aui-classnamemanager",
            "aui-image-viewer-base"
        ],
        "skinnable": true
    },
    "aui-image-viewer-multiple-swipe": {
        "condition": {
            "name": "aui-image-viewer-multiple-swipe",
            "trigger": "aui-image-viewer-multiple",
            "ua": "touchEnabled"
        },
        "requires": [
            "aui-image-viewer-multiple",
            "aui-image-viewer-swipe"
        ]
    },
    "aui-image-viewer-slideshow": {
        "requires": [
            "node",
            "aui-classnamemanager"
        ]
    },
    "aui-image-viewer-swipe": {
        "condition": {
            "name": "aui-image-viewer-swipe",
            "trigger": "aui-image-viewer-base",
            "ua": "touchEnabled"
        },
        "requires": [
            "event-resize",
            "aui-image-viewer-base",
            "aui-widget-swipe"
        ]
    },
    "aui-input-text-control-deprecated": {
        "requires": [
            "aui-base-deprecated",
            "aui-datasource-control-base-deprecated",
            "aui-form-combobox-deprecated"
        ]
    },
    "aui-io": {
        "use": [
            "aui-io-request"
        ]
    },
    "aui-io-deprecated": {
        "use": [
            "aui-io-request",
            "aui-io-plugin-deprecated"
        ]
    },
    "aui-io-plugin-deprecated": {
        "requires": [
            "aui-overlay-base-deprecated",
            "aui-parse-content",
            "aui-io-request",
            "aui-loading-mask-deprecated"
        ]
    },
    "aui-io-request": {
        "requires": [
            "io-base",
            "json",
            "plugin",
            "querystring-stringify",
            "aui-component"
        ]
    },
    "aui-io-request-deprecated": {
        "requires": [
            "io-base",
            "json",
            "plugin",
            "querystring-stringify",
            "aui-base-deprecated"
        ]
    },
    "aui-layout": {
        "requires": [
            "aui-layout-col",
            "aui-layout-row",
            "aui-node-base",
            "base-build",
            "datatype-number-parse",
            "event-resize"
        ]
    },
    "aui-layout-builder": {
        "requires": [
            "aui-classnamemanager",
            "aui-layout",
            "aui-layout-builder-add-col",
            "aui-layout-builder-add-row",
            "aui-layout-builder-move",
            "aui-layout-builder-remove-row",
            "aui-layout-builder-resize-col",
            "aui-node-base",
            "base-build",
            "node-event-delegate",
            "node-screen",
            "node-style"
        ]
    },
    "aui-layout-builder-add-col": {
        "requires": [
            "event-key",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-layout-builder-add-row": {
        "requires": [
            "aui-node-base",
            "base-build",
            "node-scroll-info"
        ],
        "skinnable": true
    },
    "aui-layout-builder-move": {
        "requires": [
            "aui-node-base",
            "base-build"
        ],
        "skinnable": true
    },
    "aui-layout-builder-remove-row": {
        "requires": [
            "aui-node-base",
            "base-build"
        ],
        "skinnable": true
    },
    "aui-layout-builder-resize-col": {
        "requires": [
            "dd-constrain",
            "dd-delegate",
            "dd-drop-plugin",
            "dd-proxy",
            "event-mouseenter",
            "node-base"
        ],
        "skinnable": true
    },
    "aui-layout-col": {
        "requires": [
            "aui-classnamemanager",
            "aui-node-base",
            "base-build"
        ],
        "skinnable": true
    },
    "aui-layout-row": {
        "requires": [
            "array-invoke",
            "aui-node-base",
            "base-build"
        ],
        "skinnable": true
    },
    "aui-linkedset": {
        "requires": [
            "aui-set"
        ]
    },
    "aui-live-search-deprecated": {
        "requires": [
            "aui-base-deprecated"
        ]
    },
    "aui-loading-mask-deprecated": {
        "requires": [
            "plugin",
            "aui-overlay-mask-deprecated"
        ],
        "skinnable": true
    },
    "aui-map": {
        "requires": [
            "base-build"
        ]
    },
    "aui-menu": {
        "requires": [
            "base-build",
            "event-mouseenter",
            "event-resize",
            "widget",
            "widget-position",
            "widget-position-align",
            "widget-position-constrain",
            "widget-stack",
            "aui-classnamemanager",
            "aui-debounce",
            "aui-dropdown",
            "aui-menu-item"
        ],
        "skinnable": true
    },
    "aui-menu-item": {
        "requires": [
            "base-build",
            "node-base",
            "aui-classnamemanager",
            "aui-node",
            "aui-widget-shortcut"
        ]
    },
    "aui-messaging": {
        "requires": [
            "querystring",
            "aui-timer"
        ]
    },
    "aui-modal": {
        "requires": [
            "widget",
            "widget-autohide",
            "widget-buttons",
            "widget-modality",
            "widget-position",
            "widget-position-align",
            "widget-position-constrain",
            "widget-stack",
            "widget-stdmod",
            "dd-plugin",
            "dd-constrain",
            "timers",
            "aui-classnamemanager",
            "aui-widget-cssclass",
            "aui-widget-toggle",
            "aui-widget-toolbars"
        ],
        "skinnable": true
    },
    "aui-modal-resize": {
        "condition": {
            "name": "aui-modal-resize",
            "test": function(A) {
    return !A.UA.mobile;
},
            "trigger": "aui-modal"
        },
        "requires": [
            "aui-modal",
            "resize-plugin"
        ]
    },
    "aui-node": {
        "use": [
            "aui-node-base"
        ]
    },
    "aui-node-accessible": {
        "requires": [
            "aui-node-base",
            "event-custom-base"
        ]
    },
    "aui-node-base": {
        "requires": [
            "array-extras",
            "aui-base-lang",
            "aui-classnamemanager",
            "aui-debounce",
            "node"
        ]
    },
    "aui-node-html5": {
        "condition": {
            "name": "aui-node-html5",
            "trigger": "aui-node",
            "ua": "ie"
        },
        "requires": [
            "collection",
            "aui-node-base"
        ]
    },
    "aui-options-data-editor": {
        "requires": [
            "aui-data-editor",
            "dd-constrain",
            "dd-delegate",
            "dd-drop-plugin",
            "dd-proxy",
            "event-valuechange",
            "node-event-delegate"
        ],
        "skinnable": true
    },
    "aui-overlay-base-deprecated": {
        "requires": [
            "widget-position",
            "widget-stack",
            "widget-position-align",
            "widget-position-constrain",
            "widget-stdmod",
            "aui-component"
        ]
    },
    "aui-overlay-context-deprecated": {
        "requires": [
            "aui-overlay-manager-deprecated",
            "aui-delayed-task-deprecated",
            "aui-aria"
        ]
    },
    "aui-overlay-context-panel-deprecated": {
        "requires": [
            "anim",
            "aui-overlay-context-deprecated"
        ],
        "skinnable": true
    },
    "aui-overlay-deprecated": {
        "use": [
            "aui-overlay-base-deprecated",
            "aui-overlay-context-deprecated",
            "aui-overlay-context-panel-deprecated",
            "aui-overlay-manager-deprecated",
            "aui-overlay-mask-deprecated"
        ]
    },
    "aui-overlay-manager-deprecated": {
        "requires": [
            "overlay",
            "plugin",
            "aui-base-deprecated",
            "aui-overlay-base-deprecated"
        ]
    },
    "aui-overlay-mask-deprecated": {
        "requires": [
            "event-resize",
            "aui-base-deprecated",
            "aui-overlay-base-deprecated"
        ],
        "skinnable": true
    },
    "aui-pagination": {
        "requires": [
            "node-event-delegate",
            "aui-node",
            "aui-component",
            "widget-htmlparser"
        ],
        "skinnable": true
    },
    "aui-palette": {
        "requires": [
            "base-build",
            "event-hover",
            "widget",
            "aui-classnamemanager",
            "aui-base",
            "aui-widget-cssclass",
            "aui-widget-toggle"
        ],
        "skinnable": true
    },
    "aui-parse-content": {
        "requires": [
            "async-queue",
            "plugin",
            "io-base",
            "aui-component",
            "aui-node-base"
        ]
    },
    "aui-popover": {
        "requires": [
            "event-resize",
            "widget",
            "widget-autohide",
            "widget-buttons",
            "widget-modality",
            "widget-position",
            "widget-position-align",
            "widget-position-constrain",
            "widget-stack",
            "widget-stdmod",
            "aui-classnamemanager",
            "aui-widget-cssclass",
            "aui-widget-toggle",
            "aui-widget-toolbars",
            "aui-widget-transition",
            "aui-widget-trigger",
            "aui-widget-position-align-suggestion",
            "aui-component",
            "aui-node-base"
        ],
        "skinnable": true
    },
    "aui-progressbar": {
        "requires": [
            "aui-node",
            "aui-component",
            "aui-aria"
        ],
        "skinnable": true
    },
    "aui-promise": {
        "requires": [
            "array-invoke",
            "promise",
            "oop"
        ]
    },
    "aui-property-builder": {
        "requires": [
            "dd",
            "collection",
            "aui-property-builder-available-field",
            "aui-property-builder-field-support",
            "aui-property-builder-settings",
            "aui-tabview"
        ],
        "skinnable": true
    },
    "aui-property-builder-available-field": {
        "requires": [
            "base",
            "aui-component",
            "aui-node"
        ]
    },
    "aui-property-builder-field-support": {},
    "aui-property-builder-settings": {
        "requires": [
            "aui-tabview",
            "aui-datatable-property-list"
        ]
    },
    "aui-radio-group-data-editor": {
        "requires": [
            "aui-data-editor",
            "node-event-delegate"
        ],
        "skinnable": true
    },
    "aui-rating": {
        "use": [
            "aui-rating-base",
            "aui-rating-thumb"
        ]
    },
    "aui-rating-base": {
        "requires": [
            "aui-component",
            "aui-node-base",
            "widget-htmlparser",
            "widget-uievents"
        ],
        "skinnable": true
    },
    "aui-rating-thumb": {
        "requires": [
            "aui-rating-base"
        ]
    },
    "aui-resize-base-deprecated": {
        "requires": [
            "dd-drag",
            "dd-delegate",
            "dd-drop",
            "aui-base-deprecated"
        ],
        "skinnable": true
    },
    "aui-resize-constrain-deprecated": {
        "requires": [
            "dd-constrain",
            "plugin",
            "aui-resize-base-deprecated"
        ]
    },
    "aui-resize-deprecated": {
        "skinnable": true,
        "use": [
            "aui-resize-base-deprecated",
            "aui-resize-constrain-deprecated"
        ]
    },
    "aui-scale-data-editor": {
        "requires": [
            "aui-classnamemanager",
            "aui-data-editor",
            "event-valuechange"
        ]
    },
    "aui-scheduler": {
        "use": [
            "event-gestures",
            "aui-scheduler-base",
            "aui-scheduler-event-recorder",
            "aui-scheduler-view-agenda",
            "aui-scheduler-view-day",
            "aui-scheduler-view-month",
            "aui-scheduler-view-table-dd",
            "aui-scheduler-view-table",
            "aui-scheduler-view-week",
            "aui-viewport"
        ]
    },
    "aui-scheduler-base": {
        "requires": [
            "model",
            "model-list",
            "widget-stdmod",
            "color-hsl",
            "aui-event-base",
            "aui-node-base",
            "aui-component",
            "aui-datatype",
            "aui-button",
            "node-focusmanager"
        ],
        "skinnable": true
    },
    "aui-scheduler-event-recorder": {
        "requires": [
            "querystring",
            "io-form",
            "overlay",
            "aui-scheduler-base",
            "aui-popover"
        ],
        "skinnable": true
    },
    "aui-scheduler-touch": {
        "condition": {
            "name": "aui-scheduler-touch",
            "trigger": "aui-scheduler",
            "ua": "touchEnabled"
        },
        "requires": [
            "base-build",
            "aui-scheduler"
        ],
        "skinnable": true
    },
    "aui-scheduler-view-agenda": {
        "requires": [
            "aui-scheduler-base"
        ],
        "skinnable": true
    },
    "aui-scheduler-view-day": {
        "requires": [
            "dd-drag",
            "dd-delegate",
            "dd-drop",
            "dd-constrain",
            "aui-scheduler-view-table"
        ],
        "skinnable": true
    },
    "aui-scheduler-view-month": {
        "requires": [
            "aui-scheduler-view-table"
        ],
        "skinnable": true
    },
    "aui-scheduler-view-table": {
        "requires": [
            "overlay",
            "aui-scheduler-base"
        ],
        "skinnable": true
    },
    "aui-scheduler-view-table-dd": {
        "requires": [
            "dd-drag",
            "dd-delegate",
            "dd-drop",
            "aui-scheduler-view-table"
        ]
    },
    "aui-scheduler-view-week": {
        "requires": [
            "aui-scheduler-view-day"
        ],
        "skinnable": true
    },
    "aui-scroller-deprecated": {
        "requires": [
            "event-mouseenter",
            "aui-base-deprecated",
            "aui-simple-anim-deprecated"
        ],
        "skinnable": true
    },
    "aui-scrollspy": {
        "requires": [
            "base-build",
            "node-screen",
            "aui-classnamemanager"
        ]
    },
    "aui-search": {
        "use": [
            "aui-search-tst"
        ]
    },
    "aui-search-tst": {
        "requires": [
            "aui-component"
        ]
    },
    "aui-selector": {
        "requires": [
            "selector-css3",
            "aui-classnamemanager"
        ]
    },
    "aui-set": {
        "requires": [
            "aui-map"
        ]
    },
    "aui-simple-anim-deprecated": {
        "requires": [
            "aui-base-deprecated"
        ]
    },
    "aui-skin-deprecated": {
        "type": "css"
    },
    "aui-sortable": {
        "use": [
            "aui-sortable-layout",
            "aui-sortable-list"
        ]
    },
    "aui-sortable-layout": {
        "requires": [
            "dd-delegate",
            "dd-drag",
            "dd-drop",
            "dd-proxy",
            "aui-node",
            "aui-component"
        ],
        "skinnable": true
    },
    "aui-sortable-list": {
        "requires": [
            "dd-drag",
            "dd-drop",
            "dd-proxy",
            "dd-scroll",
            "aui-node",
            "aui-component"
        ]
    },
    "aui-state-interaction-deprecated": {
        "requires": [
            "aui-base-deprecated",
            "plugin"
        ]
    },
    "aui-surface": {
        "use": [
            "aui-surface-app",
            "aui-surface-screen"
        ]
    },
    "aui-surface-app": {
        "requires": [
            "event-delegate",
            "node-event-html5",
            "aui-surface-base",
            "aui-surface-screen",
            "aui-surface-screen-route"
        ]
    },
    "aui-surface-base": {
        "requires": [
            "base-build",
            "node-style",
            "timers",
            "aui-debounce",
            "aui-promise",
            "aui-parse-content"
        ]
    },
    "aui-surface-screen": {
        "requires": [
            "base-build"
        ]
    },
    "aui-surface-screen-html": {
        "requires": [
            "aui-base",
            "aui-io-request",
            "aui-promise",
            "aui-surface-screen",
            "aui-url"
        ]
    },
    "aui-surface-screen-route": {
        "requires": [
            "base-build"
        ]
    },
    "aui-swf-deprecated": {
        "requires": [
            "querystring-parse-simple",
            "querystring-stringify-simple",
            "aui-base-deprecated"
        ]
    },
    "aui-tabs-data-editor": {
        "requires": [
            "aui-data-editor",
            "aui-tabview"
        ]
    },
    "aui-tabview": {
        "requires": [
            "selector-css3",
            "tabview",
            "aui-component",
            "aui-widget-css"
        ],
        "skinnable": true
    },
    "aui-template-deprecated": {
        "requires": [
            "aui-base-deprecated"
        ]
    },
    "aui-text-data-editor": {
        "requires": [
            "aui-data-editor",
            "event-valuechange"
        ],
        "skinnable": true
    },
    "aui-text-data-unicode": {
        "requires": [
            "text"
        ]
    },
    "aui-text-unicode": {
        "requires": [
            "aui-text-data-unicode"
        ]
    },
    "aui-textboxlist-deprecated": {
        "requires": [
            "anim-node-plugin",
            "aui-autocomplete-deprecated",
            "aui-button-item-deprecated",
            "aui-data-set-deprecated",
            "escape",
            "node-focusmanager"
        ],
        "skinnable": true
    },
    "aui-timepicker": {
        "requires": [
            "autocomplete",
            "aui-datepicker-delegate",
            "aui-datepicker-popover"
        ],
        "skinnable": true
    },
    "aui-timepicker-native": {
        "requires": [
            "base",
            "base-build",
            "aui-node-base",
            "aui-datepicker-delegate",
            "aui-datepicker-native"
        ]
    },
    "aui-timer": {
        "requires": [
            "oop"
        ]
    },
    "aui-toggler": {
        "use": [
            "aui-toggler-base",
            "aui-toggler-delegate"
        ]
    },
    "aui-toggler-accessibility": {
        "requires": [
            "aui-toggler-base"
        ]
    },
    "aui-toggler-base": {
        "requires": [
            "transition",
            "aui-selector",
            "aui-event-base",
            "aui-node",
            "aui-component",
            "event-tap"
        ],
        "skinnable": true
    },
    "aui-toggler-delegate": {
        "requires": [
            "array-invoke",
            "node-event-delegate",
            "aui-toggler-base"
        ]
    },
    "aui-toolbar": {
        "requires": [
            "arraylist",
            "arraylist-add",
            "aui-component",
            "aui-button-core"
        ]
    },
    "aui-tooltip": {
        "use": [
            "aui-tooltip-base",
            "aui-tooltip-delegate"
        ]
    },
    "aui-tooltip-base": {
        "requires": [
            "aui-aria",
            "aui-classnamemanager",
            "aui-component",
            "aui-debounce",
            "aui-node-base",
            "aui-widget-cssclass",
            "aui-widget-toggle",
            "aui-widget-transition",
            "aui-widget-trigger",
            "aui-widget-position-align-suggestion",
            "event-hover",
            "event-resize",
            "escape",
            "widget",
            "widget-autohide",
            "widget-position",
            "widget-position-align",
            "widget-position-constrain",
            "widget-stack",
            "widget-stdmod"
        ],
        "skinnable": true
    },
    "aui-tooltip-delegate": {
        "requires": [
            "aui-tooltip-base",
            "node-event-delegate"
        ]
    },
    "aui-tooltip-deprecated": {
        "requires": [
            "aui-overlay-context-panel-deprecated"
        ],
        "skinnable": true
    },
    "aui-tpl-snippets-base-deprecated": {
        "requires": [
            "aui-template-deprecated"
        ]
    },
    "aui-tpl-snippets-checkbox-deprecated": {
        "requires": [
            "aui-tpl-snippets-base-deprecated"
        ]
    },
    "aui-tpl-snippets-deprecated": {
        "use": [
            "aui-tpl-snippets-base-deprecated",
            "aui-tpl-snippets-checkbox-deprecated",
            "aui-tpl-snippets-input-deprecated",
            "aui-tpl-snippets-select-deprecated",
            "aui-tpl-snippets-textarea-deprecated"
        ]
    },
    "aui-tpl-snippets-input-deprecated": {
        "requires": [
            "aui-tpl-snippets-base-deprecated"
        ]
    },
    "aui-tpl-snippets-select-deprecated": {
        "requires": [
            "aui-tpl-snippets-base-deprecated"
        ]
    },
    "aui-tpl-snippets-textarea-deprecated": {
        "requires": [
            "aui-tpl-snippets-base-deprecated"
        ]
    },
    "aui-tree": {
        "use": [
            "aui-tree-data",
            "aui-tree-io",
            "aui-tree-node",
            "aui-tree-paginator",
            "aui-tree-view"
        ]
    },
    "aui-tree-data": {
        "requires": [
            "aui-base-core",
            "aui-base-lang",
            "aui-node-base",
            "aui-timer",
            "aui-component"
        ]
    },
    "aui-tree-io": {
        "requires": [
            "aui-component",
            "aui-io"
        ]
    },
    "aui-tree-node": {
        "requires": [
            "json",
            "querystring-stringify",
            "aui-tree-data",
            "aui-tree-io",
            "aui-tree-paginator",
            "event-key"
        ]
    },
    "aui-tree-paginator": {
        "requires": [
            "yui-base"
        ]
    },
    "aui-tree-view": {
        "requires": [
            "dd-delegate",
            "dd-proxy",
            "widget",
            "aui-tree-node",
            "aui-tree-paginator",
            "aui-tree-io"
        ],
        "skinnable": true
    },
    "aui-undo-redo": {
        "requires": [
            "aui-base",
            "base",
            "base-build",
            "event-key",
            "promise"
        ]
    },
    "aui-url": {
        "requires": [
            "oop",
            "querystring-parse",
            "querystring-stringify"
        ]
    },
    "aui-video": {
        "requires": [
            "event-resize",
            "node-event-html5",
            "querystring-stringify-simple",
            "aui-aria",
            "aui-node",
            "aui-component",
            "aui-debounce"
        ],
        "skinnable": true
    },
    "aui-viewport": {
        "requires": [
            "aui-node",
            "aui-component"
        ]
    },
    "aui-widget": {
        "use": [
            "aui-widget-cssclass",
            "aui-widget-toolbars"
        ]
    },
    "aui-widget-core": {
        "use": [
            "aui-widget-cssclass"
        ]
    },
    "aui-widget-cssclass": {
        "requires": [
            "widget-base"
        ]
    },
    "aui-widget-position-align-suggestion": {
        "requires": [
            "widget-position-align",
            "widget-stdmod"
        ]
    },
    "aui-widget-responsive": {
        "requires": [
            "event-resize",
            "widget-base"
        ]
    },
    "aui-widget-shortcut": {
        "requires": [
            "base"
        ]
    },
    "aui-widget-swipe": {
        "requires": [
            "classnamemanager",
            "scrollview-base",
            "scrollview-paginator",
            "timers"
        ]
    },
    "aui-widget-toggle": {},
    "aui-widget-toolbars": {
        "requires": [
            "widget-stdmod",
            "aui-toolbar"
        ]
    },
    "aui-widget-transition": {
        "requires": [
            "transition"
        ]
    },
    "aui-widget-trigger": {
        "requires": [
            "node"
        ]
    }
});
YUI.Env[Y.version].md5 = 'd7c627eb00edd6b6f054d8f6e7147480';
/*
 * Alloy JavaScript Library
 * http://alloy.liferay.com/
 *
 * Copyright (c) 2010 Liferay Inc.
 * http://alloy.liferay.com/LICENSE.txt
 *
 * Nate Cavanaugh (nathan.cavanaugh@liferay.com)
 * Eduardo Lundgren (eduardo.lundgren@liferay.com)
 *
 * Attribution/Third-party licenses
 * http://alloy.liferay.com/ATTRIBUTION.txt
 */

// Simple version of
// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/

A.UA.edge = (function() {
    var edgeVersion = A.UA.userAgent.match(/Edge\/(.[0-9.]+)/);

    if (edgeVersion) {
        return edgeVersion[1];
    }

    return 0;
})();

A.supportsDOMEvent = function(domNode, eventName) {
    eventName = 'on' + eventName;

    if (!(eventName in domNode)) {
        if (!domNode.setAttribute) {
            domNode = A.config.doc.createElement('div');
        }

        if (domNode.setAttribute) {
            domNode.setAttribute(eventName, '');
            return (typeof domNode[eventName] === 'function');
        }
    }

    domNode = null;

    return true;
};
(function() {
    var slice = Array.prototype.slice;

    YUI.prototype.ready = function() {
        var instance = this,
            xargs = arguments,
            index = xargs.length - 1,
            modules = slice.call(arguments, 0, index);

        modules.unshift('event-base');
        modules.push(function(instance) {
            var args = arguments;

            instance.on('domready', function() {
                xargs[index].apply(this, args);
            });
        });
        instance.use.apply(instance, modules);
    };
}());


}, '3.1.0-deprecated.76');

YUI.add('aui-classnamemanager', function (A, NAME) {

var ClassNameManager = A.ClassNameManager,
    _getClassName = ClassNameManager.getClassName;

A.getClassName = A.cached(
    function() {
        var args = A.Array(arguments, 0, true);

        args[args.length] = true;

        return _getClassName.apply(ClassNameManager, args);
    }
);


}, '3.1.0-deprecated.76', {"requires": ["classnamemanager"]});

YUI.add('aui-component', function (A, NAME) {

/**
 * The Component Utility
 *
 * @module aui-component
 */

var Lang = A.Lang,
    AArray = A.Array,

    concat = function(arr, arr2) {
        return (arr || []).concat(arr2 || []);
    },

    _INSTANCES = {},
    _CONSTRUCTOR_OBJECT = A.config.win.Object.prototype.constructor,

    ClassNameManager = A.ClassNameManager,

    _getClassName = ClassNameManager.getClassName,
    _getWidgetClassName = A.Widget.getClassName,

    getClassName = A.getClassName,

    CSS_HIDE = getClassName('hide');

/**
 * A base class for `A.Component`, providing:
 *
 * - Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)
 *
 * @class A.Component
 * @extends Widget
 * @uses A.WidgetCssClass, A.WidgetToggle
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 */
var Component = A.Base.create('component', A.Widget, [
        A.WidgetCssClass,
        A.WidgetToggle
    ], {
    initializer: function(config) {
        var instance = this;

        instance._originalConfig = config;

        instance._setRender(config);

        _INSTANCES[instance.get('id')] = instance;
    },

    /**
     * Clone the current `A.Component`.
     *
     * @method clone
     * @param {Object} config
     * @return {Widget} Cloned instance.
     */
    clone: function(config) {
        var instance = this;

        config = config || {};

        config.id = config.id || A.guid();

        A.mix(config, instance._originalConfig);

        return new instance.constructor(config);
    },

    /**
     * Set the visibility on the UI.
     *
     * @method _uiSetVisible
     * @param value
     * @protected
     */
    _uiSetVisible: function(value) {
        var instance = this;

        var superUISetVisible = Component.superclass._uiSetVisible;

        if (superUISetVisible) {
            superUISetVisible.apply(instance, arguments);
        }

        var hideClass = instance.get('hideClass');

        if (hideClass !== false) {
            var boundingBox = instance.get('boundingBox');

            boundingBox.toggleClass(hideClass || CSS_HIDE, !value);
        }
    },

    /**
     * Applies standard class names to the `boundingBox` and `contentBox`.
     *
     * @method _renderBoxClassNames
     * @protected
     */
    _renderBoxClassNames: function() {
        var instance = this;

        var boundingBoxNode = instance.get('boundingBox')._node;
        var contentBoxNode = instance.get('contentBox')._node;

        var boundingBoxNodeClassName = boundingBoxNode.className;
        var contentBoxNodeClassName = contentBoxNode.className;

        var boundingBoxBuffer = (boundingBoxNodeClassName) ? boundingBoxNodeClassName.split(' ') : [];
        var contentBoxBuffer = (contentBoxNodeClassName) ? contentBoxNodeClassName.split(' ') : [];

        var classes = instance._getClasses();

        var classLength = classes.length;

        var auiClassesLength = classLength - 4;

        var classItem;
        var classItemName;

        boundingBoxBuffer.push(_getWidgetClassName());

        for (var i = classLength - 3; i >= 0; i--) {
            classItem = classes[i];

            classItemName = String(classItem.NAME).toLowerCase();

            boundingBoxBuffer.push(classItem.CSS_PREFIX || _getClassName(classItemName));

            if (i <= auiClassesLength) {
                classItemName = classItemName;

                contentBoxBuffer.push(getClassName(classItemName, 'content'));
            }
        }

        contentBoxBuffer.push(instance.getClassName('content'));

        if (boundingBoxNode === contentBoxNode) {
            contentBoxNodeClassName = AArray.dedupe(contentBoxBuffer.concat(boundingBoxBuffer)).join(' ');
        }
        else {
            boundingBoxNode.className = AArray.dedupe(boundingBoxBuffer).join(' ');

            contentBoxNodeClassName = AArray.dedupe(contentBoxBuffer).join(' ');
        }

        contentBoxNode.className = contentBoxNodeClassName;
    },

    /**
     * Renders the `A.Component` based upon a passed in interaction.
     *
     * @method _renderInteraction
     * @param event
     * @param parentNode
     * @protected
     */
    _renderInteraction: function(event, parentNode) {
        var instance = this;

        instance.render(parentNode);

        var renderHandles = instance._renderHandles;

        for (var i = renderHandles.length - 1; i >= 0; i--) {
            var handle = renderHandles.pop();

            handle.detach();
        }
    },

    /**
     * Sets the interaction and render behavior based upon an object (intercepts
     * the default rendering behavior).
     *
     * @method _setRender
     * @param config
     * @protected
     */
    _setRender: function(config) {
        var instance = this;

        var render = config && config.render;

        if (render && render.constructor === _CONSTRUCTOR_OBJECT) {
            var eventType = render.eventType || 'mousemove';
            var parentNode = render.parentNode;
            var selector = render.selector || parentNode;

            if (selector) {
                instance._renderHandles = [];

                var renderHandles = instance._renderHandles;

                if (!Lang.isArray(eventType)) {
                    eventType = [eventType];
                }

                var renderInteraction = A.rbind(instance._renderInteraction, instance, parentNode);

                var interactionNode = A.one(selector);

                for (var i = eventType.length - 1; i >= 0; i--) {
                    renderHandles[i] = interactionNode.once(eventType[i], renderInteraction);
                }

                delete config.render;
            }
        }
    }
}, {
    /**
     * Static property used to define the default attribute configuration for
     * the Component.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {
        /**
         * Indicates if use of the WAI-ARIA Roles and States should be enabled
         * for the Widget.
         *
         * @attribute useARIA
         * @default false
         * @type Boolean
         * @writeOnce
         */
        useARIA: {
            writeOnce: true,
            value: false,
            validator: Lang.isBoolean
        },

        /**
         * CSS class added to hide the `boundingBox` when
         * [visible](A.Component.html#attr_visible) is set to `false`.
         *
         * @attribute hideClass
         * @default 'aui-hide'
         * @type String
         */
        hideClass: {
            value: CSS_HIDE
        },

        /**
         * If `true` the render phase will be autimatically invoked preventing
         * the `.render()` manual call.
         *
         * @attribute render
         * @default false
         * @type Boolean | Node
         * @writeOnce
         */
        render: {
            value: false,
            writeOnce: true
        }
    }
});

/**
 * Static property used to define the map to store Component instances by id.
 *
 * @property _INSTANCES
 * @type Object
 * @static
 */
Component._INSTANCES = _INSTANCES;

/**
 * Gets component's instance by id.
 *
 * @method getById
 * @param id
 */
Component.getById = function(id) {
    return _INSTANCES[id];
};

var DEFAULT_UI_ATTRS = A.Widget.prototype._UI_ATTRS;

/**
 * Applies a CSS prefix on a component.
 *
 * @method _applyCssPrefix
 * @param component
 * @protected
 */
Component._applyCssPrefix = function(component) {
    if (component && component.NAME && !('CSS_PREFIX' in component)) {
        component.CSS_PREFIX = A.getClassName(String(component.NAME).toLowerCase());
    }

    return component;
};

/**
 * Applies standard extensions from a given config to create a new class using
 * the static `Base.build` method.
 *
 * @method create
 * @param config
 */
Component.create = function(config) {
    config = config || {};

    var extendsClass = config.EXTENDS || A.Component;

    var component = config.constructor;

    if (!A.Object.owns(config, 'constructor')) {
        component = function() {
            component.superclass.constructor.apply(this, arguments);
        };
    }

    var configProto = config.prototype;

    if (configProto) {
        if (config.UI_ATTRS || config.BIND_UI_ATTRS || config.SYNC_UI_ATTRS) {
            var BIND_UI_ATTRS = concat(config.BIND_UI_ATTRS, config.UI_ATTRS);
            var SYNC_UI_ATTRS = concat(config.SYNC_UI_ATTRS, config.UI_ATTRS);

            var extendsProto = extendsClass.prototype;
            var extendsUIAttrs = (extendsProto && extendsProto._UI_ATTRS) || DEFAULT_UI_ATTRS;

            BIND_UI_ATTRS = concat(extendsUIAttrs.BIND, BIND_UI_ATTRS);
            SYNC_UI_ATTRS = concat(extendsUIAttrs.SYNC, SYNC_UI_ATTRS);

            var configProtoUIAttrs = configProto._UI_ATTRS;

            if (!configProtoUIAttrs) {
                configProtoUIAttrs = configProto._UI_ATTRS = {};
            }

            if (BIND_UI_ATTRS.length) {
                configProtoUIAttrs.BIND = BIND_UI_ATTRS;
            }

            if (SYNC_UI_ATTRS.length) {
                configProtoUIAttrs.SYNC = SYNC_UI_ATTRS;
            }
        }
    }

    var augmentsClasses = config.AUGMENTS;

    if (augmentsClasses && !Lang.isArray(augmentsClasses)) {
        augmentsClasses = [augmentsClasses];
    }

    A.mix(component, config);

    delete component.prototype;

    A.extend(component, extendsClass, configProto);

    if (augmentsClasses) {
        component = A.Base.build(config.NAME, component, augmentsClasses, {
            dynamic: false
        });
    }

    Component._applyCssPrefix(component);

    return component;
};

/**
 * Static property provides a string to identify the CSS prefix.
 *
 * @property CSS_PREFIX
 * @type String
 * @static
 */
Component.CSS_PREFIX = getClassName('component');

var Base = A.Base;

/**
 * Applies extensions to a class using the static `Base.build` method.
 *
 * @method build
 */
Component.build = function() {
    var component = Base.build.apply(Base, arguments);

    Component._applyCssPrefix(component);

    return component;
};

A.Component = Component;


}, '3.1.0-deprecated.76', {
    "requires": [
        "aui-classnamemanager",
        "aui-widget-cssclass",
        "aui-widget-toggle",
        "base-build",
        "widget-base"
    ]
});

YUI.add('aui-debounce', function (A, NAME) {

var Lang = A.Lang,
    aArray = A.Array,
    isString = Lang.isString,
    isUndefined = Lang.isUndefined,

    DEFAULT_ARGS = [];

var toArray = function(arr, fallback, index, arrayLike) {
    return !isUndefined(arr) ? aArray(arr, index || 0, (arrayLike !== false)) : fallback;
};

A.debounce = function(fn, delay, context, args) {
    var id;
    var tempArgs;
    var wrapped;

    if (isString(fn) && context) {
        fn = A.bind(fn, context);
    }

    delay = delay || 0;

    args = toArray(arguments, DEFAULT_ARGS, 3);

    var clearFn = function() {
        clearInterval(id);

        id = null;
    };

    var base = function() {
        clearFn();

        var result = fn.apply(context, tempArgs || args || DEFAULT_ARGS);

        tempArgs = null;

        return result;
    };

    var delayFn = function(delayTime, newArgs, newContext, newFn) {
        wrapped.cancel();

        delayTime = !isUndefined(delayTime) ? delayTime : delay;

        fn = newFn || fn;
        context = newContext || context;

        if (newArgs !== args) {
            tempArgs = toArray(newArgs, DEFAULT_ARGS, 0, false).concat(args);
        }

        if (delayTime > 0) {
            id = setInterval(base, delayTime);
        }
        else {
            return base();
        }
    };

    var cancelFn = function() {
        if (id) {
            clearFn();
        }
    };

    var setDelay = function(delay) {
        cancelFn();

        delay = delay || 0;
    };

    wrapped = function() {
        var currentArgs = arguments.length ? arguments : args;

        return wrapped.delay(delay, currentArgs, context || this);
    };

    wrapped.cancel = cancelFn;
    wrapped.delay = delayFn;
    wrapped.setDelay = setDelay;

    return wrapped;
};


}, '3.1.0-deprecated.76');

YUI.add('aui-delayed-task-deprecated', function (A, NAME) {

/**
 * The DelayedTask Utility - Executes the supplied function in the context of
 * the supplied object 'when' milliseconds later
 *
 * @module aui-delayed-task
 */

/**
 * A base class for DelayedTask, providing:
 * <ul>
 *    <li>Executes the supplied function in the context of the supplied object 'when' milliseconds later</li>
 * </ul>
 *
 * Quick Example:<br/>
 *
 * <pre><code>var delayed = new A.DelayedTask({
 *	 function() {
 *     // This callback will be executed when the <code>DelayedTask</code> be invoked
 *	 },
 *	 scope
 *  });
 *
 * 	// executes after 1000ms the callback
 *  delayed.delay(1000);
 * </code></pre>
 *
 * Check the list of <a href="DelayedTask.html#configattributes">Configuration Attributes</a> available for
 * DelayedTask.
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class DelayedTask
 * @param {function} fn Callback
 * @param {Object} scope Context object. Optional.
 * @param args 0..n additional arguments that should be provided to the listener.
 * @constructor
 */
var DelayedTask = function(fn, scope, args) {
    var instance = this;

    /**
     * Stores the passed <code>args</code> attribute.
     *
     * @property _args
     * @type Object
     * @protected
     */
    instance._args = args;

    /**
     * Stores the passed <code>delay</code> attribute.
     *
     * @property _delay
     * @default 0
     * @type Number
     * @protected
     */
    instance._delay = 0;

    /**
     * Stores the passed <code>fn</code> attribute.
     *
     * @property _fn
     * @type function
     * @protected
     */
    instance._fn = fn;

    /**
     * Stores the timer <code>id</code> given from the <code>setInterval</code>.
     *
     * @property _id
     * @default null
     * @type Number
     * @protected
     */
    instance._id = null;

    /**
     * Stores the passed <code>scope</code> attribute.
     *
     * @property _scope
     * @default instance
     * @type Object
     * @protected
     */
    instance._scope = scope || instance;

    /**
     * Stores the current timestamp given from
     * <a href="DelayedTask.html#method__getTime">_getTime</a>.
     *
     * @property _time
     * @default 0
     * @type Number
     * @protected
     */
    instance._time = 0;

    instance._base = function() {
        var now = instance._getTime();

        if (now - instance._time >= instance._delay) {
            clearInterval(instance._id);

            instance._id = null;

            instance._fn.apply(instance._scope, instance._args || []);
        }
    };
};

DelayedTask.prototype = {
    /**
     * <p>This function is responsible to execute the user callback, passed in
     * the <code>constructor</code> after <code>delay</code> milliseconds.</p>
     *
     * Example:
     *
     * <pre><code>// executes after 1000ms the callback
     * delayed.delay(1000);</code></pre>
     *
     * @method delay
     * @param {Number} delay Delay in milliseconds.
     * @param {function} newFn Callback.
     * @param {Object} newScope Context object. Optional.
     * @param newArgs 0..n additional arguments that should be provided to the listener.
     */
    delay: function(delay, newFn, newScope, newArgs) {
        var instance = this;

        if (instance._id && instance._delay != delay) {
            instance.cancel();
        }

        instance._delay = delay || instance._delay;
        instance._time = instance._getTime();

        instance._fn = newFn || instance._fn;
        instance._scope = newScope || instance._scope;
        instance._args = newArgs || instance._args;

        if (!A.Lang.isArray(instance._args)) {
            instance._args = [instance._args];
        }

        if (!instance._id) {
            if (instance._delay > 0) {
                instance._id = setInterval(instance._base, instance._delay);
            }
            else {
                instance._base();
            }
        }
    },

    /**
     * Cancel the delayed task in case it's running (i.e., clearInterval from
     * the current running <a href="DelayedTask.html#property__id">_id</a>).
     *
     * @method cancel
     */
    cancel: function() {
        var instance = this;

        if (instance._id) {
            clearInterval(instance._id);

            instance._id = null;
        }
    },

    /**
     * Get the current timestamp (i.e., now).
     *
     * @method _getTime
     * @protected
     * @return {Number} Current timestamp
     */
    _getTime: function() {
        var instance = this;

        return (+new Date());
    }
};

A.DelayedTask = DelayedTask;


}, '3.1.0-deprecated.76', {"requires": ["yui-base"]});

YUI.add('aui-event-base', function (A, NAME) {

/**
 * The Event Base.
 *
 * @module aui-event
 * @submodule aui-event-base
 */

var aArray = A.Array,
    DOMEventFacade = A.DOMEventFacade,
    DOMEventFacadeProto = DOMEventFacade.prototype;

var KeyMap = {
    BACKSPACE: 8,
    TAB: 9,
    NUM_CENTER: 12,

    ENTER: 13,
    RETURN: 13,

    SHIFT: 16,
    CTRL: 17,
    ALT: 18,

    PAUSE: 19,
    CAPS_LOCK: 20,
    ESC: 27,
    SPACE: 32,

    PAGE_UP: 33,
    PAGE_DOWN: 34,

    END: 35,
    HOME: 36,

    LEFT: 37,
    UP: 38,
    RIGHT: 39,
    DOWN: 40,

    PRINT_SCREEN: 44,
    INSERT: 45,
    DELETE: 46,

    ZERO: 48,
    ONE: 49,
    TWO: 50,
    THREE: 51,
    FOUR: 52,
    FIVE: 53,
    SIX: 54,
    SEVEN: 55,
    EIGHT: 56,
    NINE: 57,

    A: 65,
    B: 66,
    C: 67,
    D: 68,
    E: 69,
    F: 70,
    G: 71,
    H: 72,
    I: 73,
    J: 74,
    K: 75,
    L: 76,
    M: 77,
    N: 78,
    O: 79,
    P: 80,
    Q: 81,
    R: 82,
    S: 83,
    T: 84,
    U: 85,
    V: 86,
    W: 87,
    X: 88,
    Y: 89,
    Z: 90,

    CONTEXT_MENU: 93,

    NUM_ZERO: 96,
    NUM_ONE: 97,
    NUM_TWO: 98,
    NUM_THREE: 99,
    NUM_FOUR: 100,
    NUM_FIVE: 101,
    NUM_SIX: 102,
    NUM_SEVEN: 103,
    NUM_EIGHT: 104,
    NUM_NINE: 105,

    NUM_MULTIPLY: 106,
    NUM_PLUS: 107,
    NUM_MINUS: 109,
    NUM_PERIOD: 110,
    NUM_DIVISION: 111,

    F1: 112,
    F2: 113,
    F3: 114,
    F4: 115,
    F5: 116,
    F6: 117,
    F7: 118,
    F8: 119,
    F9: 120,
    F10: 121,
    F11: 122,
    F12: 123,

    NUM_LOCK: 144,

    WIN_KEY: 224,
    WIN_IME: 229,

    NON_MODIFYING_KEYS: [
        'ALT',
        'CAPS_LOCK',
        'CTRL',
        'DOWN',
        'END',
        'ESC',
        'F1',
        'F10',
        'F11',
        'F12',
        'F2',
        'F3',
        'F4',
        'F5',
        'F6',
        'F7',
        'F8',
        'F9',
        'HOME',
        'LEFT',
        'NUM_LOCK',
        'PAGE_DOWN',
        'PAGE_UP',
        'PAUSE',
        'PRINT_SCREEN',
        'RIGHT',
        'SHIFT',
        'SPACE',
        'UP',
        'WIN_KEY'
    ],

    hasModifier: function(event) {
        return event &&
            (event.ctrlKey ||
            event.altKey ||
            event.shiftKey ||
            event.metaKey);
    },

    isKey: function(keyCode, name) {
        var instance = this;

        return name && ((instance[name] || instance[name.toUpperCase()]) === keyCode);
    },

    isKeyInRange: function(keyCode, start, end) {
        var instance = this;

        var result = false;

        if (start && end) {
            var startKey = instance[start] || instance[start.toUpperCase()];
            var endKey = instance[end] || instance[end.toUpperCase()];

            result = startKey && endKey &&
                (keyCode >= startKey && keyCode <= endKey);
        }

        return result;
    },

    isKeyInSet: function(keyCode) {
        var instance = this;

        var args = aArray(arguments, 1, true);

        return instance._isKeyInSet(keyCode, args);
    },

    isNavKey: function(keyCode) {
        var instance = this;

        return instance.isKeyInRange(keyCode, 'PAGE_UP', 'DOWN') || instance.isKeyInSet(keyCode, 'ENTER', 'TAB', 'ESC');
    },

    isSpecialKey: function(keyCode, eventType) {
        var instance = this;

        var isCtrlPress = (eventType === 'keypress' && instance.ctrlKey);

        return isCtrlPress ||
            instance.isNavKey(keyCode) ||
            instance.isKeyInRange(keyCode, 'SHIFT', 'CAPS_LOCK') ||
            instance.isKeyInSet(keyCode, 'BACKSPACE', 'PRINT_SCREEN', 'INSERT', 'WIN_IME');
    },

    isModifyingKey: function(keyCode) {
        var instance = this;

        return !instance._isKeyInSet(keyCode, instance.NON_MODIFYING_KEYS);
    },

    _isKeyInSet: function(keyCode, arr) {
        var instance = this;

        var i = arr.length;

        var result = false;

        var keyName;
        var key;

        while (i--) {
            keyName = arr[i];
            key = keyName && (instance[keyName] || instance[String(keyName).toUpperCase()]);

            if (keyCode === key) {
                result = true;

                break;
            }
        }

        return result;
    }
};

A.mix(
    DOMEventFacadeProto, {
        /**
         * Checks if an event is triggered by a keyboard key like `CTRL`, `ALT`
         * or `SHIFT`.
         *
         * @method hasModifier
         * @return {Boolean}
         */
        hasModifier: function() {
            var instance = this;

            return KeyMap.hasModifier(instance);
        },

        /**
         * Checks if an event is triggered by a keyboard key.
         *
         * @method isKey
         * @param name
         * @return {Boolean}
         */
        isKey: function(name) {
            var instance = this;

            return KeyMap.isKey(instance.keyCode, name);
        },

        /**
         * Checks if an event is triggered by a keyboard key located between two
         * other keys.
         *
         * @method isKeyInRange
         * @param start
         * @param end
         * @return {Boolean}
         */
        isKeyInRange: function(start, end) {
            var instance = this;

            return KeyMap.isKeyInRange(instance.keyCode, start, end);
        },

        /**
         * Checks if an event is triggered by a keyboard key contained in the
         * key set.
         *
         * @method isKeyInSet
         * @return {Boolean}
         */
        isKeyInSet: function() {
            var instance = this;

            var args = aArray(arguments, 0, true);

            return KeyMap._isKeyInSet(instance.keyCode, args);
        },

        /**
         * Checks if an event is triggered by `ENTER`, `TAB`, `ESC` keyboard
         * keys or by a key located between `PAGE UP` and `DOWN`.
         *
         * @method isModifyingKey
         */
        isModifyingKey: function() {
            var instance = this;

            return KeyMap.isModifyingKey(instance.keyCode);
        },

        /**
         * Checks if an event is triggered by navigation keys like `PAGE UP`
         * and `DOWN` keys.
         *
         * @method isNavKey
         * @return {Boolean}
         */
        isNavKey: function() {
            var instance = this;

            return KeyMap.isNavKey(instance.keyCode);
        },

        /**
         * Checks if an event is triggered by a special keyboard key like
         * `SHIFT`, `CAPS LOCK`, etc.
         *
         * @method isSpecialKey
         * @return {Boolean}
         */
        isSpecialKey: function() {
            var instance = this;

            return KeyMap.isSpecialKey(instance.keyCode, instance.type);
        }
    }
);

A.Event.KeyMap = KeyMap;

A.Event.supportsDOMEvent = A.supportsDOMEvent;


}, '3.1.0-deprecated.76', {"requires": ["event-base"]});

YUI.add('aui-event-input', function (A, NAME) {

/**
 * An object that encapsulates text changed events for textareas and input
 * element of type text and password. This event only occurs when the element
 * is focused.
 *
 * @module aui-event
 * @submodule aui-event-input
 */

var DOM_EVENTS = A.Node.DOM_EVENTS;

// Input event feature check should be done on textareas. WebKit before
// version 531 (3.0.182.2) did not support input events for textareas.
// See http://dev.chromium.org/developers/webkit-version-table
if (A.Features.test('event', 'input')) {
    // http://yuilibrary.com/projects/yui3/ticket/2533063
    DOM_EVENTS.input = 1;
    return;
}

DOM_EVENTS.cut = 1;
DOM_EVENTS.dragend = 1;
DOM_EVENTS.paste = 1;

var KeyMap = A.Event.KeyMap,

    _HANDLER_DATA_KEY = '~~aui|input|event~~',
    _INPUT_EVENT_TYPE = ['keydown', 'paste', 'drop', 'cut'],
    _SKIP_FOCUS_CHECK_MAP = {
        cut: 1,
        drop: 1,
        paste: 1
    };

/**
 * Defines a new `input` event in the DOM event system.
 *
 * @event input
 */
A.Event.define('input', {

    /**
     * Implementation logic for event subscription.
     *
     * @method on
     * @param node
     * @param subscription
     * @param notifier
     */
    on: function(node, subscription, notifier) {
        var instance = this;

        subscription._handler = node.on(
            _INPUT_EVENT_TYPE, A.bind(instance._dispatchEvent, instance, subscription, notifier));
    },

    /**
     * Implementation logic for subscription via `node.delegate`.
     *
     * @method delegate
     * @param node
     * @param subscription
     * @param notifier
     * @param filter
     */
    delegate: function(node, subscription, notifier, filter) {
        var instance = this;

        subscription._handles = [];
        subscription._handler = node.delegate('focus', function(event) {
            var element = event.target,
                handler = element.getData(_HANDLER_DATA_KEY);

            if (!handler) {
                handler = element.on(
                    _INPUT_EVENT_TYPE,
                    A.bind(instance._dispatchEvent, instance, subscription, notifier));

                subscription._handles.push(handler);
                element.setData(_HANDLER_DATA_KEY, handler);
            }
        }, filter);
    },

    /**
     * Implementation logic for cleaning up a detached subscription.
     *
     * @method detach
     * @param node
     * @param subscription
     * @param notifier
     */
    detach: function(node, subscription) {
        subscription._handler.detach();
    },

    /**
     * Implementation logic for cleaning up a detached delegate subscription.
     *
     * @method detachDelegate
     * @param node
     * @param subscription
     * @param notifier
     */
    detachDelegate: function(node, subscription) {
        A.Array.each(subscription._handles, function(handle) {
            var element = A.one(handle.evt.el);
            if (element) {
                element.setData(_HANDLER_DATA_KEY, null);
            }
            handle.detach();
        });
        subscription._handler.detach();
    },

    /**
     * Dispatches an `input` event.
     *
     * @method _dispatchEvent
     * @param subscription
     * @param notifier
     * @param event
     * @protected
     */
    _dispatchEvent: function(subscription, notifier, event) {
        var instance = this,
            input,
            valueBeforeKey;

        input = event.target;

        // Since cut, drop and paste events fires before the element is focused,
        // skip focus checking.
        if (_SKIP_FOCUS_CHECK_MAP[event.type] ||
            (input.get('ownerDocument').get('activeElement') === input)) {

            if (KeyMap.isModifyingKey(event.keyCode)) {
                if (subscription._timer) {
                    subscription._timer.cancel();
                    subscription._timer = null;
                }

                valueBeforeKey = KeyMap.isKey(event.keyCode, 'WIN_IME') ? null : input.get('value');

                subscription._timer = A.soon(
                    A.bind('_fireEvent', instance, subscription, notifier, event, valueBeforeKey)
                );
            }
        }
    },

    /**
     * Fires an event.
     *
     * @method _fireEvent
     * @param subscription
     * @param notifier
     * @param event
     * @param valueBeforeKey
     * @protected
     */
    _fireEvent: function(subscription, notifier, event, valueBeforeKey) {
        var input = event.target;

        subscription._timer = null;

        if (input.get('value') !== valueBeforeKey) {
            notifier.fire(event);
        }
    }
});


}, '3.1.0-deprecated.76', {"requires": ["aui-event-base", "event-delegate", "event-synthetic", "timers"]});

YUI.add('aui-form-validator', function (A, NAME) {

/**
 * The Form Validator Component
 *
 * @module aui-form-validator
 */

// API inspired on the amazing jQuery Form Validation -
// http://jquery.bassistance.de/validate/

var Lang = A.Lang,
    AObject = A.Object,
    isBoolean = Lang.isBoolean,
    isDate = Lang.isDate,
    isEmpty = AObject.isEmpty,
    isFunction = Lang.isFunction,
    isNode = Lang.isNode,
    isObject = Lang.isObject,
    isString = Lang.isString,
    trim = Lang.trim,

    defaults = A.namespace('config.FormValidator'),

    getRegExp = A.DOM._getRegExp,

    getCN = A.getClassName,

    CSS_FORM_GROUP = getCN('form', 'group'),
    CSS_HAS_ERROR = getCN('has', 'error'),
    CSS_ERROR_FIELD = getCN('error', 'field'),
    CSS_HAS_SUCCESS = getCN('has', 'success'),
    CSS_SUCCESS_FIELD = getCN('success', 'field'),
    CSS_HELP_BLOCK = getCN('help', 'block'),
    CSS_STACK = getCN('form-validator', 'stack'),

    TPL_MESSAGE = '<div role="alert"></div>',
    TPL_STACK_ERROR = '<div class="' + [CSS_STACK, CSS_HELP_BLOCK].join(' ') + '"></div>';

if (!Element.prototype.matches) {
    Element.prototype.matches = Element.prototype.msMatchesSelector;
}

A.mix(defaults, {
    STRINGS: {
        DEFAULT: 'Please fix {field}.',
        acceptFiles: 'Please enter a value with a valid extension ({0}) in {field}.',
        alpha: 'Please enter only alpha characters in {field}.',
        alphanum: 'Please enter only alphanumeric characters in {field}.',
        date: 'Please enter a valid date in {field}.',
        digits: 'Please enter only digits in {field}.',
        email: 'Please enter a valid email address in {field}.',
        equalTo: 'Please enter the same value again in {field}.',
        iri: 'Please enter a valid IRI in {field}.',
        max: 'Please enter a value less than or equal to {0} in {field}.',
        maxLength: 'Please enter no more than {0} characters in {field}.',
        min: 'Please enter a value greater than or equal to {0} in {field}.',
        minLength: 'Please enter at least {0} characters in {field}.',
        number: 'Please enter a valid number in {field}.',
        range: 'Please enter a value between {0} and {1} in {field}.',
        rangeLength: 'Please enter a value between {0} and {1} characters long in {field}.',
        required: '{field} is required.',
        url: 'Please enter a valid URL in {field}.'
    },

    REGEX: {
        alpha: /^[a-z_]+$/i,

        alphanum: /^\w+$/,

        digits: /^\d+$/,

        // Regex from Scott Gonzalez Email Address Validation:
        // http://projects.scottsplayground.com/email_address_validation/
        email: new RegExp('^((([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|' +
            '[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#' +
            '\\$%&\'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF' +
            '\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20' +
            '|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\' +
            'x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])' +
            '|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-' +
            '\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\' +
            'x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\' +
            'uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\' +
            'uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\' +
            'uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\' +
            'uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\' +
            'uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\' +
            'uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\' +
            'u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\' +
            'u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$', 'i'),

        // Regex from Scott Gonzalez IRI:
        // http://projects.scottsplayground.com/iri/demo/
        iri: new RegExp('^([a-z]([a-z]|\\d|\\+|-|\\.)*):(\\/\\/(((([a-z]|\\d|' +
            '-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[' +
            '\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?((\\[(|(v[\\da-f]{1' +
            ',}\\.(([a-z]|\\d|-|\\.|_|~)|[!\\$&\'\\(\\)\\*\\+,;=]|:)+))\\])' +
            '|((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1' +
            '\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d' +
            '|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|' +
            '(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-' +
            '\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=])*)(:\\d*)?)' +
            '(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\' +
            'uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)' +
            '*|(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\' +
            'uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)+' +
            '(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\' +
            'uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|' +
            '@)*)*)?)|((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\' +
            'uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\' +
            '+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\' +
            'uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\' +
            '(\\)\\*\\+,;=]|:|@)*)*)|((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\' +
            'uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\' +
            '$&\'\\(\\)\\*\\+,;=]|:|@)){0})(\\?((([a-z]|\\d|-|\\.|_|~|' +
            '[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]' +
            '{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|' +
            '\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\' +
            'uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\' +
            '+,;=]|:|@)|\\/|\\?)*)?$', 'i'),

        number: /^[+\-]?(\d+([.,]\d+)?)+([eE][+-]?\d+)?$/,

        // Regex from Scott Gonzalez Common URL:
        // http://projects.scottsplayground.com/iri/demo/common.html
        url: new RegExp('^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\' +
            'u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})' +
            '|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|' +
            '2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25' +
            '[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.' +
            '(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d' +
            '|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\' +
            'd|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|' +
            '-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*' +
            '([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\' +
            '.)*(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|' +
            '(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]' +
            '|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])' +
            '*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)' +
            '(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\' +
            'uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]' +
            '|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF' +
            '\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)' +
            '*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\' +
            'uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|' +
            ':|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|' +
            '[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})' +
            '|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$', 'i')
    },

    RULES: {
        acceptFiles: function(val, node, ruleValue) {
            var regex = null;

            if (isString(ruleValue)) {
                var extensions = ruleValue.replace(/\./g, '').split(/,\s*|\b\s*/);

                extensions = A.Array.map(extensions, A.Escape.regex);

                regex = getRegExp('[.](' + extensions.join('|') + ')$', 'i');
            }

            return regex && regex.test(val);
        },

        date: function(val) {
            var date = new Date(val);

            return (isDate(date) && (date !== 'Invalid Date') && !isNaN(date));
        },

        equalTo: function(val, node, ruleValue) {
            var comparator = A.one(ruleValue);

            return comparator && (trim(comparator.val()) === val);
        },

        hasValue: function(val, node) {
            var instance = this;

            if (A.FormValidator.isCheckable(node)) {
                var name = node.get('name'),
                    elements = A.all(instance.getFieldsByName(name));

                return (elements.filter(':checked').size() > 0);
            }
            else {
                return !!val;
            }
        },

        max: function(val, node, ruleValue) {
            return (Lang.toFloat(val) <= ruleValue);
        },

        maxLength: function(val, node, ruleValue) {
            return (val.length <= ruleValue);
        },

        min: function(val, node, ruleValue) {
            return (Lang.toFloat(val) >= ruleValue);
        },

        minLength: function(val, node, ruleValue) {
            return (val.length >= ruleValue);
        },

        range: function(val, node, ruleValue) {
            var num = Lang.toFloat(val);

            return (num >= ruleValue[0]) && (num <= ruleValue[1]);
        },

        rangeLength: function(val, node, ruleValue) {
            var length = val.length;

            return (length >= ruleValue[0]) && (length <= ruleValue[1]);
        },

        required: function(val, node, ruleValue) {
            var instance = this;

            if (ruleValue === true) {
                return defaults.RULES.hasValue.apply(instance, [val, node]);
            }
            else {
                return true;
            }
        }
    }
});

/**
 * A base class for `A.FormValidator`.
 *
 * @class A.FormValidator
 * @extends Base
 * @param {Object} config Object literal specifying widget configuration
 *     properties.
 * @constructor
 * @include http://alloyui.com/examples/form-validator/basic-markup.html
 * @include http://alloyui.com/examples/form-validator/basic.js
 */
var FormValidator = A.Component.create({

    /**
     * Static property provides a string to identify the class.
     *
     * @property NAME
     * @type String
     * @static
     */
    NAME: 'form-validator',

    /**
     * Static property used to define the default attribute
     * configuration for the `A.FormValidator`.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    ATTRS: {

        /**
         * The widget's outermost node, used for sizing and positioning.
         *
         * @attribute boundingBox
         */
        boundingBox: {
            setter: A.one
        },

        /**
         * Container for the CSS error class.
         *
         * @attribute containerErrorClass
         * @type String
         */
        containerErrorClass: {
            value: CSS_HAS_ERROR,
            validator: isString
        },

        /**
         * Container for the CSS valid class.
         *
         * @attribute containerValidClass
         * @type String
         */
        containerValidClass: {
            value: CSS_HAS_SUCCESS,
            validator: isString
        },

        /**
         * Defines the CSS error class.
         *
         * @attribute errorClass
         * @type String
         */
        errorClass: {
            value: CSS_ERROR_FIELD,
            validator: isString
        },

        /**
         * If `true` the validation rules are extracted from the DOM.
         *
         * @attribute extractRules
         * @default true
         * @type Boolean
         */
        extractRules: {
            value: true,
            validator: isBoolean
        },

        /**
         * Container for a field.
         *
         * @attribute fieldContainer
         * @type String
         */
        fieldContainer: {
            value: '.' + CSS_FORM_GROUP
        },

        /**
         * Collection of strings used on a field.
         *
         * @attribute fieldStrings
         * @default {}
         * @type Object
         */
        fieldStrings: {
            value: {},
            validator: isObject
        },

        /**
         * The CSS class for `<label>`.
         *
         * @attribute labelCssClass
         * @default 'control-label'
         * @type String
         */
        labelCssClass: {
            validator: isString,
            value: 'control-label'
        },

        /**
         * Container for the form message.
         *
         * @attribute messageContainer
         * @default '<div role="alert"></div>'
         */
        messageContainer: {
            getter: function(val) {
                return A.Node.create(val).clone();
            },
            value: TPL_MESSAGE
        },

        /**
         * Collection of rules to validate fields.
         *
         * @attribute rules
         * @default {}
         * @type Object
         */
        rules: {
            getter: function(val) {
                var instance = this;
                if (!instance._rulesAlreadyExtracted) {
                    instance._extractRulesFromMarkup(val);
                }
                return val;
            },
            validator: isObject,
            value: {}
        },

        /**
         * Defines if the text will be selected or not after validation.
         *
         * @attribute selectText
         * @default true
         * @type Boolean
         */
        selectText: {
            value: true,
            validator: isBoolean
        },

        /**
         * Defines if the validation messages will be showed or not.
         *
         * @attribute showMessages
         * @default true
         * @type Boolean
         */
        showMessages: {
            value: true,
            validator: isBoolean
        },

        /**
         * Defines if all validation messages will be showed or not.
         *
         * @attribute showAllMessages
         * @default false
         * @type Boolean
         */
        showAllMessages: {
            value: false,
            validator: isBoolean
        },

        /**
         * List of CSS selectors for targets that will not get validated
         *
         * @attribute skipValidationTargetSelectors
         * @default 'a[class=btn-cancel'
         */
        skipValidationTargetSelector: {
            value: 'a[class~=btn-cancel]'
        },

        /**
         * Defines a container for the stack errors.
         *
         * @attribute stackErrorContainer
         */
        stackErrorContainer: {
            getter: function(val) {
                return A.Node.create(val).clone();
            },
            value: TPL_STACK_ERROR
        },

        /**
         * Collection of strings used to label elements of the UI.
         *
         * @attribute strings
         * @type Object
         */
        strings: {
            valueFn: function() {
                return defaults.STRINGS;
            }
        },

        /**
         * If `true` the field will be validated on blur event.
         *
         * @attribute validateOnBlur
         * @default true
         * @type Boolean
         */
        validateOnBlur: {
            value: true,
            validator: isBoolean
        },

        /**
         * If `true` the field will be validated on input event.
         *
         * @attribute validateOnInput
         * @default false
         * @type Boolean
         */
        validateOnInput: {
            value: false,
            validator: isBoolean
        },

        /**
         * Defines the CSS valid class.
         *
         * @attribute validClass
         * @type String
         */
        validClass: {
            value: CSS_SUCCESS_FIELD,
            validator: isString
        }
    },

    /**
     * Creates custom rules from user input.
     *
     * @method _setCustomRules
     * @param object
     * @protected
     */
    _setCustomRules: function(object) {
        A.each(
            object,
            function(rule, fieldName) {
                A.config.FormValidator.RULES[fieldName] = rule.condition;
                A.config.FormValidator.STRINGS[fieldName] = rule.errorMessage;
            }
        );
    },

    /**
     * Ability to add custom validation rules.
     *
     * @method customRules
     * @param object
     * @public
     * @static
     */
    addCustomRules: function(object) {
        var instance = this;

        if (isObject(object)) {
            instance._setCustomRules(object);
        }
    },

    /**
     * Checks if a node is a checkbox or radio input.
     *
     * @method isCheckable
     * @param node
     * @private
     * @return {Boolean}
     */
    isCheckable: function(node) {
        var nodeType = node.get('type').toLowerCase();

        return (nodeType === 'checkbox' || nodeType === 'radio');
    },

    /**
     * Static property used to define which component it extends.
     *
     * @property EXTENDS
     * @type Object
     * @static
     */
    EXTENDS: A.Base,

    prototype: {

        /**
         * Construction logic executed during `A.FormValidator` instantiation.
         * Lifecycle.
         *
         * @method initializer
         * @protected
         */
        initializer: function() {
            var instance = this;

            instance.errors = {};
            instance._blurHandlers = null;
            instance._fileBlurHandlers = null;
            instance._fileInputHandlers = null;
            instance._inputHandlers = null;
            instance._rulesAlreadyExtracted = false;
            instance._stackErrorContainers = {};

            instance.bindUI();
            instance._uiSetValidateOnBlur(instance.get('validateOnBlur'));
            instance._uiSetValidateOnInput(instance.get('validateOnInput'));
        },

        /**
         * Bind the events on the `A.FormValidator` UI. Lifecycle.
         *
         * @method bindUI
         * @protected
         */
        bindUI: function() {
            var instance = this,
                boundingBox = instance.get('boundingBox');

            var onceFocusHandler = boundingBox.delegate('focus', function() {
                instance._setARIARoles();
                onceFocusHandler.detach();
            }, 'input,select,textarea,button');

            instance.publish({
                errorField: {
                    defaultFn: instance._defErrorFieldFn
                },
                validField: {
                    defaultFn: instance._defValidFieldFn
                },
                validateField: {
                    defaultFn: instance._defValidateFieldFn
                }
            });

            boundingBox.on({
                reset: A.bind(instance._onFormReset, instance),
                submit: A.bind(instance._onFormSubmit, instance)
            });

            instance.after({
                extractRulesChange: instance._afterExtractRulesChange,
                validateOnBlurChange: instance._afterValidateOnBlurChange,
                validateOnInputChange: instance._afterValidateOnInputChange
            });
        },

        /**
         * Adds a validation error in the field.
         *
         * @method addFieldError
         * @param {Node} field
         * @param ruleName
         */
        addFieldError: function(field, ruleName) {
            var instance = this,
                errors = instance.errors,
                name = field.get('name');

            if (!errors[name]) {
                errors[name] = [];
            }

            errors[name].push(ruleName);
        },

        /**
         * Deletes the field from the errors property object.
         *
         * @method clearFieldError
         * @param {Node|String} field
         */
        clearFieldError: function(field) {
            var fieldName = isNode(field) ? field.get('name') : field;

            if (isString(fieldName)) {
                delete this.errors[fieldName];
            }
        },

        /**
         * Executes a function to each rule.
         *
         * @method eachRule
         * @param fn
         */
        eachRule: function(fn) {
            var instance = this;

            A.each(
                instance.get('rules'),
                function(rule, fieldName) {
                    if (isFunction(fn)) {
                        fn.apply(instance, [rule, fieldName]);
                    }
                }
            );
        },

        /**
         * Gets the ancestor of a given field.
         *
         * @method findFieldContainer
         * @param {Node} field
         * @return {Node}
         */
        findFieldContainer: function(field) {
            var instance = this,
                fieldContainer = instance.get('fieldContainer');

            if (fieldContainer) {
                return field.ancestor(fieldContainer);
            }
        },

        /**
         * Focus on the invalid field.
         *
         * @method focusInvalidField
         */
        focusInvalidField: function() {
            var instance = this,
                boundingBox = instance.get('boundingBox'),
                field = boundingBox.one('.' + CSS_ERROR_FIELD);

            if (field) {
                field = instance.findFieldContainer(field);

                if (instance.get('selectText')) {
                    field.selectText();
                }

                field.focus();

                field.scrollIntoView(false);

                window.scrollBy(0, field.getDOM().scrollHeight);
            }
        },

        /**
         * Gets a field from the form.
         *
         * @method getField
         * @param {Node|String} field
         * @return {Node}
         */
        getField: function(field) {
            var instance = this;

            if (isString(field)) {
                field = instance.getFieldsByName(field);

                if (field && field.length && !field.name) {
                    field = field[0];
                }
            }

            return A.one(field);
        },

        /**
         * Gets a list of fields based on its name.
         *
         * @method getFieldsByName
         * @param fieldName
         * @return {NodeList}
         */
        getFieldsByName: function(fieldName) {
            var instance = this,
                domBoundingBox = instance.get('boundingBox').getDOM();

            return domBoundingBox.elements[fieldName];
        },

        /**
         * Gets a list of fields with errors.
         *
         * @method getFieldError
         * @param {Node} field
         * @return {String}
         */
        getFieldError: function(field) {
            var instance = this;

            return instance.errors[field.get('name')];
        },

        /**
         * Gets the stack error container of a field.
         *
         * @method getFieldStackErrorContainer
         * @param {Node|String} field
         * @return {Node}
         */
        getFieldStackErrorContainer: function(field) {
            var instance = this,
                name = isNode(field) ? field.get('name') : field,
                stackContainers = instance._stackErrorContainers;

            if (!stackContainers[name]) {
                stackContainers[name] = instance.get('stackErrorContainer');
            }

            return stackContainers[name];
        },

        /**
         * Gets the error message of a field.
         *
         * @method getFieldErrorMessage
         * @param {Node} field
         * @param rule
         * @return {String}
         */
        getFieldErrorMessage: function(field, rule) {
            var instance = this,
                fieldName = field.get('name'),
                fieldStrings = instance.get('fieldStrings')[fieldName] || {},
                fieldRules = instance.get('rules')[fieldName],
                fieldLabel = instance._findFieldLabel(field),
                strings = instance.get('strings'),
                substituteRulesMap = {};

            if (fieldLabel) {
                substituteRulesMap.field = fieldLabel;
            }

            if (rule in fieldRules) {
                var ruleValue = A.Array(fieldRules[rule]);

                A.each(
                    ruleValue,
                    function(value, index) {
                        substituteRulesMap[index] = [value].join('');
                    }
                );
            }

            var message = (fieldStrings[rule] || strings[rule] || strings.DEFAULT);

            return Lang.sub(message, substituteRulesMap);
        },

        /**
         * Returns `true` if there are errors.
         *
         * @method hasErrors
         * @return {Boolean}
         */
        hasErrors: function() {
            var instance = this;

            return !isEmpty(instance.errors);
        },

        /**
         * Highlights a field with error or success.
         *
         * @method highlight
         * @param {Node} field
         * @param valid
         */
        highlight: function(field, valid) {
            var instance = this,
                fieldContainer,
                fieldName,
                namedFieldNodes;

            if (field) {
                fieldContainer = instance.findFieldContainer(field);

                fieldName = field.get('name');

                if (this.validatable(field)) {
                    namedFieldNodes = A.all(instance.getFieldsByName(fieldName));

                    namedFieldNodes.each(
                        function(node) {
                            instance._highlightHelper(
                                node,
                                instance.get('errorClass'),
                                instance.get('validClass'),
                                valid
                            );
                        }
                    );

                    if (fieldContainer) {
                        instance._highlightHelper(
                            fieldContainer,
                            instance.get('containerErrorClass'),
                            instance.get('containerValidClass'),
                            valid
                        );
                    }
                }
                else if (!field.val()) {
                    instance.resetField(fieldName);
                }
            }
        },

        /**
         * Normalizes rule value.
         *
         * @method normalizeRuleValue
         * @param ruleValue
         * @param {Node} field
         */
        normalizeRuleValue: function(ruleValue, field) {
            var instance = this;

            return isFunction(ruleValue) ? ruleValue.apply(instance, [field]) : ruleValue;
        },

        /**
         * Removes the highlight of a field.
         *
         * @method unhighlight
         * @param {Node} field
         */
        unhighlight: function(field) {
            var instance = this;

            instance.highlight(field, true);
        },

        /**
         * Prints the stack error messages into a container.
         *
         * @method printStackError
         * @param {Node} field
         * @param {Node} container
         * @param {Array} errors
         */
        printStackError: function(field, container, errors) {
            var instance = this;

            if (!instance.get('showAllMessages')) {
                if (A.Array.indexOf(errors, 'required') !== -1) {
                    errors = ['required'];
                }
                else {
                    errors = errors.slice(0, 1);
                }
            }

            container.empty();

            A.Array.each(
                errors,
                function(error) {
                    var message = instance.getFieldErrorMessage(field, error),
                        messageEl = instance.get('messageContainer').addClass(error);

                    container.append(
                        messageEl.html(message)
                    );
                }
            );
        },

        /**
         * Resets the CSS class and content of all fields.
         *
         * @method resetAllFields
         */
        resetAllFields: function() {
            var instance = this;

            instance.eachRule(
                function(rule, fieldName) {
                    instance.resetField(fieldName);
                }
            );
        },

        /**
         * Resets the CSS class and error status of a field.
         *
         * @method resetField
         * @param {Node|String} field
         */
        resetField: function(field) {
            var instance = this,
                fieldName,
                fieldRules,
                namedFieldNodes,
                stackContainer;

            fieldName = isNode(field) ? field.get('name') : field;

            if (fieldName) {
                fieldRules = instance.get('rules')[fieldName];

                if (fieldRules) {
                    instance.clearFieldError(fieldName);

                    stackContainer = instance.getFieldStackErrorContainer(fieldName);

                    stackContainer.remove();

                    namedFieldNodes = A.all(instance.getFieldsByName(fieldName));

                    namedFieldNodes.each(
                        function(node) {
                            instance.resetFieldCss(node);
                            node.removeAttribute('aria-errormessage');
                            node.removeAttribute('aria-invalid');
                        }
                    );
                }
            }
        },

        /**
         * Removes the CSS classes of a field.
         *
         * @method resetFieldCss
         * @param {Node} field
         */
        resetFieldCss: function(field) {
            var instance = this,
                fieldContainer = instance.findFieldContainer(field);

            var removeClasses = function(elem, classAttrs) {
                if (elem) {
                    A.each(classAttrs, function(attrName) {
                        elem.removeClass(
                            instance.get(attrName)
                        );
                    });
                }
            };

            removeClasses(field, ['validClass', 'errorClass']);
            removeClasses(fieldContainer, ['containerValidClass', 'containerErrorClass']);
        },

        /**
         * Checks if a field can be validated or not.
         *
         * @method validatable
         * @param {Node} field
         * @return {Boolean}
         */
        validatable: function(field) {
            var instance = this,
                validatable = false,
                fieldRules = instance.get('rules')[field.get('name')];

            if (fieldRules) {
                validatable = instance.normalizeRuleValue(fieldRules.required, field) ||
                    defaults.RULES.hasValue.apply(instance, [field.val(), field]);
            }

            return !!validatable;
        },

        /**
         * Validates all fields.
         *
         * @method validate
         */
        validate: function() {
            var instance = this;

            instance.eachRule(
                function(rule, fieldName) {
                    instance.validateField(fieldName);
                }
            );

            instance.focusInvalidField();
        },

        /**
         * Validates a single field.
         *
         * @method validateField
         * @param {Node|String} field
         */
        validateField: function(field) {
            var fieldNode,
                validatable;

            this.resetField(field);
            fieldNode = isString(field) ? this.getField(field) : field;

            if (isNode(fieldNode)) {
                validatable = this.validatable(fieldNode);

                if (validatable) {
                    this.fire('validateField', {
                        validator: {
                            field: fieldNode
                        }
                    });
                }
            }
        },

        /**
         * Fires after `extractRules` attribute change.
         *
         * @method _afterExtractRulesChange
         * @param event
         * @protected
         */
        _afterExtractRulesChange: function(event) {
            var instance = this;

            instance._uiSetExtractRules(event.newVal);
        },

        /**
         * Fires after `validateOnBlur` attribute change.
         *
         * @method _afterValidateOnBlurChange
         * @param event
         * @protected
         */
        _afterValidateOnBlurChange: function(event) {
            var instance = this;

            instance._uiSetValidateOnBlur(event.newVal);
        },

        /**
         * Fires after `validateOnInput` attribute change.
         *
         * @method _afterValidateOnInputChange
         * @param event
         * @protected
         */
        _afterValidateOnInputChange: function(event) {
            var instance = this;

            instance._uiSetValidateOnInput(event.newVal);
        },

        /**
         * Defines an error field.
         *
         * @method _defErrorFieldFn
         * @param event
         * @protected
         */
        _defErrorFieldFn: function(event) {
            var instance = this,
                field,
                label,
                stackContainer,
                target,
                validator;

            label = instance.get('labelCssClass');
            validator = event.validator;
            field = validator.field;

            instance.highlight(field);

            if (instance.get('showMessages')) {
                target = field;

                stackContainer = instance.getFieldStackErrorContainer(field);

                if (A.FormValidator.isCheckable(target)) {
                    target = field.ancestor('.' + CSS_HAS_ERROR).get('lastChild');
                }

                var id = field.get('id') + 'Helper';

                stackContainer.set('id', id);

                target.placeAfter(stackContainer);

                instance.printStackError(
                    field,
                    stackContainer,
                    validator.errors
                );
            }
        },

        /**
         * Defines a valid field.
         *
         * @method _defValidFieldFn
         * @param event
         * @protected
         */
        _defValidFieldFn: function(event) {
            var instance = this;

            var field = event.validator.field;

            instance.unhighlight(field);
        },

        /**
         * Defines the validation of a field.
         *
         * @method _defValidateFieldFn
         * @param event
         * @protected
         */
        _defValidateFieldFn: function(event) {
            var instance = this;

            var field = event.validator.field;
            var fieldRules = instance.get('rules')[field.get('name')];

            A.each(
                fieldRules,
                function(ruleValue, ruleName) {
                    var rule = defaults.RULES[ruleName];
                    var fieldValue = trim(field.val());

                    ruleValue = instance.normalizeRuleValue(ruleValue, field);

                    if (isFunction(rule) && !rule.apply(instance, [fieldValue, field, ruleValue])) {

                        instance.addFieldError(field, ruleName);
                    }
                }
            );

            var fieldErrors = instance.getFieldError(field);

            if (fieldErrors) {
                instance.fire('errorField', {
                    validator: {
                        field: field,
                        errors: fieldErrors
                    }
                });
            }
            else {
                instance.fire('validField', {
                    validator: {
                        field: field
                    }
                });
            }
        },

        /**
         * Finds the label text of a field if existing.
         *
         * @method _findFieldLabel
         * @param {Node} field
         * @return {String}
         */
        _findFieldLabel: function(field) {
            var labelCssClass = '.' + this.get('labelCssClass'),
                label = A.one('label[for=' + field.get('id') + ']') ||
                    field.ancestor().previous(labelCssClass);

            if (!label) {
                label = field.ancestor('.' + CSS_HAS_ERROR);

                if (label) {
                    label = label.one(labelCssClass);
                }
            }

            if (label) {
                return label.get('text');
            }
        },

        /**
         * Sets the error/success CSS classes based on the validation of a
         * field.
         *
         * @method _highlightHelper
         * @param {Node} field
         * @param {String} errorClass
         * @param {String} validClass
         * @param {Boolean} valid
         * @protected
         */
        _highlightHelper: function(field, errorClass, validClass, valid) {
            var instance = this;

            if (valid) {
                field.removeClass(errorClass).addClass(validClass);

                if (validClass === CSS_SUCCESS_FIELD) {
                    field.removeAttribute('aria-errormessage');
                    field.removeAttribute('aria-invalid');
                }
            }
            else {
                field.removeClass(validClass).addClass(errorClass);

                if (errorClass === CSS_ERROR_FIELD) {
                    field.set('aria-errormessage', field.get('id') + 'Helper');
                    field.set('aria-invalid', true);
                }
            }
        },

        /**
         * Extracts form rules from the DOM.
         *
         * @method _extractRulesFromMarkup
         * @param rules
         * @protected
         */
        _extractRulesFromMarkup: function(rules) {
            var instance = this,
                domBoundingBox = instance.get('boundingBox').getDOM(),
                elements = domBoundingBox.elements,
                defaultRulesKeys = AObject.keys(defaults.RULES),
                defaultRulesJoin = defaultRulesKeys.join('|'),
                regex = getRegExp('field-(' + defaultRulesJoin + ')', 'g'),
                i,
                length,
                ruleNameMatch = [],
                ruleMatcher = function(m1, m2) {
                    ruleNameMatch.push(m2);
                };

            for (i = 0, length = elements.length; i < length; i++) {
                var el = elements[i],
                    fieldName = el.name;

                el.className.replace(regex, ruleMatcher);

                if (ruleNameMatch.length) {
                    var fieldRules = rules[fieldName],
                        j,
                        ruleNameLength;

                    if (!fieldRules) {
                        fieldRules = {};
                        rules[fieldName] = fieldRules;
                    }
                    for (j = 0, ruleNameLength = ruleNameMatch.length; j < ruleNameLength; j++) {
                        var rule = ruleNameMatch[j];

                        if (!(rule in fieldRules)) {
                            fieldRules[rule] = true;
                        }
                    }
                    ruleNameMatch.length = 0;
                }
            }

            instance._rulesAlreadyExtracted = true;
        },

        /**
         * Triggers when there's an input in the field.
         *
         * @method _onFieldInput
         * @param event
         * @protected
         */
        _onFieldInput: function(event) {
            var instance = this;

            var skipValidationTargetSelector = instance.get('skipValidationTargetSelector');

            if (!event.relatedTarget || !event.relatedTarget.getDOMNode().matches(skipValidationTargetSelector)) {
                setTimeout(
                    function() {
                        instance.validateField(event.target);
                    },
                    300
                );
            }
        },

        /**
         * Triggers when the form is submitted.
         *
         * @method _onFormSubmit
         * @param event
         * @protected
         */
        _onFormSubmit: function(event) {
            var instance = this;

            var data = {
                validator: {
                    formEvent: event
                }
            };

            instance.validate();

            if (instance.hasErrors()) {
                data.validator.errors = instance.errors;

                instance.fire('submitError', data);

                event.halt();
            }
            else {
                instance.fire('submit', data);
            }
        },

        /**
         * Triggers when the form is reseted.
         *
         * @method _onFormReset
         * @param event
         * @protected
         */
        _onFormReset: function() {
            var instance = this;

            instance.resetAllFields();
        },

        /**
         * Sets the aria roles.
         *
         * @method _setARIARoles
         * @protected
         */
        _setARIARoles: function() {
            var instance = this;

            instance.eachRule(
                function(rule, fieldName) {
                    var field = instance.getField(fieldName);

                    var required = instance.normalizeRuleValue(rule.required, field);

                    if (required) {
                        if (field && !field.attr('aria-required')) {
                            field.attr('aria-required', true);
                        }
                    }
                }
            );
        },

        /**
         * Sets the `extractRules` attribute on the UI.
         *
         * @method _uiSetExtractRules
         * @param val
         * @protected
         */
        _uiSetExtractRules: function(val) {
            var instance = this;
            if (val) {
                instance._extractRulesFromMarkup(instance.get('rules'));
            }
        },

        /**
         * Sets the `validateOnInput` attribute on the UI.
         *
         * @method _uiSetValidateOnInput
         * @param val
         * @protected
         */
        _uiSetValidateOnInput: function(val) {
            var instance = this,
                boundingBox = instance.get('boundingBox');

            if (val) {
                if (!instance._inputHandlers) {
                    instance._inputHandlers = boundingBox.delegate('input', instance._onFieldInput,
                        'input:not([type="file"]),select,textarea,button', instance);
                }

                if (!instance._fileInputHandlers) {
                    instance._fileInputHandlers = boundingBox.delegate('change', instance._onFieldInput,
                        'input[type="file"]', instance);
                }
            }
            else {
                if (instance._inputHandlers) {
                    instance._inputHandlers.detach();
                }

                if (instance._fileInputHandlers) {
                    instance._fileInputHandlers.detach();
                }
            }
        },

        /**
         * Sets the `validateOnBlur` attribute on the UI.
         *
         * @method _uiSetValidateOnBlur
         * @param val
         * @protected
         */
        _uiSetValidateOnBlur: function(val) {
            var instance = this,
                boundingBox = instance.get('boundingBox');

            if (val) {
                if (!instance._blurHandlers) {
                    instance._blurHandlers = boundingBox.delegate('blur', instance._onFieldInput,
                        'input:not([type="file"]),select,textarea,button', instance);
                }

                if (!instance._fileBlurHandlers) {
                    instance._fileBlurHandlers = boundingBox.delegate('change', instance._onFieldInput,
                        'input[type="file"]', instance);
                }
            }
            else {
                if (instance._blurHandlers) {
                    instance._blurHandlers.detach();
                }

                if (instance._fileBlurHandlers) {
                    instance._fileBlurHandlers.detach();
                }
            }
        }
    }
});

A.each(
    defaults.REGEX,
    function(regex, key) {
        defaults.RULES[key] = function(val) {
            return defaults.REGEX[key].test(val);
        };
    }
);

A.FormValidator = FormValidator;

}, '3.1.0-deprecated.76', {
    "requires": [
        "escape",
        "selector-css3",
        "node-event-delegate",
        "aui-node",
        "aui-component",
        "aui-event-input"
    ]
});

YUI.add('aui-node-base', function (A, NAME) {

/**
 * A set of utility methods to the Node.
 *
 * @module aui-node
 * @submodule aui-node-base
 */

var Lang = A.Lang,
    isArray = Lang.isArray,
    isFunction = Lang.isFunction,
    isObject = Lang.isObject,
    isString = Lang.isString,
    isUndefined = Lang.isUndefined,
    isValue = Lang.isValue,

    AArray = A.Array,
    ANode = A.Node,
    ANodeList = A.NodeList,

    getClassName = A.getClassName,
    getRegExp = A.DOM._getRegExp,

    CONFIG = A.config,
    DOC = CONFIG.doc,
    WIN = CONFIG.win,

    NODE_PROTO = ANode.prototype,
    NODE_PROTO_HIDE = NODE_PROTO._hide,
    NODE_PROTO_SHOW = NODE_PROTO._show,
    NODELIST_PROTO = ANodeList.prototype,

    ARRAY_EMPTY_STRINGS = ['', ''],

    CSS_HIDE = getClassName('hide'),
    CSS_UNSELECTABLE_VALUE = 'none',
    CSS_SELECTABLE_VALUE = 'text',

    SUPPORT_CLONED_EVENTS = false,

    MAP_BORDER = {
        b: 'borderBottomWidth',
        l: 'borderLeftWidth',
        r: 'borderRightWidth',
        t: 'borderTopWidth'
    },
    MAP_MARGIN = {
        b: 'marginBottom',
        l: 'marginLeft',
        r: 'marginRight',
        t: 'marginTop'
    },
    MAP_PADDING = {
        b: 'paddingBottom',
        l: 'paddingLeft',
        r: 'paddingRight',
        t: 'paddingTop'
    };

/* Parts of this file are used from jQuery (http://jquery.com)
 * Dual-licensed under MIT/GPL
 */
var div = DOC.createElement('div');

div.style.display = 'none';
div.innerHTML = '   <table></table>&nbsp;';

if (div.attachEvent && div.fireEvent) {
    div.attachEvent(
        'onclick',
        function detach() {
            SUPPORT_CLONED_EVENTS = true;

            div.detachEvent('onclick', detach);
        }
    );

    div.cloneNode(true).fireEvent('onclick');
}

var SUPPORT_OPTIONAL_TBODY = !div.getElementsByTagName('tbody').length;

var REGEX_LEADING_WHITE_SPACE = /^\s+/,
    REGEX_IE8_ACTION = /\=([^=\x27\x22>\s]+\/)>/g,
    REGEX_TAGNAME = /<([\w:]+)/;

div = null;

var _setUnselectable = function(element, unselectable, noRecurse) {
    var descendants,
        value = unselectable ? 'on' : '',
        i,
        descendant;

    element.setAttribute('unselectable', value);

    if (!noRecurse) {
        descendants = element.getElementsByTagName('*');

        for (i = 0;
            (descendant = descendants[i]); i++) {
            descendant.setAttribute('unselectable', value);
        }
    }
};

/**
 * Augments the [YUI3 Node](Node.html) with more util methods.
 *
 * Check the [live demo](http://alloyui.com/examples/node/).
 *
 * @class A.Node
 * @uses Node
 * @constructor
 * @include http://alloyui.com/examples/node/basic-markup.html
 * @include http://alloyui.com/examples/node/basic.js
 */
A.mix(NODE_PROTO, {

    /**
     * Returns the current ancestors of the node element filtered by a
     * className. This is an optimized method for finding ancestors by a
     * specific CSS class name.
     *
     * Example:
     *
     * ```
     * A.one('#nodeId').ancestorsByClassName('aui-hide');
     * ```
     *
     * @method ancestorsByClassName
     * @param {String} className A selector to filter the ancestor elements
     *     against.
     * @param {Boolean} testSelf optional Whether or not to include the element
     * in the scan
     * @return {NodeList}
     */
    ancestorsByClassName: function(className, testSelf) {
        var instance = this;

        var ancestors = [];
        var cssRE = new RegExp('\\b' + className + '\\b');
        var currentEl = instance.getDOM();

        if (!testSelf) {
            currentEl = currentEl.parentNode;
        }

        while (currentEl && currentEl.nodeType !== 9) {
            if (currentEl.nodeType === 1 && cssRE.test(currentEl.className)) {
                ancestors.push(currentEl);
            }

            currentEl = currentEl.parentNode;
        }

        return A.all(ancestors);
    },

    /**
     * Gets or sets the value of an attribute for the first element in the set
     * of matched elements. If only the `name` is passed it works as a getter.
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * node.attr('title', 'Setting a new title attribute');
     * // Alert the value of the title attribute: 'Setting a new title attribute'
     * alert( node.attr('title') );
     * ```
     *
     * @method attr
     * @param {String} name The name of the attribute
     * @param {String} value The value of the attribute to be set. Optional.
     * @return {String}
     */
    attr: function(name, value) {
        var instance = this,
            i;

        if (!isUndefined(value)) {
            var el = instance.getDOM();

            if (name in el) {
                instance.set(name, value);
            }
            else {
                instance.setAttribute(name, value);
            }

            return instance;
        }
        else {
            if (isObject(name)) {
                for (i in name) {
                    if (name.hasOwnProperty(i)) {
                        instance.attr(i, name[i]);
                    }
                }

                return instance;
            }

            var currentValue = instance.get(name);

            if (!Lang.isValue(currentValue)) {
                currentValue = instance.getAttribute(name);
            }

            return currentValue;
        }
    },

    /**
     * Normalizes the behavior of cloning a node, which by default should not
     * clone the events that are attached to it.
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * node.clone().appendTo('body');
     * ```
     *
     * @method clone
     * @return {Node}
     */
    clone: (function() {
        var clone;

        if (SUPPORT_CLONED_EVENTS) {
            clone = function() {
                var el = this.getDOM();
                var clone;

                if (el.nodeType !== 3) {
                    var outerHTML = this.outerHTML();

                    outerHTML = outerHTML.replace(REGEX_IE8_ACTION, '="$1">').replace(REGEX_LEADING_WHITE_SPACE,
                        '');

                    clone = ANode.create(outerHTML);
                }
                else {
                    clone = A.one(el.cloneNode());
                }

                return clone;
            };
        }
        else {
            clone = function() {
                return this.cloneNode(true);
            };
        }

        return clone;
    }()),

    /**
     * Centralizes the current Node instance with the passed `val` Array, Node,
     * String, or Region, if not specified, the body will be used.
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * // Center the `node` with the `#container`.
     * node.center('#container');
     * ```
     *
     * @method center
     * @chainable
     * @param {Array|Node|Region|String} val Array, Node, String, or Region to
     *     center with.
     */
    center: function(val) {
        var instance = this,
            nodeRegion = instance.get('region'),
            x,
            y;

        if (isArray(val)) {
            x = val[0];
            y = val[1];
        }
        else {
            var region;

            if (isObject(val) && !A.instanceOf(val, ANode)) {
                region = val;
            }
            else {
                region = (A.one(val) || A.getBody()).get('region');
            }

            x = region.left + (region.width / 2);
            y = region.top + (region.height / 2);
        }

        instance.setXY([x - (nodeRegion.width / 2), y - (nodeRegion.height / 2)]);
    },

    /**
     * Removes not only child (and other descendant) elements, but also any text
     * within the set of matched elements. This is because, according to the DOM
     * specification, any string of text within an element is considered a child
     * node of that element.
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * node.empty();
     * ```
     *
     * @method empty
     * @chainable
     */
    empty: function() {
        var instance = this;

        instance.all('>*').remove().purge();

        var el = ANode.getDOMNode(instance);

        while (el.firstChild) {
            el.removeChild(el.firstChild);
        }

        return instance;
    },

    /**
     * Retrieves the DOM node bound to a Node instance. See
     * [getDOMNode](Node.html#method_getDOMNode).
     *
     * @method getDOM
     * @return {HTMLNode} The DOM node bound to the Node instance.
     */
    getDOM: function() {
        var instance = this;

        return ANode.getDOMNode(instance);
    },

    /**
     * Returns the combined width of the border for the specified sides.
     *
     * @method getBorderWidth
     * @param {String} sides Can be t, r, b, l or any combination of those to
     *     represent the top, right, bottom, or left sides.
     * @return {Number}
     */
    getBorderWidth: function(sides) {
        var instance = this;

        return instance._getBoxStyleAsNumber(sides, MAP_BORDER);
    },

    /**
     * Gets the current center position of the node in page coordinates.
     *
     * @method getCenterXY
     * @for Node
     * @return {Array} The XY position of the node
     */
    getCenterXY: function() {
        var instance = this;
        var region = instance.get('region');

        return [(region.left + region.width / 2), (region.top + region.height / 2)];
    },

    /**
     * Returns the combined size of the margin for the specified sides.
     *
     * @method getMargin
     * @param {String} sides Can be t, r, b, l or any combination of those to
     *     represent the top, right, bottom, or left sides.
     * @return {Number}
     */
    getMargin: function(sides) {
        var instance = this;

        return instance._getBoxStyleAsNumber(sides, MAP_MARGIN);
    },

    /**
     * Returns the combined width of the border for the specified sides.
     *
     * @method getPadding
     * @param {String} sides Can be t, r, b, l or any combination of those to
     *     represent the top, right, bottom, or left sides.
     * @return {Number}
     */
    getPadding: function(sides) {
        var instance = this;

        return instance._getBoxStyleAsNumber(sides, MAP_PADDING);
    },

    /**
     * Sets the id of the Node instance if the object does not have one. The
     * generated id is based on a guid created by the
     * [stamp](YUI.html#method_stamp) method.
     *
     * @method guid
     * @return {String} The current id of the node
     */
    guid: function() {
        var instance = this;
        var currentId = instance.get('id');

        if (!currentId) {
            currentId = A.stamp(instance);

            instance.set('id', currentId);
        }

        return currentId;
    },

    /**
     * Creates a hover interaction.
     *
     * @method hover
     * @param {String} overFn
     * @param {String} outFn
     * @return {Node} The current Node instance
     */
    hover: function(overFn, outFn) {
        var instance = this;

        var hoverOptions;
        var defaultHoverOptions = instance._defaultHoverOptions;

        if (isObject(overFn, true)) {
            hoverOptions = overFn;

            hoverOptions = A.mix(hoverOptions, defaultHoverOptions);

            overFn = hoverOptions.over;
            outFn = hoverOptions.out;
        }
        else {
            hoverOptions = A.mix({
                    over: overFn,
                    out: outFn
                },
                defaultHoverOptions
            );
        }

        instance._hoverOptions = hoverOptions;

        hoverOptions.overTask = A.debounce(instance._hoverOverTaskFn, null, instance);
        hoverOptions.outTask = A.debounce(instance._hoverOutTaskFn, null, instance);

        return new A.EventHandle(
   [
    instance.on(hoverOptions.overEventType, instance._hoverOverHandler, instance),
    instance.on(hoverOptions.outEventType, instance._hoverOutHandler, instance)
   ]
        );
    },

    /**
     * Gets or sets the HTML contents of the node. If the `value` is passed it's
     * set the content of the element, otherwise it works as a getter for the
     * current content.
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * node.html('Setting new HTML');
     * // Alert the value of the current content
     * alert( node.html() );
     * ```
     *
     * @method html
     * @param {String} value A string of html to set as the content of the node
     *     instance.
     */
    html: function() {
        var args = arguments,
            length = args.length;

        if (length) {
            this.set('innerHTML', args[0]);
        }
        else {
            return this.get('innerHTML');
        }

        return this;
    },

    /**
     * Gets the outerHTML of a node, which islike innerHTML, except that it
     * actually contains the HTML of the node itself.
     *
     * @method outerHTML
     * @return {string} The outerHTML of the given element.
     */
    outerHTML: function() {
        var instance = this;
        var domEl = instance.getDOM();

        // IE, Opera and WebKit all have outerHTML.
        if ('outerHTML' in domEl) {
            return domEl.outerHTML;
        }

        var temp = ANode.create('<div></div>').append(
            this.clone()
        );

        try {
            return temp.html();
        }
        catch (e) {}
        finally {
            temp = null;
        }
    },

    /**
     * Inserts a `newNode` after the node instance (i.e., as the next sibling).
     * If the reference node has no parent, then does nothing.
     *
     * Example:
     *
     * ```
     * var titleNode = A.one('#titleNode');
     * var descriptionNode = A.one('#descriptionNode');
     * // the description is usually shown after the title
     * titleNode.placeAfter(descriptionNode);
     * ```
     *
     * @method placeAfter
     * @chainable
     * @param {Node} newNode Node to insert.
     */
    placeAfter: function(newNode) {
        var instance = this;

        return instance._place(newNode, instance.get('nextSibling'));
    },

    /**
     * Inserts a `newNode` before the node instance (i.e., as the previous
     * sibling). If the reference node has no parent, then does nothing.
     *
     * Example:
     *
     * ```
     * var descriptionNode = A.one('#descriptionNode');
     * var titleNode = A.one('#titleNode');
     * // the title is usually shown before the description
     * descriptionNode.placeBefore(titleNode);
     * ```
     *
     * @method placeBefore
     * @chainable
     * @param {Node} newNode Node to insert.
     */
    placeBefore: function(newNode) {
        var instance = this;

        return instance._place(newNode, instance);
    },

    /**
     * Inserts the node instance to the begining of the `selector` node (i.e.,
     * insert before the `firstChild` of the `selector`).
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * node.prependTo('body');
     * ```
     *
     * @method prependTo
     * @chainable
     * @param {Node|String} selector A selector, element, HTML string, Node
     */
    prependTo: function(selector) {
        var instance = this;

        A.one(selector).prepend(instance);

        return instance;
    },

    /**
     * Adds one or more CSS classes to an element and remove the class(es) from
     * the siblings of the element.
     *
     * @method radioClass
     * @chainable
     * @param {String} cssClass
     */
    radioClass: function(cssClass) {
        var instance = this;

        var siblings = instance.siblings();

        if (isString(cssClass)) {
            siblings.removeClass(cssClass);

            instance.addClass(cssClass);
        }
        else if (isArray(cssClass)) {
            var siblingNodes = siblings.getDOM();

            var regex = getRegExp('(?:^|\\s+)(?:' + cssClass.join('|') + ')(?=\\s+|$)', 'g'),
                node,
                i;

            for (i = siblingNodes.length - 1; i >= 0; i--) {
                node = siblingNodes[i];
                node.className = node.className.replace(regex, '');
            }

            instance.addClass(cssClass.join(' '));
        }

        return instance;
    },

    /**
     * Generates an unique identifier and reset the id attribute of the node
     * instance using the new value. Invokes the [guid](Node.html#method_guid).
     *
     * @method resetId
     * @chainable
     * @param {String} prefix Optional prefix for the guid.
     */
    resetId: function(prefix) {
        var instance = this;

        instance.attr('id', A.guid(prefix));

        return instance;
    },

    /**
     * Selects a substring of text inside of the input element.
     *
     * @method selectText
     * @param {Number} start The index to start the selection range from
     * @param {Number} end The index to end the selection range at
     */
    selectText: function(start, end) {
        var instance = this;

        var textField = instance.getDOM();
        var length = instance.val().length;

        end = isValue(end) ? end : length;
        start = isValue(start) ? start : 0;

        // Some form elements could throw a (NS_ERROR_FAILURE)
        // [nsIDOMNSHTMLInputElement.setSelectionRange] error when invoke the
        // setSelectionRange on firefox. Wrapping in a try/catch to prevent the
        // error be thrown
        try {
            if (textField.setSelectionRange) {
                textField.setSelectionRange(start, end);
            }
            else if (textField.createTextRange) {
                var range = textField.createTextRange();

                range.moveStart('character', start);
                range.moveEnd('character', end - length);

                range.select();
            }
            else {
                textField.select();
            }

            if (textField !== DOC.activeElement) {
                textField.focus();
            }
        }
        catch (e) {}

        return instance;
    },

    /**
     * Enables text selection for this element (normalized across browsers).
     *
     * @method selectable
     * @param noRecurse
     * @chainable
     */
    selectable: function(noRecurse) {
        var instance = this;

        instance.setStyles({
            '-webkit-user-select': CSS_SELECTABLE_VALUE,
            '-khtml-user-select': CSS_SELECTABLE_VALUE,
            '-moz-user-select': CSS_SELECTABLE_VALUE,
            '-ms-user-select': CSS_SELECTABLE_VALUE,
            '-o-user-select': CSS_SELECTABLE_VALUE,
            'user-select': CSS_SELECTABLE_VALUE
        });

        if (A.UA.ie || A.UA.opera) {
            _setUnselectable(instance._node, false, noRecurse);
        }

        return instance;
    },

    /**
     * Stops the specified event(s) from bubbling and optionally prevents the
     * default action.
     *
     * Example:
     *
     * ```
     * var anchor = A.one('a#anchorId');
     * anchor.swallowEvent('click');
     * ```
     *
     * @method swallowEvent
     * @chainable
     * @param {String|Array} eventName An event or array of events to stop from
     *     bubbling
     * @param {Boolean} preventDefault (optional) true to prevent the default
     *     action too
     */
    swallowEvent: function(eventName, preventDefault) {
        var instance = this;

        var fn = function(event) {
            event.stopPropagation();

            if (preventDefault) {
                event.preventDefault();

                event.halt();
            }

            return false;
        };

        if (isArray(eventName)) {
            AArray.each(
                eventName,
                function(name) {
                    instance.on(name, fn);
                }
            );

            return this;
        }
        else {
            instance.on(eventName, fn);
        }

        return instance;
    },

    /**
     * Gets or sets the combined text contents of the node instance, including
     * it's descendants. If the `text` is passed it's set the content of the
     * element, otherwise it works as a getter for the current content.
     *
     * Example:
     *
     * ```
     * var node = A.one('#nodeId');
     * node.text('Setting new text content');
     * // Alert the value of the current content
     * alert( node.text() );
     * ```
     *
     * @method text
     * @param {String} text A string of text to set as the content of the node
     *     instance.
     */
    text: function(text) {
        var instance = this;
        var el = instance.getDOM();

        if (!isUndefined(text)) {
            text = A.DOM._getDoc(el).createTextNode(text);

            return instance.empty().append(text);
        }

        return instance._getText(el.childNodes);
    },

    /**
     * Displays or hide the node instance.
     *
     * NOTE: This method assume that your node were hidden because of the
     * 'aui-hide' css class were being used. This won't manipulate the inline
     * `style.display` property.
     *
     * @method toggle
     * @chainable
     * @param {Boolean} on Whether to force the toggle. Optional.
     * @param {Function} callback A function to run after the visibility change.
     *     Optional.
     */
    toggle: function() {
        var instance = this;

        instance._toggleView.apply(instance, arguments);

        return instance;
    },

    /**
     * Disables text selection for this element (normalized across browsers).
     *
     * @method unselectable
     * @param noRecurse
     * @chainable
     */
    unselectable: function(noRecurse) {
        var instance = this;

        instance.setStyles({
            '-webkit-user-select': CSS_UNSELECTABLE_VALUE,
            '-khtml-user-select': CSS_UNSELECTABLE_VALUE,
            '-moz-user-select': CSS_UNSELECTABLE_VALUE,
            '-ms-user-select': CSS_UNSELECTABLE_VALUE,
            '-o-user-select': CSS_UNSELECTABLE_VALUE,
            'user-select': CSS_UNSELECTABLE_VALUE
        });

        if (A.UA.ie || A.UA.opera) {
            _setUnselectable(instance._node, true, noRecurse);
        }

        return instance;
    },

    /**
     * Gets or sets the value attribute of the node instance. If the `value` is
     * passed it's set the value of the element, otherwise it works as a getter
     * for the current value.
     *
     * Example:
     *
     * ```
     * var input = A.one('#inputId');
     * input.val('Setting new input value');
     * // Alert the value of the input
     * alert( input.val() );
     * ```
     *
     * @method val
     * @param {String} value Value to be set. Optional.
     */
    val: function(value) {
        var instance = this;

        if (isUndefined(value)) {
            return instance.get('value');
        }
        else {
            return instance.set('value', value);
        }
    },

    /**
     * Returns the combined size of the box style for the specified sides.
     *
     * @method _getBoxStyleAsNumber
     * @param {String} sides Can be t, r, b, l or any combination of
     * those to represent the top, right, bottom, or left sides.
     * @param {String} map An object mapping mapping the "sides" param to the a
     *     CSS value to retrieve
     * @return {Number}
     * @private
     */
    _getBoxStyleAsNumber: function(sides, map) {
        var instance = this;

        var sidesArray = sides.match(/\w/g),
            value = 0,
            side,
            sideKey,
            i;

        for (i = sidesArray.length - 1; i >= 0; i--) {
            sideKey = sidesArray[i];
            side = 0;

            if (sideKey) {
                side = parseFloat(instance.getComputedStyle(map[sideKey]));
                side = Math.abs(side);

                value += side || 0;
            }
        }

        return value;
    },

    /**
     * Extracts text content from the passed nodes.
     *
     * @method _getText
     * @private
     * @param {Native NodeList} childNodes
     */
    _getText: function(childNodes) {
        var instance = this;

        var length = childNodes.length,
            childNode,
            str = [],
            i;

        for (i = 0; i < length; i++) {
            childNode = childNodes[i];

            if (childNode && childNode.nodeType !== 8) {
                if (childNode.nodeType !== 1) {
                    str.push(childNode.nodeValue);
                }

                if (childNode.childNodes) {
                    str.push(instance._getText(childNode.childNodes));
                }
            }
        }

        return str.join('');
    },

    /**
     * Overrides Y.Node._hide. Adds aui-hide to the node's cssClass
     *
     * @method _hide
     * @private
     */
    _hide: function() {
        var instance = this;

        instance.addClass(CSS_HIDE);

        return NODE_PROTO_HIDE.apply(instance, arguments);
    },

    /**
     * The event handler for the "out" function that is fired for events
     * attached via the hover method.
     *
     * @method _hoverOutHandler
     * @private
     * @param {EventFacade} event
     */
    _hoverOutHandler: function(event) {
        var instance = this;

        var hoverOptions = instance._hoverOptions;

        hoverOptions.outTask.delay(hoverOptions.outDelay, event);
    },

    /**
     * The event handler for the "over" function that is fired for events
     * attached via the hover method.
     *
     * @method _hoverOverHandler
     * @private
     * @param {EventFacade} event
     */
    _hoverOverHandler: function(event) {
        var instance = this;

        var hoverOptions = instance._hoverOptions;

        hoverOptions.overTask.delay(hoverOptions.overDelay, event);
    },

    /**
     * Cancels the over task, and fires the users custom "out" function for the
     * hover method
     *
     * @method _hoverOverHandler
     * @private
     * @param {EventFacade} event
     */
    _hoverOutTaskFn: function(event) {
        var instance = this;

        var hoverOptions = instance._hoverOptions;

        hoverOptions.overTask.cancel();

        hoverOptions.out.apply(hoverOptions.context || event.currentTarget, arguments);
    },

    /**
     * Cancels the out task, and fires the users custom "over" function for the
     * hover method
     *
     * @method _hoverOverHandler
     * @private
     * @param {EventFacade} event
     */
    _hoverOverTaskFn: function(event) {
        var instance = this;

        var hoverOptions = instance._hoverOptions;

        hoverOptions.outTask.cancel();

        hoverOptions.over.apply(hoverOptions.context || event.currentTarget, arguments);
    },

    /**
     * Places a node or html string at a specific location
     *
     * @method _place
     * @private
     * @param {Node|String} newNode
     * @param {Node} refNode
     */
    _place: function(newNode, refNode) {
        var instance = this;

        var parent = instance.get('parentNode');

        if (parent) {
            if (isString(newNode)) {
                newNode = ANode.create(newNode);
            }

            parent.insertBefore(newNode, refNode);
        }

        return instance;
    },

    /**
     * Overrides Y.Node._show. Removes aui-hide from the node's cssClass
     *
     * @method _show
     * @private
     */
    _show: function() {
        var instance = this;

        instance.removeClass(CSS_HIDE);

        return NODE_PROTO_SHOW.apply(instance, arguments);
    },

    _defaultHoverOptions: {
        overEventType: 'mouseenter',
        outEventType: 'mouseleave',
        overDelay: 0,
        outDelay: 0,
        over: Lang.emptyFn,
        out: Lang.emptyFn
    }
}, true);

NODE_PROTO.__isHidden = NODE_PROTO._isHidden;

NODE_PROTO._isHidden = function() {
    var instance = this;

    return NODE_PROTO.__isHidden.call(instance) || instance.hasClass(instance._hideClass || CSS_HIDE);
};

/**
 * Returns the width of the content, not including the padding, border or
 * margin. If a width is passed, the node's overall width is set to that size.
 *
 * Example:
 *
 * ```
 * var node = A.one('#nodeId');
 * node.width(); //return content width
 * node.width(100); // sets box width
 * ```
 *
 * @method width
 * @return {number}
 */

/**
 * Returns the height of the content, not including the padding, border or
 * margin. If a height is passed, the node's overall height is set to that size.
 *
 * Example:
 *
 * ```
 * var node = A.one('#nodeId');
 * node.height(); //return content height
 * node.height(100); // sets box height
 * ```
 *
 * @method height
 * @return {number}
 */

/**
 * Returns the size of the box from inside of the border, which is the
 * `offsetWidth` plus the padding on the left and right.
 *
 * Example:
 *
 * ```
 * var node = A.one('#nodeId');
 * node.innerWidth();
 * ```
 *
 * @method innerWidth
 * @return {number}
 */

/**
 * Returns the size of the box from inside of the border, which is offsetHeight
 * plus the padding on the top and bottom.
 *
 * Example:
 *
 * ```
 * var node = A.one('#nodeId');
 * node.innerHeight();
 * ```
 *
 * @method innerHeight
 * @return {number}
 */

/**
 * Returns the outer width of the box including the border, if true is passed as
 * the first argument, the margin is included.
 *
 * Example:
 *
 * ```
 * var node = A.one('#nodeId');
 * node.outerWidth();
 * node.outerWidth(true); // includes margin
 * ```
 *
 * @method outerWidth
 * @return {number}
 */

/**
 * Returns the outer height of the box including the border, if true is passed
 * as the first argument, the margin is included.
 *
 * Example:
 *
 * ```
 * var node = A.one('#nodeId');
 * node.outerHeight();
 * node.outerHeight(true); // includes margin
 * ```
 *
 * @method outerHeight
 * @return {number}
 */

A.each(
 ['Height', 'Width'],
    function(item, index) {
        var sides = index ? 'lr' : 'tb';

        var dimensionType = item.toLowerCase();

        NODE_PROTO[dimensionType] = function(size) {
            var instance = this;

            var returnValue = instance;

            if (isUndefined(size)) {
                var node = instance._node;
                var dimension;

                if (node) {
                    if ((!node.tagName && node.nodeType === 9) || node.alert) {
                        dimension = instance.get('region')[dimensionType];
                    }
                    else {
                        dimension = instance.get('offset' + item);

                        if (!dimension) {
                            var originalDisplay = instance.getStyle('display');
                            var originalPosition = instance.getStyle('position');
                            var originalVisibility = instance.getStyle('visibility');

                            instance.setStyles({
                                display: 'block !important',
                                position: 'absolute !important',
                                visibility: 'hidden !important'
                            });

                            dimension = instance.get('offset' + item);

                            instance.setStyles({
                                display: originalDisplay,
                                position: originalPosition,
                                visibility: originalVisibility
                            });
                        }

                        if (dimension) {
                            dimension -= (instance.getPadding(sides) + instance.getBorderWidth(sides));
                        }
                    }
                }

                returnValue = dimension;
            }
            else {
                instance.setStyle(dimensionType, size);
            }

            return returnValue;
        };

        NODE_PROTO['inner' + item] = function() {
            var instance = this;

            return instance[dimensionType]() + instance.getPadding(sides);
        };

        NODE_PROTO['outer' + item] = function(margin) {
            var instance = this;

            var innerSize = instance['inner' + item]();
            var borderSize = instance.getBorderWidth(sides);

            var size = innerSize + borderSize;

            if (margin) {
                size += instance.getMargin(sides);
            }

            return size;
        };
    }
);

if (!SUPPORT_OPTIONAL_TBODY) {
    A.DOM._ADD_HTML = A.DOM.addHTML;

    A.DOM.addHTML = function(node, content, where) {
        var nodeName = (node.nodeName && node.nodeName.toLowerCase()) || '';

        var tagName = '';

        if (!isUndefined(content)) {
            if (isString(content)) {
                tagName = (REGEX_TAGNAME.exec(content) || ARRAY_EMPTY_STRINGS)[1];
            }
            else if (content.nodeType && content.nodeType === 11 && content.childNodes.length) { // a doc frag
                tagName = content.childNodes[0].nodeName;
            }
            else if (content.nodeName) { // a node
                tagName = content.nodeName;
            }

            tagName = tagName && tagName.toLowerCase();
        }

        if (nodeName === 'table' && tagName === 'tr') {
            node = node.getElementsByTagName('tbody')[0] || node.appendChild(node.ownerDocument.createElement('tbody'));

            var whereNodeName = ((where && where.nodeName) || '').toLowerCase();

            // Assuming if the "where" is a tbody node,
            // we're trying to prepend to a table. Attempt to
            // grab the first child of the tbody.
            if (whereNodeName === 'tbody' && where.childNodes.length > 0) {
                where = where.firstChild;
            }
        }

        return A.DOM._ADD_HTML(node, content, where);
    };
}

/**
 * Augments the [YUI3 NodeList](NodeList.html) with more util methods.
 *
 * Checks the list of [Methods](NodeList.html#methods) available for AUI
 * NodeList.
 *
 * @class A.NodeList
 * @constructor
 * @uses A.Node
 */
ANodeList.importMethod(
    NODE_PROTO, [
  'after',

  'appendTo',

  'attr',

  'before',

  'empty',

  'getX',

  'getXY',

  'getY',

  'hover',

  'html',

  'innerHeight',

  'innerWidth',

  'outerHeight',

  'outerHTML',

  'outerWidth',

  'prepend',

  'prependTo',

  'purge',

  'selectText',

  'selectable',

  'setX',

  'setXY',

  'setY',

  'text',

  'toggle',

  'unselectable',

  'val'
 ]
);

A.mix(
    NODELIST_PROTO, {
        /**
         * See [Node all](Node.html#method_all).
         *
         * @method all
         */
        all: function(selector) {
            var instance = this,
                newNodeList = [],
                nodes = instance._nodes,
                length = nodes.length,
                subList,
                i;

            for (i = 0; i < length; i++) {
                subList = A.Selector.query(selector, nodes[i]);

                if (subList && subList.length) {
                    newNodeList.push.apply(newNodeList, subList);
                }
            }

            newNodeList = AArray.unique(newNodeList);

            return A.all(newNodeList);
        },

        /**
         * Returns the first element in the node list collection.
         *
         * @method first
         * @return {Node}
         */
        first: function() {
            var instance = this;

            return instance.item(0);
        },

        /**
         * See [Node getDOMNode](Node.html#method_getDOMNode).
         *
         * @method getDOM
         */
        getDOM: function() {
            return ANodeList.getDOMNodes(this);
        },

        /**
         * Returns the last element in the node list collection.
         *
         * @method last
         * @return {Node}
         */
        last: function() {
            var instance = this;

            return instance.item(instance._nodes.length - 1);
        },

        /**
         * See [Node one](Node.html#method_one).
         *
         * @method one
         */
        one: function(selector) {
            var instance = this,
                newNode = null,
                nodes = instance._nodes,
                length = nodes.length,
                i;

            for (i = 0; i < length; i++) {
                newNode = A.Selector.query(selector, nodes[i], true);

                if (newNode) {
                    newNode = A.one(newNode);

                    break;
                }
            }

            return newNode;
        }
    }
);

NODELIST_PROTO.__filter = NODELIST_PROTO.filter;

NODELIST_PROTO.filter = function(value, context) {
    var instance = this;

    var newNodeList;

    if (isFunction(value)) {
        var nodes = [];

        instance.each(
            function(item, index, collection) {
                if (value.call(context || item, item, index, collection)) {
                    nodes.push(item._node);
                }
            }
        );

        newNodeList = A.all(nodes);
    }
    else {
        newNodeList = NODELIST_PROTO.__filter.call(instance, value);
    }

    return newNodeList;
};

A.mix(
    ANodeList, {
        /**
         * Converts the passed `html` into a `NodeList` and returns the result.
         *
         * @method create
         * @param {String} html
         * @return {NodeList}
         */
        create: function(html) {
            var docFrag = A.getDoc().invoke('createDocumentFragment');

            return docFrag.append(html).get('childNodes');
        }
    }
);

A.mix(
    A, {
        /**
         * Gets the body node. Shortcut to `A.one('body')`.
         *
         * @method getBody
         */
        getBody: function() {
            var instance = this;

            if (!instance._bodyNode) {
                instance._bodyNode = A.one(DOC.body);
            }

            return instance._bodyNode;
        },

        /**
         * Gets the document node. Shortcut to `A.one(document)`.
         *
         * @method getDoc
         */
        getDoc: function() {
            var instance = this;

            if (!instance._documentNode) {
                instance._documentNode = A.one(DOC);
            }

            return instance._documentNode;
        },

        /**
         * Gets the window node. Shortcut to `A.one(window)`.
         *
         * @method getWin
         */
        getWin: function() {
            var instance = this;

            if (!instance._windowNode) {
                instance._windowNode = A.one(WIN);
            }

            return instance._windowNode;
        }
    }
);


}, '3.1.0-deprecated.76', {"requires": ["array-extras", "aui-base-lang", "aui-classnamemanager", "aui-debounce", "node"]});

YUI.add('aui-node-html5', function (A, NAME) {

/**
 * Provides support for HTML shiv natively on the Alloy DOM methods. The HTML5
 * shiv just affects IE.
 *
 * @module aui-node
 * @submodule aui-node-html5
 */

if (A.UA.ie) {
    /**
     * An object that encapsulates util methods for HTML5 shiving.
     *
     * **What is a "shiv"?**
     *
     * To the world, a shiv is a slang term for a sharp object used as a
     * knife-like weapon. To Internet Explorer, a shiv is a script that, when
     * executed, forces the browser to recognize HTML5 elements.
     *
     * @class A.HTML5
     */
    var HTML5 = A.namespace('HTML5'),
        DOM_create = A.DOM._create;

    if (!HTML5._fragHTML5Shived) {
        /**
         * A global DocumentFragment already HTML5 shived, for performance
         * reasons. (i.e., all nodes and its HTML5 children appended to this
         * fragment iherits the styles on IE).
         *
         * @property _fragHTML5Shived
         * @type {DocumentFragment}
         * @protected
         */
        HTML5._fragHTML5Shived = A.html5shiv(
            A.config.doc.createDocumentFragment()
        );
    }

    A.mix(
        HTML5, {
            /**
             * Receives a `frag` and a HTML content. This method shivs the HTML5
             * nodes appended to a Node or fragment which is not on the document
             * yet.
             *
             * @method IECreateFix
             * @param {Node|DocumentFragment} frag Fragment to be fixed.
             * @param {String} content HTML to be set (using innerHTML) on the
             *     `frag`.
             * @return {Node|DocumentFragment}
             */
            IECreateFix: function(frag, content) {
                var shivedFrag = HTML5._fragHTML5Shived;

                shivedFrag.appendChild(frag);

                frag.innerHTML = content;

                shivedFrag.removeChild(frag);

                return frag;
            },

            /**
             * AOP listener to the A.DOM._create method. This method intercepts
             * all the calls to the A.DOM._create and append the generated
             * fragment to [A.HTML._fragHTML5Shived](A.HTML5.html#property__frag
             * HTML5Shived), this fixes the IE bug for painting the HTML5 nodes
             * on the HTML fragment.
             *
             * @method _doBeforeCreate
             * @param {String} html HTML content
             * @param {String} doc
             * @param {String} tag
             * @protected
             * @return {DocumentFragment}
             */
            _doBeforeCreate: function(html) {
                var createdFrag = DOM_create.apply(this, arguments);

                var shivedFrag = HTML5.IECreateFix(createdFrag, html);

                return new A.Do.Halt(null, shivedFrag);
            }
        }
    );

    A.Do.before(HTML5._doBeforeCreate, A.DOM, '_create', A.DOM);
}
/**
 * The Node Utility.
 *
 * @module aui-node
 * @submodule aui-node-html5-print
 */

var CONFIG = A.config,
    DOC = CONFIG.doc,
    WIN = CONFIG.win,
    UA = A.UA,
    IE = UA.ie,

    isShivDisabled = function() {
        return WIN.AUI_HTML5_IE === false;
    };

if (!IE || IE >= 9 || isShivDisabled()) {
    return;
}

var BUFFER_CSS_TEXT = [],

    LOCATION = WIN.location,

    DOMAIN = LOCATION.protocol + '//' + LOCATION.host,

    HTML = DOC.documentElement,

    HTML5_ELEMENTS = A.HTML5_ELEMENTS,
    HTML5_ELEMENTS_LENGTH = HTML5_ELEMENTS.length,
    HTML5_ELEMENTS_LIST = HTML5_ELEMENTS.join('|'),

    REGEX_CLONE_NODE_CLEANUP = new RegExp('<(/?):(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
    REGEX_ELEMENTS = new RegExp('(' + HTML5_ELEMENTS_LIST + ')', 'gi'),
    REGEX_ELEMENTS_FAST = new RegExp('\\b(' + HTML5_ELEMENTS_LIST + ')\\b', 'i'),

    REGEX_PRINT_MEDIA = /print|all/,

    REGEX_RULE = new RegExp('(^|[^\\n{}]*?\\s)(' + HTML5_ELEMENTS_LIST + ').*?{([^}]*)}', 'gim'),
    REGEX_TAG = new RegExp('<(\/*)(' + HTML5_ELEMENTS_LIST + ')', 'gi'),

    SELECTOR_REPLACE_RULE = '.' + 'printfix-' + '$1',

    STR_EMPTY = '',

    STR_URL_DOMAIN = 'url(' + DOMAIN,

    TAG_REPLACE_ORIGINAL = '<$1$2',
    TAG_REPLACE_FONT = '<$1font';

var html5shiv = A.html5shiv,
    // Yes, IE does this wackiness; converting an object
    // to a string should never result in undefined, but
    // IE's styleSheet object sometimes becomes inaccessible
    // after trying to print the second time
    isStylesheetDefined = function(obj) {
        return obj && (obj + STR_EMPTY !== undefined);
    },

    toggleNode = function(node, origNode, prop) {
        var state = origNode[prop];

        if (state) {
            node.setAttribute(prop, state);
        }
        else {
            node.removeAttribute(prop);
        }
    };

html5shiv(DOC);

var printFix = function() {
    var destroy;

    var afterPrint = function() {
        if (isShivDisabled()) {
            destroy();
        }
        else {
            printFix.onAfterPrint();
        }
    };

    var beforePrint = function() {
        if (isShivDisabled()) {
            destroy();
        }
        else {
            printFix.onBeforePrint();
        }
    };

    destroy = function() {
        WIN.detachEvent('onafterprint', afterPrint);
        WIN.detachEvent('onbeforeprint', beforePrint);
    };

    var init = function() {
        WIN.attachEvent('onafterprint', afterPrint);
        WIN.attachEvent('onbeforeprint', beforePrint);
    };

    init();

    printFix.destroy = destroy;
    printFix.init = init;
};

A.mix(
    printFix, {
        /**
         * Fires after a print.
         *
         * @method onAfterPrint
         */
        onAfterPrint: function() {
            var instance = this;

            instance.restoreHTML();

            var styleSheet = instance._getStyleSheet();

            styleSheet.styleSheet.cssText = '';
        },

        /**
         * Fires before a print.
         *
         * @method onBeforePrint
         */
        onBeforePrint: function() {
            var instance = this;

            var styleSheet = instance._getStyleSheet();
            var cssRules = instance._getAllCSSText();

            styleSheet.styleSheet.cssText = instance.parseCSS(cssRules);

            instance.writeHTML();
        },

        /**
         * Navigates through the CSS joining rules and replacing content.
         *
         * @method parseCSS
         * @param cssText
         * @return {String}
         */
        parseCSS: function(cssText) {
            var css = '';
            var rules = cssText.match(REGEX_RULE);

            if (rules) {
                css = rules.join('\n').replace(REGEX_ELEMENTS, SELECTOR_REPLACE_RULE);
            }

            return css;
        },

        /**
         * Restores the HTML from the `bodyClone` and `bodyEl` attributes.
         *
         * @method restoreHTML
         */
        restoreHTML: function() {
            var instance = this;

            var bodyClone = instance._getBodyClone();
            var bodyEl = instance._getBodyEl();

            var newNodes = bodyClone.getElementsByTagName('IFRAME');
            var originalNodes = bodyEl.getElementsByTagName('IFRAME');

            var length = originalNodes.length;

            // Moving IFRAME nodes back to their original position
            if (length === newNodes.length) {
                while (length--) {
                    var newNode = newNodes[length];
                    var originalNode = originalNodes[length];

                    originalNode.swapNode(newNode);
                }
            }

            bodyClone.innerHTML = '';

            HTML.removeChild(bodyClone);
            HTML.appendChild(bodyEl);
        },

        /**
         * Generates the HTML for print.
         *
         * @method writeHTML
         */
        writeHTML: function() {
            var instance = this;

            var i = -1;
            var j;

            var bodyEl = instance._getBodyEl();

            var html5Element;

            var cssClass;

            var nodeList;
            var nodeListLength;
            var node;
            var buffer = [];

            while (++i < HTML5_ELEMENTS_LENGTH) {
                html5Element = HTML5_ELEMENTS[i];

                nodeList = DOC.getElementsByTagName(html5Element);
                nodeListLength = nodeList.length;

                j = -1;

                while (++j < nodeListLength) {
                    node = nodeList[j];

                    cssClass = node.className;

                    if (cssClass.indexOf('printfix-') === -1) {
                        buffer[0] = 'printfix-' + html5Element;
                        buffer[1] = cssClass;

                        node.className = buffer.join(' ');
                    }
                }
            }

            var docFrag = instance._getDocFrag();
            var bodyClone = instance._getBodyClone();

            docFrag.appendChild(bodyEl);
            HTML.appendChild(bodyClone);

            bodyClone.className = bodyEl.className;
            bodyClone.id = bodyEl.id;

            var originalNodes = bodyEl.getElementsByTagName('*');
            var length = originalNodes.length;

            // IE will throw a mixed content warning when using https
            // and calling clone node if the body contains elements with
            // an inline background-image style that is relative to the domain.
            if (UA.secure) {
                var bodyElStyle = bodyEl.style;

                var elStyle;
                var backgroundImage;

                bodyElStyle.display = 'none';

                for (i = 0; i < length; i++) {
                    elStyle = originalNodes[i].style;

                    backgroundImage = elStyle.backgroundImage;

                    if (backgroundImage &&
                        backgroundImage.indexOf('url(') > -1 &&
                        backgroundImage.indexOf('https') === -1) {

                        elStyle.backgroundImage = backgroundImage.replace('url(', STR_URL_DOMAIN);
                    }
                }

                bodyElStyle.display = '';
            }

            var bodyElClone = bodyEl.cloneNode(true);

            var newNodes = bodyElClone.getElementsByTagName('*');

            if (length === newNodes.length) {
                while (length--) {
                    var newNode = newNodes[length];
                    var newNodeName = newNode.nodeName;

                    if (newNodeName === 'INPUT' || newNodeName === 'OPTION' || newNodeName === 'IFRAME') {
                        var originalNode = originalNodes[length];
                        var originalNodeName = originalNode.nodeName;

                        if (originalNodeName === newNodeName) {
                            var prop = null;

                            if (newNodeName === 'OPTION') {
                                prop = 'selected';
                            }
                            else if (newNodeName === 'INPUT' && (newNode.type === 'checkbox' || newNode.type ===
                                'radio')) {
                                prop = 'checked';
                            }
                            else if (newNodeName === 'IFRAME') {
                                newNode.src = '';
                            }

                            if (prop !== null) {
                                toggleNode(newNode, originalNode, prop);
                            }
                        }
                    }
                }
            }

            var bodyHTML = bodyElClone.innerHTML;

            bodyHTML = bodyHTML.replace(REGEX_CLONE_NODE_CLEANUP, TAG_REPLACE_ORIGINAL).replace(REGEX_TAG,
                TAG_REPLACE_FONT);

            bodyClone.innerHTML = bodyHTML;

            // Post processing the DOM in order to move IFRAME nodes

            newNodes = bodyClone.getElementsByTagName('IFRAME');
            originalNodes = bodyEl.getElementsByTagName('IFRAME');

            length = originalNodes.length;

            if (length === newNodes.length) {
                while (length--) {
                    var newNodeIframe = newNodes[length];
                    var originalNodeIframe = originalNodes[length];

                    // According to quirksmode.org, swapNode is supported on all major IE versions
                    originalNodeIframe.swapNode(newNodeIframe);
                }
            }
        },

        /**
         * Gets all CSS text from all stylesheets.
         *
         * @method _getAllCSSText
         * @protected
         * @return {Array}
         */
        _getAllCSSText: function() {
            var instance = this;

            var buffer = [];
            var styleSheets = instance._getAllStyleSheets(DOC.styleSheets, 'all');
            var rule;
            var cssText;
            var styleSheet;

            for (var i = 0; styleSheet = styleSheets[i]; i++) {
                var rules = styleSheet.rules;

                if (rules && rules.length) {
                    for (var j = 0, ruleLength = rules.length; j < ruleLength; j++) {
                        rule = rules[j];

                        if (!rule.href) {
                            cssText = instance._getCSSTextFromRule(rule);

                            buffer.push(cssText);
                        }
                    }
                }
            }

            return buffer.join(' ');
        },

        /**
         * Extracts the CSS text from a rule.
         *
         * @method _getCSSTextFromRule
         * @param rule
         * @protected
         * @return {String}
         */
        _getCSSTextFromRule: function(rule) {
            var cssText = '';

            var ruleStyle = rule.style;
            var ruleCSSText;
            var ruleSelectorText;

            if (ruleStyle && (ruleCSSText = ruleStyle.cssText) && (ruleSelectorText = rule.selectorText) &&
                REGEX_ELEMENTS_FAST.test(ruleSelectorText)) {
                BUFFER_CSS_TEXT.length = 0;

                BUFFER_CSS_TEXT.push(ruleSelectorText, '{', ruleCSSText, '}');

                cssText = BUFFER_CSS_TEXT.join(' ');
            }

            return cssText;
        },

        /**
         * Gets all stylesheets from a page.
         *
         * @method _getAllStyleSheets
         * @param styleSheet, mediaType, level, buffer
         * @protected
         * @return {Array}
         */
        _getAllStyleSheets: function(styleSheet, mediaType, level, buffer) {
            var instance = this;

            level = level || 1;

            buffer = buffer || [];

            var i;

            if (isStylesheetDefined(styleSheet)) {
                var imports = styleSheet.imports;

                mediaType = styleSheet.mediaType || mediaType;

                if (REGEX_PRINT_MEDIA.test(mediaType)) {
                    var length;

                    // IE can crash when trying to access imports more than 3 levels deep
                    if (level <= 3 && isStylesheetDefined(imports) && imports.length) {
                        for (i = 0, length = imports.length; i < length; i++) {
                            instance._getAllStyleSheets(imports[i], mediaType, level + 1, buffer);
                        }
                    }
                    else if (styleSheet.length) {
                        for (i = 0, length = styleSheet.length; i < length; i++) {
                            instance._getAllStyleSheets(styleSheet[i], mediaType, level, buffer);
                        }
                    }
                    else {
                        var rules = styleSheet.rules;
                        var ruleStyleSheet;

                        if (rules && rules.length) {
                            for (i = 0, length = rules.length; i < length; i++) {
                                ruleStyleSheet = rules[i].styleSheet;

                                if (ruleStyleSheet) {
                                    instance._getAllStyleSheets(ruleStyleSheet, mediaType, level, buffer);
                                }
                            }
                        }
                    }

                    if (!styleSheet.disabled && styleSheet.rules) {
                        buffer.push(styleSheet);
                    }
                }
            }

            mediaType = 'all';

            return buffer;
        },

        /**
         * Gets the `<body>` element.
         *
         * @method _getBodyEl
         * @protected
         * @return {Element}
         */
        _getBodyEl: function() {
            var instance = this;

            var bodyEl = instance._bodyEl;

            if (!bodyEl) {
                bodyEl = DOC.body;

                instance._bodyEl = bodyEl;
            }

            return bodyEl;
        },

        /**
         * Gets a clone of the `<body>` element.
         *
         * @method _getBodyClone
         * @protected
         * @return {Element}
         */
        _getBodyClone: function() {
            var instance = this;

            var bodyClone = instance._bodyClone;

            if (!bodyClone) {
                bodyClone = DOC.createElement('body');

                instance._bodyClone = bodyClone;
            }

            return bodyClone;
        },

        /**
         * Gets a document fragment object.
         *
         * @method _getDocFrag
         * @protected
         * @return {DocumentFragment}
         */
        _getDocFrag: function() {
            var instance = this;

            var docFrag = instance._docFrag;

            if (!docFrag) {
                docFrag = DOC.createDocumentFragment();

                html5shiv(docFrag);

                instance._docFrag = docFrag;
            }

            return docFrag;
        },

        /**
         * Gets the stylesheet from the DOM.
         *
         * @method _getStyleSheet
         * @protected
         * @return {Node}
         */
        _getStyleSheet: function() {
            var instance = this;

            var styleSheet = instance._styleSheet;

            if (!styleSheet) {
                styleSheet = DOC.createElement('style');

                var head = DOC.documentElement.firstChild;

                head.insertBefore(styleSheet, head.firstChild);

                styleSheet.media = 'print';
                styleSheet.className = 'printfix';

                instance._styleSheet = styleSheet;
            }

            return styleSheet;
        }
    }
);

A.namespace('HTML5').printFix = printFix;

printFix();


}, '3.1.0-deprecated.76', {"requires": ["collection", "aui-node-base"]});

YUI.add('aui-selector', function (A, NAME) {

/**
 * The Selector Utility.
 *
 * @module aui-selector
 */

var SELECTOR = A.Selector,

    CSS_BOOTSTRAP_SR_ONLY = A.getClassName('sr-only'),
    CSS_HIDE = A.getClassName('hide'),
    REGEX_CLIP_RECT_ZERO = new RegExp(/rect\((0(px)?(,)?(\s)?){4}\)/i),
    REGEX_HIDDEN_CLASSNAMES = new RegExp(CSS_HIDE),
    REGEX_SR_ONLY_CLASSNAMES = new RegExp(CSS_BOOTSTRAP_SR_ONLY);

SELECTOR._isNodeHidden = function(node) {
    var width = node.offsetWidth;
    var height = node.offsetHeight;
    var ignore = node.nodeName.toLowerCase() === 'tr';
    var className = node.className;
    var nodeStyle = node.style;

    var hidden = false;

    if (!ignore) {
        if (width === 0 && height === 0) {
            hidden = true;
        }
        else if (width > 0 && height > 0) {
            hidden = false;
        }
    }

    hidden = hidden || (nodeStyle.display === 'none' || nodeStyle.visibility === 'hidden') ||
        (nodeStyle.position === 'absolute' && REGEX_CLIP_RECT_ZERO.test(nodeStyle.clip)) ||
        REGEX_HIDDEN_CLASSNAMES.test(className) || REGEX_SR_ONLY_CLASSNAMES.test(className);

    return hidden;
};

var testNodeType = function(type) {
    return function(node) {
        return node.type === type;
    };
};

/**
 * Augment the [YUI3 Selector](Selector.html) with more util methods.
 *
 * @class A.Selector
 * @uses Selector
 * @constructor
 */
A.mix(
    SELECTOR.pseudos, {
        /**
         * Checks if the node is a button element or contains `type="button"`.
         *
         * @method button
         * @param node
         * @return {Boolean}
         */
        button: function(node) {
            return node.type === 'button' || node.nodeName.toLowerCase() === 'button';
        },

        /**
         * Checks if the node contains `type="checkbox"`.
         *
         * @method checkbox
         * @return {Boolean}
         */
        checkbox: testNodeType('checkbox'),

        /**
         * Checks if the node is checked or not.
         *
         * @method checked
         * @param node
         * @return {Boolean}
         */
        checked: function(node) {
            return node.checked === true;
        },

        /**
         * Checks if the node is disabled or not.
         *
         * @method disabled
         * @param node
         * @return {Boolean}
         */
        disabled: function(node) {
            return node.disabled === true;
        },

        /**
         * Checks if the node is empty or not.
         *
         * @method empty
         * @param node
         * @return {Boolean}
         */
        empty: function(node) {
            return !node.firstChild;
        },

        /**
         * Checks if the node is enabled or not.
         *
         * @method enabled
         * @param node
         * @return {Boolean}
         */
        enabled: function(node) {
            return node.disabled === false && node.type !== 'hidden';
        },

        /**
         * Checks if the node contains `type="file"`.
         *
         * @method file
         * @return {Boolean}
         */
        file: testNodeType('file'),

        /**
         * Checks if the node is a header (e.g. `<h1>`, `<h2>`, ...) or not.
         *
         * @method header
         * @param node
         * @return {Boolean}
         */
        header: function(node) {
            return /h\d/i.test(node.nodeName);
        },

        /**
         * Checks if the node is hidden or not.
         *
         * @method hidden
         * @param node
         * @return {Boolean}
         */
        hidden: function(node) {
            return SELECTOR._isNodeHidden(node);
        },

        /**
         * Checks if the node contains `type="image"`.
         *
         * @method image
         * @return {Boolean}
         */
        image: testNodeType('image'),

        /**
         * Checks if the node is an input (e.g. `<textarea>`, `<input>`, ...) or not.
         *
         * @method input
         * @param node
         * @return {Boolean}
         */
        input: function(node) {
            return /input|select|textarea|button/i.test(node.nodeName);
        },

        /**
         * Checks if the node contains a child or not.
         *
         * @method parent
         * @param node
         * @return {Boolean}
         */
        parent: function(node) {
            return !!node.firstChild;
        },

        /**
         * Checks if the node contains `type="password"`.
         *
         * @method password
         * @return {Boolean}
         */
        password: testNodeType('password'),

        /**
         * Checks if the node contains `type="radio"`.
         *
         * @method radio
         * @return {Boolean}
         */
        radio: testNodeType('radio'),

        /**
         * Checks if the node contains `type="reset"`.
         *
         * @method reset
         * @return {Boolean}
         */
        reset: testNodeType('reset'),

        /**
         * Checks if the node is selected or not.
         *
         * @method selected
         * @param node
         * @return {Boolean}
         */
        selected: function(node) {
            node.parentNode.selectedIndex;
            return node.selected === true;
        },

        /**
         * Checks if the node contains `type="submit"`.
         *
         * @method submit
         * @return {Boolean}
         */
        submit: testNodeType('submit'),

        /**
         * Checks if the node contains `type="text"`.
         *
         * @method text
         * @return {Boolean}
         */
        text: testNodeType('text'),

        /**
         * Checks if the node is visible or not.
         *
         * @method visible
         * @param node
         * @return {Boolean}
         */
        visible: function(node) {
            return !SELECTOR._isNodeHidden(node);
        }
    }
);


}, '3.1.0-deprecated.76', {"requires": ["selector-css3", "aui-classnamemanager"]});

YUI.add('aui-timer', function (A, NAME) {

/**
 * Utility for timing logics used to manage [JavaScript Timer
 * Congestion](http://fitzgeraldnick.com/weblog/40/) problems.
 *
 * @module aui-timer
 */

var Lang = A.Lang,
    now = Lang.now,
    isEmpty = A.Object.isEmpty,

    aArray = A.Array;

/**
 * A base class for Timer.
 *
 * @class A.Timer
 * @constructor
 */
var Timer = {

    /**
     * Cancels repeated action which was set up using `setInterval` function.
     *
     * @method clearInterval
     * @param id
     */
    clearInterval: function(id) {
        var instance = Timer;

        instance.unregister(true, id);
    },

    /**
     * Clears the delay set by `setTimeout` function.
     *
     * @method clearTimeout
     * @param id
     */
    clearTimeout: function(id) {
        var instance = Timer;

        instance.unregister(false, id);
    },

    /**
     * Defines the fixed time delay between each interval.
     *
     * @method intervalTime
     * @param newInterval
     * @return {Number}
     */
    intervalTime: function(newInterval) {
        var instance = Timer;

        if (arguments.length) {
            instance._INTERVAL = newInterval;
        }

        return instance._INTERVAL;
    },

    /**
     * Checks if the task is repeatable or not.
     *
     * @method isRepeatable
     * @param task
     * @return {Boolean}
     */
    isRepeatable: function(task) {
        return task.repeats;
    },

    /**
     * Calls a function after a specified delay.
     *
     * @method setTimeout
     * @param fn
     * @param ms
     * @param context
     */
    setTimeout: function(fn, ms, context) {
        var instance = Timer;

        var args = aArray(arguments, 3, true);

        return instance.register(false, fn, ms, context, args);
    },

    /**
     * Calls a function repeatedly, with a fixed time delay between each call to
     * that function.
     *
     * @method setInterval
     * @param fn
     * @param ms
     * @param context
     */
    setInterval: function(fn, ms, context) {
        var instance = Timer;

        var args = aArray(arguments, 3, true);

        return instance.register(true, fn, ms, context, args);
    },

    /**
     * Adds a new task to the timer.
     *
     * @method register
     * @param repeats
     * @param fn
     * @param ms
     * @param context
     * @param args
     */
    register: function(repeats, fn, ms, context, args) {
        var instance = Timer;

        var id = (++A.Env._uidx);

        args = args || [];

        args.unshift(fn, context);

        instance._TASKS[id] = instance._create(
            repeats, instance._getNearestInterval(ms), A.rbind.apply(A, args)
        );

        instance._lazyInit();

        return id;
    },

    /**
     * Runs the task function.
     *
     * @method run
     * @param task
     */
    run: function(task) {
        task.lastRunTime = now();

        return task.fn();
    },

    /**
     * Removes a task from the timer.
     *
     * @method unregister
     * @param repeats
     * @param id
     */
    unregister: function(repeats, id) {
        var instance = Timer;

        var tasks = instance._TASKS;

        var task = tasks[id];

        instance._lazyDestroy();

        return task && task.repeats === repeats && delete tasks[id];
    },

    /**
     * Creates a collection of timer definitions.
     *
     * @method _create
     * @param repeats
     * @param ms
     * @param fn
     * @protected
     * @return {Object}
     */
    _create: function(repeats, ms, fn) {
        return {
            fn: fn,
            lastRunTime: now(),
            next: ms,
            repeats: repeats,
            timeout: ms
        };
    },

    /**
     * Subtracts the current time with the last run time. The result of this
     * operation is subtracted with the task timeout.
     *
     * @method _decrementNextRunTime
     * @param tasks
     * @protected
     */
    _decrementNextRunTime: function(task) {
        return task.next = task.timeout - (now() - task.lastRunTime);
    },

    /**
     * Calculates the nearest interval by using the modulus of the argument with
     * the interval as reference.
     *
     * @method _getNearestInterval
     * @param num
     * @protected
     * @return {Number}
     */
    _getNearestInterval: function(num) {
        var instance = Timer;

        var interval = instance._INTERVAL;

        var delta = num % interval;

        var nearestInterval;

        if (delta < interval / 2) {
            nearestInterval = num - delta;
        }
        else {
            nearestInterval = num + interval - delta;
        }

        return nearestInterval;
    },

    /**
     * Checks if the timer is initialized and empty, then calls the
     * `clearTimeout` function using the global interval id.
     *
     * @method _lazyDestroy
     * @protected
     */
    _lazyDestroy: function() {
        var instance = Timer;

        if (instance._initialized && isEmpty(instance._TASKS)) {
            clearTimeout(instance._globalIntervalId);

            instance._initialized = false;
        }
    },

    /**
     * Checks if the timer is initialized and contains a task, then calls the
     * `setTimeout` function and stores the global interval id.
     *
     * @method _lazyInit
     * @protected
     */
    _lazyInit: function() {
        var instance = Timer;

        if (!instance._initialized && !isEmpty(instance._TASKS)) {
            instance._lastRunTime = now();

            instance._globalIntervalId = setTimeout(
                instance._runner, instance._INTERVAL
            );

            instance._initialized = true;
        }
    },

    /**
     * Goes through all pending tasks and initializes its timer or unregisters
     * it depending on the task status.
     *
     * @method _loop
     * @param i
     * @param pendingTasks
     * @param length
     * @protected
     */
    _loop: function(i, pendingTasks, length) {
        var instance = Timer;

        var interval = instance._INTERVAL;
        var tasks = instance._TASKS;

        var halfInterval = interval / 2;

        for (var start = now(); i < length && now() - start < 50; i++) {
            var taskId = pendingTasks[i];
            var task = tasks[taskId];

            if (task && instance._decrementNextRunTime(task) < halfInterval) {
                instance.run(task);

                if (instance.isRepeatable(task)) {
                    instance._resetNextRunTime(task);
                }
                else {
                    instance.unregister(false, taskId);
                }
            }
        }

        if (instance._initialized) {
            if (i < length) {
                instance._globalIntervalId = setTimeout(instance._loop, 10);
            }
            else {
                instance._globalIntervalId = setTimeout(
                    instance._runner, interval
                );
            }
        }
    },

    /**
     * Gets the arguments to call the `_loop` method.
     *
     * @method _runner
     * @protected
     */
    _runner: function() {
        var instance = Timer;

        var i = 0;
        var pendingTasks = A.Object.keys(instance._TASKS);
        var length = pendingTasks.length;

        instance._loop(i, pendingTasks, length);
    },

    /**
     * Resets the next run time.
     *
     * @method _resetNextRunTime
     * @param task
     * @protected
     */
    _resetNextRunTime: function(task) {
        return task.next = task.timeout;
    },

    _INTERVAL: 50,
    _TASKS: {},

    _lastRunTime: 0,
    _globalIntervalId: 0,
    _initialized: false
};

/**
 * Cancels repeated action which was set up using `setInterval` function.
 *
 * @method A.clearInterval
 * @static
 * @param id
 */
A.clearInterval = Timer.clearInterval;

/**
 * Clears the delay set by `setTimeout` function.
 *
 * @method A.clearTimeout
 * @static
 * @param id
 */
A.clearTimeout = Timer.clearTimeout;

/**
 * Calls a function repeatedly, with a fixed time delay between each call to
 * that function.
 *
 * @method A.setInterval
 * @static
 * @param fn
 * @param ms
 * @param context
 */
A.setInterval = Timer.setInterval;

/**
 * Calls a function after a specified delay.
 *
 * @method A.setTimeout
 * @static
 * @param fn
 * @param ms
 * @param context
 */
A.setTimeout = Timer.setTimeout;

A.Timer = Timer;


}, '3.1.0-deprecated.76', {"requires": ["oop"]});

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

/**
 * @deprecated As of Athanasius (7.3.x), with no direct replacement
 */
YUI.add('liferay-browser-selectors', function (A) {
  var REGEX_VERSION_DOT = /\./g;
  var YUI3_JS_ENABLED = 'yui3-js-enabled';

  var parseVersionNumber = function parseVersionNumber(str) {
    var count = 0;
    return parseFloat(str.replace(REGEX_VERSION_DOT, function () {
      return count++ == 1 ? '' : '.';
    }));
  };

  var DEFAULTS_VERSION = ['0', '0'];

  var getVersion = function getVersion(regex, userAgent) {
    var version = (userAgent.match(regex) || DEFAULTS_VERSION)[1];
    return parseVersionNumber(version);
  };

  var BROWSERS = ['ie', 'opera', 'chrome', 'edge', 'aol', 'camino', 'firefox', 'flock', 'mozilla', 'netscape', 'icab', 'konqueror', 'safari'];
  var MAP_OS_SELECTORS = {
    macintosh: 'mac',
    windows: 'win'
  };
  var nav = navigator;
  var CONFIG = A.config;
  var DOC = CONFIG.doc;
  var userAgent = nav.userAgent;
  var UA = A.UA;
  var OS = UA.os;
  var UAX = {
    agent: userAgent,
    aol: 0,
    browser: 0,
    camino: 0,
    firefox: 0,
    flock: 0,
    icab: 0,
    konqueror: 0,
    mozilla: 0,
    netscape: 0,
    safari: 0
  };
  UAX.mac = OS == 'macintosh';
  UAX.rhino = OS == 'rhino';
  UAX.win = OS == 'windows';
  var BrowserSelectors = {
    getSelectors: function getSelectors() {
      // The methods in this if block only run once across all instances
      if (!UA.selectors) {
        if (userAgent.indexOf('Edge') !== -1) {
          UAX.edge = getVersion(/Edge\/([^\s]*)/, userAgent);
        }

        if (UA.ie) {
          UAX.aol = getVersion(/America Online Browser ([^\s]*);/, userAgent);
          var docMode = DOC.documentMode;

          if (docMode) {
            UA.browser = UA.ie;
            UA.ie = docMode;
          }
        } else if (UA.gecko) {
          UAX.netscape = getVersion(/(Netscape|Navigator)\/([^\s]*)/, userAgent);
          UAX.flock = getVersion(/Flock\/([^\s]*)/, userAgent);
          UAX.camino = getVersion(/Camino\/([^\s]*)/, userAgent);
          UAX.firefox = getVersion(/Firefox\/([^\s]*)/, userAgent);
        } else if (UA.webkit) {
          UAX.safari = getVersion(/Version\/([^\s]*) Safari/, userAgent);
        } else {
          UAX.icab = getVersion(/iCab(?:\/|\s)?([^\s]*)/, userAgent);
          UAX.konqueror = getVersion(/Konqueror\/([^\s]*)/, userAgent);
        }

        if (!UAX.win && !UAX.mac) {
          var linux = /Linux/.test(userAgent);
          var sun = /Solaris|SunOS/.test(userAgent);

          if (linux) {
            UA.os = 'linux';
            UAX.linux = linux;
          } else if (sun) {
            UA.os = 'sun';
            UAX.sun = sun;
          }
        }

        var touch = UA.touchEnabled;
        UAX.touch = touch;
        UAX.touchMobile = touch && !!UA.mobile;
        A.mix(UA, UAX);
        var browserList = [];
        var versionMajor = 0;
        var browser;
        var uaVersionMajor;
        var uaVersionMinor;
        var version;
        var versionObj = {
          major: versionMajor,
          string: ''
        };
        var i = BROWSERS.length;

        while (i--) {
          browser = BROWSERS[i];
          version = UA[browser];

          if (version > 0) {
            versionMajor = parseInt(version, 10);
            uaVersionMajor = browser + versionMajor;
            uaVersionMinor = browser + version;

            if (String(version).indexOf('.') > -1) {
              uaVersionMinor = uaVersionMinor.replace(/\.(\d).*/, '-$1');
            } else {
              uaVersionMinor += '-0';
            }

            browserList.push(browser, uaVersionMajor, uaVersionMinor);
            versionObj.string = browser + '';
            versionObj.major = versionMajor;
          }
        }

        UA.version = versionObj;
        UA.renderer = '';

        if (UA.ie) {
          UA.renderer = 'trident';
        } else if (UA.edge) {
          UA.renderer = 'edgeHTML';
        } else if (UA.gecko) {
          UA.renderer = 'gecko';
        } else if (UA.webkit) {
          UA.renderer = 'webkit';
        } else if (UA.opera) {
          UA.renderer = 'presto';
        }

        A.UA = UA;
        /*
         * Browser selectors
         */

        var selectors = [UA.renderer, 'js'].concat(browserList);
        var osSelector = MAP_OS_SELECTORS[UA.os] || UA.os;
        selectors.push(osSelector);

        if (UA.mobile) {
          selectors.push('mobile');
        }

        if (UA.secure) {
          selectors.push('secure');
        }

        if (UA.touch) {
          selectors.push('touch');
        }

        UA.selectors = selectors.join(' ');
        var svg;
        var vml;
        vml = !(svg = !!(CONFIG.win.SVGAngle || DOC.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1')));

        if (vml) {
          var behaviorObj;
          var div = DOC.createElement('div');
          div.innerHTML = '<v:shape adj="1"/>';
          behaviorObj = div.firstChild;
          behaviorObj.style.behavior = 'url(#default#VML)';

          if (!(behaviorObj && _typeof(behaviorObj.adj) == 'object')) {
            vml = false;
          }

          div = null;
        }

        YUI._VML = vml;
        YUI._SVG = svg;
        UA.vml = YUI._VML;
        UA.svg = YUI._SVG;
      }

      return UA.selectors;
    },
    run: function run() {
      var documentElement = DOC.documentElement;
      var selectors = this.getSelectors();
      UA.dir = documentElement.getAttribute('dir') || 'ltr';

      if (documentElement.className.indexOf(UA.dir) === -1) {
        selectors += ' ' + UA.dir;
      }

      if (documentElement.className.indexOf(YUI3_JS_ENABLED) === -1 && selectors.indexOf(YUI3_JS_ENABLED) === -1) {
        selectors += ' ' + YUI3_JS_ENABLED;
      }

      documentElement.className += ' ' + selectors;
    }
  };
  Liferay.BrowserSelectors = BrowserSelectors;
}, '', {
  requires: ['yui-base']
});
//# sourceMappingURL=browser_selectors.js.map
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */
AUI.add('liferay-form', function (A) {
  var AArray = A.Array;
  var Lang = A.Lang;
  var DEFAULTS_FORM_VALIDATOR = A.config.FormValidator;
  var defaultAcceptFiles = DEFAULTS_FORM_VALIDATOR.RULES.acceptFiles;
  var TABS_SECTION_STR = 'TabsSection';
  var REGEX_NUMBER = /^[+-]?(\d+)([.|,]\d+)*([eE][+-]?\d+)?$/;
  var REGEX_URL = /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(https?:\/\/|www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))((.*):(\d*)\/?(.*))?)/;

  var acceptFiles = function acceptFiles(val, node, ruleValue) {
    if (ruleValue && ruleValue.split(',').includes('*')) {
      return true;
    }

    return defaultAcceptFiles(val, node, ruleValue);
  };

  var maxFileSize = function maxFileSize(_val, node, ruleValue) {
    var nodeType = node.get('type').toLowerCase();

    if (nodeType === 'file') {
      return ruleValue === 0 || node._node.files[0].size <= ruleValue;
    }

    return true;
  };

  var number = function number(val, _node, _ruleValue) {
    return REGEX_NUMBER && REGEX_NUMBER.test(val);
  };

  var url = function url(val, _node, _ruleValue) {
    return REGEX_URL && REGEX_URL.test(val);
  };

  A.mix(DEFAULTS_FORM_VALIDATOR.RULES, {
    acceptFiles: acceptFiles,
    maxFileSize: maxFileSize,
    number: number,
    url: url
  }, true);
  A.mix(DEFAULTS_FORM_VALIDATOR.STRINGS, {
    DEFAULT: 'Please\x20fix\x20this\x20field\x2e',
    acceptFiles: 'Please\x20enter\x20a\x20file\x20with\x20a\x20valid\x20extension\x20\x28\x7b0\x7d\x29\x2e',
    alpha: 'Please\x20enter\x20only\x20alpha\x20characters\x2e',
    alphanum: 'Please\x20enter\x20only\x20alphanumeric\x20characters\x2e',
    date: 'Please\x20enter\x20a\x20valid\x20date\x2e',
    digits: 'Please\x20enter\x20only\x20digits\x2e',
    email: 'Please\x20enter\x20a\x20valid\x20email\x20address\x2e',
    equalTo: 'Please\x20enter\x20the\x20same\x20value\x20again\x2e',
    max: 'Please\x20enter\x20a\x20value\x20less\x20than\x20or\x20equal\x20to\x20\x7b0\x7d\x2e',
    maxFileSize: 'Please\x20enter\x20a\x20file\x20with\x20a\x20valid\x20file\x20size\x20no\x20larger\x20than\x20\x7b0\x7d\x2e',
    maxLength: 'Please\x20enter\x20no\x20more\x20than\x20\x7b0\x7d\x20characters\x2e',
    min: 'Please\x20enter\x20a\x20value\x20greater\x20than\x20or\x20equal\x20to\x20\x7b0\x7d\x2e',
    minLength: 'Please\x20enter\x20at\x20least\x20\x7b0\x7d\x20characters\x2e',
    number: 'Please\x20enter\x20a\x20valid\x20number\x2e',
    range: 'Please\x20enter\x20a\x20value\x20between\x20\x7b0\x7d\x20and\x20\x7b1\x7d\x2e',
    rangeLength: 'Please\x20enter\x20a\x20value\x20between\x20\x7b0\x7d\x20and\x20\x7b1\x7d\x20characters\x20long\x2e',
    required: 'This\x20field\x20is\x20required\x2e',
    url: 'Please\x20enter\x20a\x20valid\x20URL\x2e'
  }, true);
  var Form = A.Component.create({
    _INSTANCES: {},
    ATTRS: {
      fieldRules: {
        setter: function setter(val) {
          var instance = this;

          instance._processFieldRules(val);

          return val;
        }
      },
      id: {},
      namespace: {},
      onSubmit: {
        valueFn: function valueFn() {
          var instance = this;
          return instance._onSubmit;
        }
      },
      validateOnBlur: {
        validator: Lang.isBoolean,
        value: true
      }
    },
    EXTENDS: A.Base,
    get: function get(id) {
      var instance = this;
      return instance._INSTANCES[id];
    },
    prototype: {
      _afterGetFieldsByName: function _afterGetFieldsByName(fieldName) {
        var instance = this;
        var editorString = 'Editor';

        if (fieldName.lastIndexOf(editorString) === fieldName.length - editorString.length) {
          var formNode = instance.formNode;
          return new A.Do.AlterReturn('Return editor dom element', formNode.one('#' + fieldName));
        }
      },
      _bindForm: function _bindForm() {
        var instance = this;
        var formNode = instance.formNode;
        var formValidator = instance.formValidator;
        formValidator.on('submit', A.bind('_onValidatorSubmit', instance));
        formValidator.on('submitError', A.bind('_onSubmitError', instance));
        formNode.delegate(['blur', 'focus'], A.bind('_onFieldFocusChange', instance), 'button,input,select,textarea');
        formNode.delegate(['blur', 'input'], A.bind('_onEditorBlur', instance), 'div[contenteditable="true"]');
        A.Do.after('_afterGetFieldsByName', formValidator, 'getFieldsByName', instance);
      },
      _defaultSubmitFn: function _defaultSubmitFn(event) {
        var instance = this;

        if (!event.stopped) {
          submitForm(instance.form);
        }
      },
      _findRuleIndex: function _findRuleIndex(fieldRules, fieldName, validatorName) {
        var ruleIndex = -1;
        AArray.some(fieldRules, function (element, index) {
          if (element.fieldName === fieldName && element.validatorName === validatorName) {
            ruleIndex = index;
            return true;
          }
        });
        return ruleIndex;
      },
      _focusInvalidFieldTab: function _focusInvalidFieldTab() {
        var instance = this;
        var formNode = instance.formNode;
        var field = formNode.one('.' + instance.formValidator.get('errorClass'));

        if (field) {
          var fieldWrapper = field.ancestor('form > fieldset > div');
          var formTabs = formNode.one('.lfr-nav');

          if (fieldWrapper && formTabs) {
            var tabs = formTabs.all('.nav-item');
            var tabsNamespace = formTabs.getAttribute('data-tabs-namespace');
            var tabNames = AArray.map(tabs._nodes, function (tab) {
              return tab.getAttribute('data-tab-name');
            });
            var fieldWrapperId = fieldWrapper.getAttribute('id').slice(0, -TABS_SECTION_STR.length);
            var fieldTabId = AArray.find(tabs._nodes, function (tab) {
              return tab.getAttribute('id').indexOf(fieldWrapperId) !== -1;
            });
            Liferay.Portal.Tabs.show(tabsNamespace, tabNames, fieldTabId.getAttribute('data-tab-name'));
          }
        }
      },
      _onEditorBlur: function _onEditorBlur(event) {
        var instance = this;
        var formValidator = instance.formValidator;
        formValidator.validateField(event.target);
      },
      _onFieldFocusChange: function _onFieldFocusChange(event) {
        var row = event.currentTarget.ancestor('.field');

        if (row) {
          row.toggleClass('field-focused', event.type === 'focus');
        }
      },
      _onSubmit: function _onSubmit(event) {
        var instance = this;
        event.preventDefault();
        setTimeout(function () {
          instance._defaultSubmitFn(event);
        }, 0);
      },
      _onSubmitError: function _onSubmitError() {
        var instance = this;
        var collapsiblePanels = instance.formNode.all('.panel-collapse');
        collapsiblePanels.each(function (panel) {
          var errorFields = panel.get('children').all('.has-error');

          if (errorFields.size() > 0 && !panel.hasClass('in')) {
            var panelNode = panel.getDOM();
            Liferay.CollapseProvider.show({
              panel: panelNode
            });
          }
        });
      },
      _onValidatorSubmit: function _onValidatorSubmit(event) {
        var instance = this;
        var onSubmit = instance.get('onSubmit');
        onSubmit.call(instance, event.validator.formEvent);
      },
      _processFieldRule: function _processFieldRule(rules, strings, rule) {
        var instance = this;
        var value = true;
        var fieldName = rule.fieldName;
        var validatorName = rule.validatorName;
        var field = this.formValidator.getField(fieldName);

        if (field) {
          var fieldNode = field.getDOMNode();
          A.Do.after('_setFieldAttribute', fieldNode, 'setAttribute', instance, fieldName);
          A.Do.after('_removeFieldAttribute', fieldNode, 'removeAttribute', instance, fieldName);
        }

        if ((rule.body || rule.body === 0) && !rule.custom) {
          value = rule.body;
        }

        var fieldRules = rules[fieldName];

        if (!fieldRules) {
          fieldRules = {};
          rules[fieldName] = fieldRules;
        }

        fieldRules[validatorName] = value;

        if (rule.custom) {
          DEFAULTS_FORM_VALIDATOR.RULES[validatorName] = rule.body;
        }

        var errorMessage = rule.errorMessage;

        if (errorMessage) {
          var fieldStrings = strings[fieldName];

          if (!fieldStrings) {
            fieldStrings = {};
            strings[fieldName] = fieldStrings;
          }

          fieldStrings[validatorName] = errorMessage;
        }
      },
      _processFieldRules: function _processFieldRules(fieldRules) {
        var instance = this;

        if (!fieldRules) {
          fieldRules = instance.get('fieldRules');
        }

        var fieldStrings = {};
        var rules = {};

        for (var rule in fieldRules) {
          instance._processFieldRule(rules, fieldStrings, fieldRules[rule]);
        }

        var formValidator = instance.formValidator;

        if (formValidator) {
          formValidator.set('fieldStrings', fieldStrings);
          formValidator.set('rules', rules);
        }
      },
      _removeFieldAttribute: function _removeFieldAttribute(name, fieldName) {
        if (name === 'disabled') {
          this.formValidator.validateField(fieldName);
        }
      },
      _setFieldAttribute: function _setFieldAttribute(name, value, fieldName) {
        if (name === 'disabled') {
          this.formValidator.resetField(fieldName);
        }
      },
      _validatable: function _validatable(field) {
        var result;

        if (field.test(':disabled')) {
          result = new A.Do.Halt();
        }

        return result;
      },
      addRule: function addRule(fieldName, validatorName, errorMessage, body, custom) {
        var instance = this;
        var fieldRules = instance.get('fieldRules');

        var ruleIndex = instance._findRuleIndex(fieldRules, fieldName, validatorName);

        if (ruleIndex == -1) {
          fieldRules.push({
            body: body || '',
            custom: custom || false,
            errorMessage: errorMessage || '',
            fieldName: fieldName,
            validatorName: validatorName
          });

          instance._processFieldRules(fieldRules);
        }
      },
      initializer: function initializer() {
        var instance = this;
        var id = instance.get('id');
        var form = document[id];
        var formNode = A.one(form);
        instance.form = form;
        instance.formNode = formNode;

        if (formNode) {
          var formValidator = new A.FormValidator({
            boundingBox: formNode,
            validateOnBlur: instance.get('validateOnBlur')
          });
          A.Do.before('_focusInvalidFieldTab', formValidator, 'focusInvalidField', instance);
          A.Do.before('_validatable', formValidator, 'validatable', instance);
          instance.formValidator = formValidator;

          instance._processFieldRules();

          instance._bindForm();
        }
      },
      removeRule: function removeRule(fieldName, validatorName) {
        var instance = this;
        var fieldRules = instance.get('fieldRules');

        var ruleIndex = instance._findRuleIndex(fieldRules, fieldName, validatorName);

        if (ruleIndex != -1) {
          var rule = fieldRules[ruleIndex];
          instance.formValidator.resetField(rule.fieldName);
          fieldRules.splice(ruleIndex, 1);

          instance._processFieldRules(fieldRules);
        }
      }
    },

    /*
     * @deprecated As of Mueller (7.2.x), with no direct replacement
     */
    register: function register(config) {
      var instance = this;
      var form = new Liferay.Form(config);
      var formName = config.id || config.namespace;
      instance._INSTANCES[formName] = form;
      Liferay.fire('form:registered', {
        form: form,
        formName: formName
      });
      return form;
    }
  });
  Liferay.Form = Form;
}, '', {
  requires: ['aui-base', 'aui-form-validator']
});
//# sourceMappingURL=form.js.map
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

/**
 * The Form Placeholders Component.
 *
 * @deprecated As of Mueller (7.2.x), with no direct replacement
 * @module liferay-form-placeholders
 */
AUI.add('liferay-form-placeholders', function (A) {
  var ANode = A.Node;
  var CSS_PLACEHOLDER = 'text-placeholder';
  var MAP_IGNORE_ATTRS = {
    id: 1,
    name: 1,
    type: 1
  };
  var SELECTOR_PLACEHOLDER_INPUTS = 'input[placeholder], textarea[placeholder]';
  var STR_BLANK = '';
  var STR_DATA_TYPE_PASSWORD_PLACEHOLDER = 'data-type-password-placeholder';
  var STR_FOCUS = 'focus';
  var STR_PASSWORD = 'password';
  var STR_PLACEHOLDER = 'placeholder';
  var STR_SPACE = ' ';
  var STR_TYPE = 'type';
  var Placeholders = A.Component.create({
    EXTENDS: A.Plugin.Base,
    NAME: 'placeholders',
    NS: STR_PLACEHOLDER,
    prototype: {
      _initializePasswordNode: function _initializePasswordNode(field) {
        var placeholder = ANode.create('<input name="' + field.attr('name') + '_pass_placeholder" type="text" />');
        Liferay.Util.getAttributes(field, function (value, name) {
          var result = false;

          if (!MAP_IGNORE_ATTRS[name]) {
            if (name === 'class') {
              value += STR_SPACE + CSS_PLACEHOLDER;
            }

            placeholder.setAttribute(name, value);
          }

          return result;
        });
        placeholder.val(field.attr(STR_PLACEHOLDER));
        placeholder.attr(STR_DATA_TYPE_PASSWORD_PLACEHOLDER, true);
        field.placeBefore(placeholder);
        field.hide();
      },
      _removePlaceholders: function _removePlaceholders() {
        var instance = this;
        var formNode = instance.host.formNode;
        var placeholderInputs = formNode.all(SELECTOR_PLACEHOLDER_INPUTS);
        placeholderInputs.each(function (item) {
          if (item.val() == item.attr(STR_PLACEHOLDER)) {
            item.val(STR_BLANK);
          }
        });
      },
      _toggleLocalizedPlaceholders: function _toggleLocalizedPlaceholders(event, currentTarget) {
        var placeholder = currentTarget.attr(STR_PLACEHOLDER);

        if (placeholder) {
          var value = currentTarget.val();

          if (event.type === STR_FOCUS) {
            if (value === placeholder) {
              currentTarget.removeClass(CSS_PLACEHOLDER);
            }
          } else if (!value) {
            currentTarget.val(placeholder);
            currentTarget.addClass(CSS_PLACEHOLDER);
          }
        }
      },
      _togglePasswordPlaceholders: function _togglePasswordPlaceholders(event, currentTarget) {
        var placeholder = currentTarget.attr(STR_PLACEHOLDER);

        if (placeholder) {
          if (event.type === STR_FOCUS) {
            if (currentTarget.hasAttribute(STR_DATA_TYPE_PASSWORD_PLACEHOLDER)) {
              currentTarget.hide();
              var passwordField = currentTarget.next();
              passwordField.show();
              setTimeout(function () {
                Liferay.Util.focusFormField(passwordField);
              }, 0);
            }
          } else if (currentTarget.attr(STR_TYPE) === STR_PASSWORD) {
            var value = currentTarget.val();

            if (!value) {
              currentTarget.hide();
              currentTarget.previous().show();
            }
          }
        }
      },
      _togglePlaceholders: function _togglePlaceholders(event) {
        var instance = this;
        var currentTarget = event.currentTarget;

        if (currentTarget.hasAttribute(STR_DATA_TYPE_PASSWORD_PLACEHOLDER) || currentTarget.attr(STR_TYPE) === STR_PASSWORD) {
          instance._togglePasswordPlaceholders(event, currentTarget);
        } else if (currentTarget.hasClass('language-value')) {
          instance._toggleLocalizedPlaceholders(event, currentTarget);
        } else {
          var placeholder = currentTarget.attr(STR_PLACEHOLDER);

          if (placeholder) {
            var value = currentTarget.val();

            if (event.type === STR_FOCUS) {
              if (value === placeholder) {
                currentTarget.val(STR_BLANK);
                currentTarget.removeClass(CSS_PLACEHOLDER);
              }
            } else if (!value) {
              currentTarget.val(placeholder);
              currentTarget.addClass(CSS_PLACEHOLDER);
            }
          }
        }
      },
      initializer: function initializer() {
        var instance = this;
        var host = instance.get('host');
        var formNode = host.formNode;

        if (formNode) {
          var placeholderInputs = formNode.all(SELECTOR_PLACEHOLDER_INPUTS);
          placeholderInputs.each(function (item) {
            if (!item.val()) {
              if (item.attr(STR_TYPE) === STR_PASSWORD) {
                instance._initializePasswordNode(item);
              } else {
                item.addClass(CSS_PLACEHOLDER);
                item.val(item.attr(STR_PLACEHOLDER));
              }
            }
          });
          instance.host = host;
          instance.beforeHostMethod('_onValidatorSubmit', instance._removePlaceholders, instance);
          instance.beforeHostMethod('_onFieldFocusChange', instance._togglePlaceholders, instance);
        }
      }
    }
  });
  Liferay.Form.Placeholders = Placeholders;
  A.Base.plug(Liferay.Form, Placeholders);
}, '', {
  requires: ['liferay-form', 'plugin']
});
//# sourceMappingURL=form_placeholders.js.map
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

/**
 * The Icon Component.
 *
 * @deprecated As of Mueller (7.2.x), with no direct replacement
 * @module liferay-icon
 */
AUI.add('liferay-icon', function (A) {
  var _ICON_REGISTRY = {};
  var Icon = {
    _forcePost: function _forcePost(event) {
      if (!Liferay.SPA || !Liferay.SPA.app) {
        Liferay.Util.forcePost(event.currentTarget);
        event.preventDefault();
      }
    },
    _getConfig: function _getConfig(event) {
      return _ICON_REGISTRY[event.currentTarget.attr('id')];
    },
    _handleDocClick: function _handleDocClick(event) {
      var instance = this;

      var config = instance._getConfig(event);

      if (config) {
        event.preventDefault();

        if (config.useDialog) {
          instance._useDialog(event);
        } else {
          instance._forcePost(event);
        }
      }
    },
    _handleDocMouseOut: function _handleDocMouseOut(event) {
      var instance = this;

      var config = instance._getConfig(event);

      if (config && config.srcHover) {
        instance._onMouseHover(event, config.src);
      }
    },
    _handleDocMouseOver: function _handleDocMouseOver(event) {
      var instance = this;

      var config = instance._getConfig(event);

      if (config && config.srcHover) {
        instance._onMouseHover(event, config.srcHover);
      }
    },
    _onMouseHover: function _onMouseHover(event, src) {
      var img = event.currentTarget.one('img');

      if (img) {
        img.attr('src', src);
      }
    },
    _useDialog: function _useDialog(event) {
      Liferay.Util.openInDialog(event, {
        dialog: {
          destroyOnHide: true
        },
        dialogIframe: {
          bodyCssClass: 'dialog-with-footer'
        }
      });
    },
    register: function register(config) {
      var instance = this;
      var doc = A.one(A.config.doc);
      _ICON_REGISTRY[config.id] = config;

      if (!instance._docClickHandler) {
        instance._docClickHandler = doc.delegate('click', instance._handleDocClick, '.lfr-icon-item', instance);
      }

      if (!instance._docHoverHandler) {
        instance._docHoverHandler = doc.delegate('hover', instance._handleDocMouseOver, instance._handleDocMouseOut, '.lfr-icon-item', instance);
      }

      Liferay.once('screenLoad', function () {
        delete _ICON_REGISTRY[config.id];
      });
    }
  };
  Liferay.Icon = Icon;
}, '', {
  requires: ['aui-base', 'liferay-util-window']
});
//# sourceMappingURL=icon.js.map
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */
AUI.add('liferay-menu', function (A) {
  var Util = Liferay.Util;
  var ARIA_ATTR_ROLE = 'role';
  var ATTR_CLASS_NAME = 'className';
  var AUTO = 'auto';
  var CSS_BTN_PRIMARY = 'btn-primary';
  var CSS_EXTENDED = 'lfr-extended';
  var CSS_OPEN = 'open';
  var CSS_PORTLET = '.portlet';
  var DEFAULT_ALIGN_POINTS = ['tl', 'bl'];
  var EVENT_CLICK = 'click';
  var PARENT_NODE = 'parentNode';
  var STR_BOTTOM = 'b';
  var STR_LEFT = 'l';
  var STR_LTR = 'ltr';
  var STR_RIGHT = 'r';
  var STR_RTL = 'rtl';
  var STR_TOP = 't';
  var MAP_ALIGN_HORIZONTAL_OVERLAY = {
    left: STR_RIGHT,
    right: STR_LEFT
  };
  var MAP_ALIGN_HORIZONTAL_OVERLAY_RTL = {
    left: STR_LEFT,
    right: STR_RIGHT
  };
  var MAP_ALIGN_HORIZONTAL_TRIGGER = {
    left: STR_LEFT,
    right: STR_RIGHT
  };
  var MAP_ALIGN_HORIZONTAL_TRIGGER_RTL = {
    left: STR_RIGHT,
    right: STR_LEFT
  };
  var MAP_ALIGN_VERTICAL_OVERLAY = {
    down: STR_TOP,
    up: STR_BOTTOM
  };
  var MAP_ALIGN_VERTICAL_TRIGGER = {
    down: STR_BOTTOM,
    up: STR_TOP
  };
  var MAP_LIVE_SEARCH = {};
  var REGEX_DIRECTION = /\bdirection-(down|left|right|up)\b/;
  var REGEX_MAX_DISPLAY_ITEMS = /max-display-items-(\d+)/;
  var SELECTOR_ANCHOR = 'a';
  var SELECTOR_LIST_ITEM = 'li';
  var SELECTOR_SEARCH_CONTAINER = '.lfr-menu-list-search-container';
  var TPL_MENU = '<div class="open" />';

  var Menu = function Menu() {
    var instance = this;
    instance._handles = [];

    if (!Menu._INSTANCE) {
      Menu._INSTANCE = instance;
    }
  };

  Menu.prototype = {
    _closeActiveMenu: function _closeActiveMenu() {
      var instance = this;
      var menu = instance._activeMenu;

      if (menu) {
        var handles = instance._handles;
        A.Array.invoke(handles, 'detach');
        handles.length = 0;
        var overlay = instance._overlay;

        if (overlay) {
          overlay.hide();
        }

        var trigger = instance._activeTrigger;
        instance._activeMenu = null;
        instance._activeTrigger = null;

        if (trigger.hasClass(CSS_EXTENDED)) {
          trigger.removeClass(CSS_BTN_PRIMARY);
        } else {
          trigger.get(PARENT_NODE).removeClass(CSS_OPEN);
          var portlet = trigger.ancestor(CSS_PORTLET);

          if (portlet) {
            portlet.removeClass(CSS_OPEN);
          }
        }
      }
    },
    _getAlignPoints: A.cached(function (cssClass) {
      var alignPoints = DEFAULT_ALIGN_POINTS;
      var defaultOverlayHorizontalAlign = STR_RIGHT;
      var defaultTriggerHorizontalAlign = STR_LEFT;
      var mapAlignHorizontalOverlay = MAP_ALIGN_HORIZONTAL_OVERLAY;
      var mapAlignHorizontalTrigger = MAP_ALIGN_HORIZONTAL_TRIGGER;
      var langDir = Liferay.Language.direction[themeDisplay.getLanguageId()] || STR_LTR;

      if (langDir === STR_RTL) {
        defaultOverlayHorizontalAlign = STR_LEFT;
        defaultTriggerHorizontalAlign = STR_RIGHT;
        mapAlignHorizontalOverlay = MAP_ALIGN_HORIZONTAL_OVERLAY_RTL;
        mapAlignHorizontalTrigger = MAP_ALIGN_HORIZONTAL_TRIGGER_RTL;
      }

      if (cssClass.indexOf(AUTO) === -1) {
        var directionMatch = cssClass.match(REGEX_DIRECTION);
        var direction = directionMatch && directionMatch[1] || AUTO;

        if (direction != 'down') {
          var overlayHorizontal = mapAlignHorizontalOverlay[direction] || defaultOverlayHorizontalAlign;
          var overlayVertical = MAP_ALIGN_VERTICAL_OVERLAY[direction] || STR_TOP;
          var triggerHorizontal = mapAlignHorizontalTrigger[direction] || defaultTriggerHorizontalAlign;
          var triggerVertical = MAP_ALIGN_VERTICAL_TRIGGER[direction] || STR_TOP;
          alignPoints = [overlayVertical + overlayHorizontal, triggerVertical + triggerHorizontal];
        }
      }

      return alignPoints;
    }),
    _getMenu: function _getMenu(trigger) {
      var instance = this;
      var overlay = instance._overlay;

      if (!overlay) {
        var MenuOverlay = A.Component.create({
          AUGMENTS: [A.WidgetCssClass, A.WidgetPosition, A.WidgetStdMod, A.WidgetModality, A.WidgetPositionAlign, A.WidgetPositionConstrain, A.WidgetStack],
          CSS_PREFIX: 'overlay',
          EXTENDS: A.Widget,
          NAME: 'overlay'
        });
        overlay = new MenuOverlay({
          align: {
            node: trigger,
            points: DEFAULT_ALIGN_POINTS
          },
          constrain: true,
          hideClass: false,
          preventOverlap: true,
          zIndex: Liferay.zIndex.MENU
        }).render();
        Liferay.once('beforeScreenFlip', function () {
          overlay.destroy();
          instance._overlay = null;
        });
        instance._overlay = overlay;
      } else {
        overlay.set('align.node', trigger);
      }

      var listContainer = trigger.getData('menuListContainer');
      var menu = trigger.getData('menu');
      var menuHeight = trigger.getData('menuHeight');
      var liveSearch = menu && MAP_LIVE_SEARCH[menu.guid()];

      if (liveSearch) {
        liveSearch.reset();
      }

      var listItems;

      if (!menu || !listContainer) {
        listContainer = trigger.next('ul');
        listItems = listContainer.all(SELECTOR_LIST_ITEM);
        menu = A.Node.create(TPL_MENU);
        listContainer.placeBefore(menu);
        listItems.last().addClass('last');
        menu.append(listContainer);
        trigger.setData('menuListContainer', listContainer);
        trigger.setData('menu', menu);

        instance._setARIARoles(trigger, menu, listContainer);

        if (trigger.hasClass('select')) {
          listContainer.delegate('click', function (event) {
            var selectedListItem = event.currentTarget;
            var selectedListItemIcon = selectedListItem.one('i');
            var triggerIcon = trigger.one('i');

            if (selectedListItemIcon && triggerIcon) {
              var selectedListItemIconClass = selectedListItemIcon.attr('class');
              triggerIcon.attr('class', selectedListItemIconClass);
            }

            var selectedListItemMessage = selectedListItem.one('.lfr-icon-menu-text');
            var triggerMessage = trigger.one('.lfr-icon-menu-text');

            if (selectedListItemMessage && triggerMessage) {
              triggerMessage.setContent(selectedListItemMessage.text());
            }
          }, SELECTOR_LIST_ITEM);
        }
      }

      overlay.setStdModContent(A.WidgetStdMod.BODY, menu);

      if (!menuHeight) {
        menuHeight = instance._getMenuHeight(trigger, menu, listItems || listContainer.all(SELECTOR_LIST_ITEM));
        trigger.setData('menuHeight', menuHeight);

        if (menuHeight !== AUTO) {
          listContainer.setStyle('maxHeight', menuHeight);
        }
      }

      instance._getFocusManager();

      return menu;
    },
    _getMenuHeight: function _getMenuHeight(trigger, menu, listItems) {
      var instance = this;
      var cssClass = trigger.attr(ATTR_CLASS_NAME);
      var height = AUTO;

      if (cssClass.indexOf('lfr-menu-expanded') === -1) {
        var params = REGEX_MAX_DISPLAY_ITEMS.exec(cssClass);
        var maxDisplayItems = params && parseInt(params[1], 10);

        if (maxDisplayItems && listItems.size() > maxDisplayItems) {
          instance._getLiveSearch(trigger, trigger.getData('menu'));

          height = 0;
          var heights = listItems.slice(0, maxDisplayItems).get('offsetHeight');

          for (var i = heights.length - 1; i >= 0; i--) {
            height += heights[i];
          }
        }
      }

      return height;
    },
    _positionActiveMenu: function _positionActiveMenu() {
      var instance = this;
      var menu = instance._activeMenu;
      var trigger = instance._activeTrigger;

      if (menu) {
        var cssClass = trigger.attr(ATTR_CLASS_NAME);
        var overlay = instance._overlay;
        var align = overlay.get('align');
        var listNode = menu.one('ul');
        var listNodeHeight = listNode.get('offsetHeight');
        var listNodeWidth = listNode.get('offsetWidth');
        var modalMask = false;
        align.points = instance._getAlignPoints(cssClass);
        menu.addClass('lfr-icon-menu-open');

        if (Util.isPhone() || Util.isTablet()) {
          overlay.hide();
          modalMask = true;
        }

        overlay.setAttrs({
          align: align,
          centered: false,
          height: listNodeHeight,
          modal: modalMask,
          width: listNodeWidth
        });

        if (!Util.isPhone() && !Util.isTablet()) {
          var focusManager = overlay.bodyNode.focusManager;

          if (focusManager) {
            focusManager.focus(0);
          }
        }

        overlay.show();

        if (cssClass.indexOf(CSS_EXTENDED) > -1) {
          trigger.addClass(CSS_BTN_PRIMARY);
        } else {
          trigger.get(PARENT_NODE).addClass(CSS_OPEN);
          var portlet = trigger.ancestor(CSS_PORTLET);

          if (portlet) {
            portlet.addClass(CSS_OPEN);
          }
        }
      }
    },
    _setARIARoles: function _setARIARoles(trigger, menu) {
      var links = menu.all(SELECTOR_ANCHOR);
      var searchContainer = menu.one(SELECTOR_SEARCH_CONTAINER);
      var listNode = menu.one('ul');
      var ariaLinksAttr = 'menuitem';
      var ariaListNodeAttr = 'menu';

      if (searchContainer) {
        ariaListNodeAttr = 'listbox';
        ariaListNodeAttr = 'option';
      }

      listNode.setAttribute(ARIA_ATTR_ROLE, ariaListNodeAttr);
      links.set(ARIA_ATTR_ROLE, ariaLinksAttr);
      trigger.attr({
        'aria-haspopup': true,
        role: 'button'
      });
      listNode.setAttribute('aria-labelledby', trigger.guid());
    }
  };

  Menu.handleFocus = function (id) {
    var node = A.one(id);

    if (node) {
      node.delegate('mouseenter', A.rbind(Menu._targetLink, node, 'focus'), SELECTOR_LIST_ITEM);
      node.delegate('mouseleave', A.rbind(Menu._targetLink, node, 'blur'), SELECTOR_LIST_ITEM);
    }
  };

  var buffer = [];

  Menu.register = function (id) {
    var menuNode = document.getElementById(id);

    if (menuNode) {
      if (!Menu._INSTANCE) {
        new Menu();
      }

      buffer.push(menuNode);

      Menu._registerTask();
    }
  };

  Menu._registerTask = A.debounce(function () {
    if (buffer.length) {
      var nodes = A.all(buffer);
      nodes.on(EVENT_CLICK, A.bind('_registerMenu', Menu));
      buffer.length = 0;
    }
  }, 100);

  Menu._targetLink = function (event, action) {
    var anchor = event.currentTarget.one(SELECTOR_ANCHOR);

    if (anchor) {
      anchor[action]();
    }
  };

  Liferay.provide(Menu, '_getFocusManager', function () {
    var menuInstance = Menu._INSTANCE;
    var focusManager = menuInstance._focusManager;

    if (!focusManager) {
      var bodyNode = menuInstance._overlay.bodyNode;
      bodyNode.plug(A.Plugin.NodeFocusManager, {
        circular: true,
        descendants: 'li:not(.hide) a,input',
        focusClass: 'focus',
        keys: {
          next: 'down:40',
          previous: 'down:38'
        }
      });
      bodyNode.on('key', function () {
        var activeTrigger = menuInstance._activeTrigger;

        if (activeTrigger) {
          menuInstance._closeActiveMenu();

          activeTrigger.focus();
        }
      }, 'down:27,9');
      focusManager = bodyNode.focusManager;
      bodyNode.delegate('mouseenter', function (event) {
        if (focusManager.get('focused')) {
          focusManager.focus(event.currentTarget.one(SELECTOR_ANCHOR));
        }
      }, SELECTOR_LIST_ITEM);
      focusManager.after('activeDescendantChange', function (event) {
        var descendants = focusManager.get('descendants');
        var selectedItem = descendants.item(event.newVal);

        if (selectedItem) {
          var overlayList = bodyNode.one('ul');

          if (overlayList) {
            overlayList.setAttribute('aria-activedescendant', selectedItem.guid());
          }
        }
      });
      menuInstance._focusManager = focusManager;
    }

    focusManager.refresh();
  }, ['node-focusmanager'], true);
  Liferay.provide(Menu, '_getLiveSearch', function (_trigger, menu) {
    var id = menu.guid();
    var liveSearch = MAP_LIVE_SEARCH[id];

    if (!liveSearch) {
      var listNode = menu.one('ul');
      var results = [];
      listNode.all('li').each(function (node) {
        results.push({
          name: node.one('.taglib-text-icon').text().trim(),
          node: node
        });
      });
      liveSearch = new Liferay.MenuFilter({
        content: listNode,
        minQueryLength: 0,
        queryDelay: 0,
        resultFilters: 'phraseMatch',
        resultTextLocator: 'name',
        source: results
      });
      liveSearch.get('inputNode').swallowEvent('click');
      MAP_LIVE_SEARCH[id] = liveSearch;
    }
  }, ['liferay-menu-filter'], true);
  Liferay.provide(Menu, '_registerMenu', function (event) {
    var menuInstance = Menu._INSTANCE;
    var handles = menuInstance._handles;
    var trigger = event.currentTarget;
    var activeTrigger = menuInstance._activeTrigger;

    if (activeTrigger) {
      if (activeTrigger != trigger) {
        activeTrigger.removeClass(CSS_BTN_PRIMARY);
        activeTrigger.get(PARENT_NODE).removeClass(CSS_OPEN);
        var portlet = activeTrigger.ancestor(CSS_PORTLET);

        if (portlet) {
          portlet.removeClass(CSS_OPEN);
        }
      } else {
        menuInstance._closeActiveMenu();

        return;
      }
    }

    if (!trigger.hasClass('disabled')) {
      var menu = menuInstance._getMenu(trigger);

      menuInstance._activeMenu = menu;
      menuInstance._activeTrigger = trigger;

      if (!handles.length) {
        var listContainer = trigger.getData('menuListContainer');
        A.Event.defineOutside('touchend');
        handles.push(A.getWin().on('resize', A.debounce(menuInstance._positionActiveMenu, 200, menuInstance)), A.getDoc().on(EVENT_CLICK, menuInstance._closeActiveMenu, menuInstance), listContainer.on('touchendoutside', function (event) {
          event.preventDefault();

          menuInstance._closeActiveMenu();
        }, menuInstance), Liferay.on('dropdownShow', function (event) {
          if (event.src !== 'LiferayMenu') {
            menuInstance._closeActiveMenu();
          }
        }));
        var DDM = A.DD && A.DD.DDM;

        if (DDM) {
          handles.push(DDM.on('ddm:start', menuInstance._closeActiveMenu, menuInstance));
        }
      }

      menuInstance._positionActiveMenu();

      Liferay.fire('dropdownShow', {
        src: 'LiferayMenu'
      });
      event.halt();
    }
  }, ['aui-widget-cssclass', 'event-outside', 'event-touch', 'widget', 'widget-modality', 'widget-position', 'widget-position-align', 'widget-position-constrain', 'widget-stack', 'widget-stdmod']);
  Liferay.Menu = Menu;
}, '', {
  requires: ['array-invoke', 'aui-debounce', 'aui-node', 'portal-available-languages']
});
//# sourceMappingURL=menu.js.map
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

/**
 * @deprecated As of Athanasius (7.3.x), replaced by `Liferay.Util.openToast`.
 */
AUI.add('liferay-notice', function (A) {
  var ADOM = A.DOM;
  var ANode = A.Node;
  var Do = A.Do;
  var Lang = A.Lang;
  var CSS_ALERTS = 'has-alerts';
  var STR_CLICK = 'click';
  var STR_EMPTY = '';
  var STR_HIDE = 'hide';
  var STR_PX = 'px';
  var STR_SHOW = 'show';
  /**
   * @deprecated As of Wilberforce (7.0.x)
   *
   * OPTIONS
   *
   * Required
   * content {string}: The content of the toolbar.
   *
   * Optional
   * animationConfig {Object}: The Transition config, defaults to {easing: 'ease-out', duration: 2, top: '50px'}. If 'left' property is not specified, it will be automatically calculated.
   * closeText {string}: Use for the "close" button. Set to false to not have a close button. If set to false but in the provided markup (via content property) there is an element with class "close", a click listener on this element will be added. As result, the notice will be closed.
   * noticeClass {string}: A class to add to the notice toolbar.
   * timeout {Number}: The timeout in milliseconds, after it the notice will be automatically closed. Set it to -1, or do not add this property to disable this functionality.
   * toggleText {object}: The text to use for the "hide" and "show" button. Set to false to not have a hide button.
   * type {String}: One of 'warning' or 'notice'. If not set, default notice type will be 'notice'
   * useAnimation {boolean}: To animate show/hide of the notice, defaults to true. If useAnimation is set to true, but there is no timeout, 5000 will be used as timeout.
   *
   * Callbacks
   * onClose {function}: Called when the toolbar is closed.
   */

  /**
   * @deprecated As of Athanasius (7.3.x), replaced by `Liferay.Util.openToast`.
   * @module liferay-notice
   */

  var Notice = function Notice(options) {
    var instance = this;
    options = options || {};
    instance._closeText = options.closeText;
    instance._node = options.node;
    instance._noticeType = options.type || 'notice';
    instance._noticeClass = 'alert-notice';
    instance._onClose = options.onClose;
    instance._useCloseButton = true;

    if (options.useAnimation) {
      instance._noticeClass += ' popup-alert-notice';

      if (!Lang.isNumber(options.timeout)) {
        options.timeout = 5000;
      }
    }

    instance._animationConfig = options.animationConfig || {
      duration: 2,
      easing: 'ease-out',
      top: '50px'
    };
    instance._useAnimation = options.useAnimation;
    instance._timeout = options.timeout;
    instance._body = A.getBody();
    instance._useToggleButton = false;
    instance._hideText = STR_EMPTY;
    instance._showText = STR_EMPTY;

    if (options.toggleText !== false) {
      instance.toggleText = A.mix(options.toggleText, {
        hide: null,
        show: null
      });
      instance._useToggleButton = true;
    }

    if (instance._noticeType == 'warning') {
      instance._noticeClass = 'alert-danger popup-alert-warning';
    }

    if (options.noticeClass) {
      instance._noticeClass += ' ' + options.noticeClass;
    }

    instance._content = options.content || STR_EMPTY;

    instance._createHTML();

    return instance._notice;
  };

  Notice.prototype = {
    _addCloseButton: function _addCloseButton(notice) {
      var instance = this;
      var closeButton;

      if (instance._closeText !== false) {
        instance._closeText = instance._closeText || 'Close';
      } else {
        instance._useCloseButton = false;
        instance._closeText = STR_EMPTY;
      }

      if (instance._useCloseButton) {
        var html = '<button class="btn btn-secondary submit popup-alert-close">' + instance._closeText + '</button>';
        closeButton = notice.append(html);
      } else {
        closeButton = notice.one('.close');
      }

      if (closeButton) {
        closeButton.on(STR_CLICK, instance.close, instance);
      }
    },
    _addToggleButton: function _addToggleButton(notice) {
      var instance = this;

      if (instance._useToggleButton) {
        instance._hideText = instance._toggleText.hide || 'Hide';
        instance._showText = instance._toggleText.show || 'Show';
        var toggleButton = ANode.create('<a class="toggle-button" href="javascript:;"><span>' + instance._hideText + '</span></a>');
        var toggleSpan = toggleButton.one('span');
        var visible = 0;
        var hideText = instance._hideText;
        var showText = instance._showText;
        toggleButton.on(STR_CLICK, function () {
          var text = showText;

          if (visible === 0) {
            text = hideText;
            visible = 1;
          } else {
            visible = 0;
          }

          notice.toggle();
          toggleSpan.text(text);
        });
        notice.append(toggleButton);
      }
    },
    _afterNoticeShow: function _afterNoticeShow() {
      var instance = this;

      instance._preventHide();

      var notice = instance._notice;

      if (instance._useAnimation) {
        var animationConfig = instance._animationConfig;
        var left = animationConfig.left;
        var top = animationConfig.top;

        if (!left) {
          var noticeRegion = ADOM.region(ANode.getDOMNode(notice));
          left = ADOM.winWidth() / 2 - noticeRegion.width / 2;
          top = -noticeRegion.height;
          animationConfig.left = left + STR_PX;
        }

        notice.setXY([left, top]);
        notice.transition(instance._animationConfig, function () {
          instance._hideHandle = A.later(instance._timeout, notice, STR_HIDE);
        });
      } else if (instance._timeout > -1) {
        instance._hideHandle = A.later(instance._timeout, notice, STR_HIDE);
      }

      Liferay.fire('noticeShow', {
        notice: instance,
        useAnimation: instance._useAnimation
      });
    },
    _beforeNoticeHide: function _beforeNoticeHide() {
      var instance = this;
      var returnVal;

      if (instance._useAnimation) {
        var animationConfig = A.merge(instance._animationConfig, {
          top: -instance._notice.get('offsetHeight') + STR_PX
        });

        instance._notice.transition(animationConfig, function () {
          instance._notice.toggle(false);
        });

        returnVal = new Do.Halt(null);
      }

      Liferay.fire('noticeHide', {
        notice: instance,
        useAnimation: instance._useAnimation
      });
      return returnVal;
    },
    _beforeNoticeShow: function _beforeNoticeShow() {
      var instance = this;

      instance._notice.toggle(true);
    },
    _createHTML: function _createHTML() {
      var instance = this;
      var content = instance._content;
      var node = A.one(instance._node);
      var notice = node || ANode.create('<div class="alert alert-warning" dynamic="true"></div>');

      if (content) {
        notice.html(content);
      }

      instance._noticeClass.split(' ').forEach(function (item) {
        notice.addClass(item);
      });

      instance._addCloseButton(notice);

      instance._addToggleButton(notice);

      if (!node || node && !node.inDoc()) {
        instance._body.prepend(notice);
      }

      instance._body.addClass(CSS_ALERTS);

      Do.before(instance._beforeNoticeHide, notice, STR_HIDE, instance);
      Do.before(instance._beforeNoticeShow, notice, STR_SHOW, instance);
      Do.after(instance._afterNoticeShow, notice, STR_SHOW, instance);
      instance._notice = notice;
    },
    _preventHide: function _preventHide() {
      var instance = this;

      if (instance._hideHandle) {
        instance._hideHandle.cancel();

        instance._hideHandle = null;
      }
    },
    close: function close() {
      var instance = this;
      var notice = instance._notice;
      notice.hide();

      instance._body.removeClass(CSS_ALERTS);

      if (instance._onClose) {
        instance._onClose();
      }
    },
    setClosing: function setClosing() {
      var instance = this;
      var alerts = A.all('.popup-alert-notice, .popup-alert-warning');

      if (alerts.size()) {
        instance._useCloseButton = true;

        if (!instance._body) {
          instance._body = A.getBody();
        }

        instance._body.addClass(CSS_ALERTS);

        alerts.each(instance._addCloseButton, instance);
      }
    }
  };
  Liferay.Notice = Notice;
}, '', {
  requires: ['aui-base']
});
//# sourceMappingURL=notice.js.map
/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

/**
 * @deprecated As of Athanasius (7.3.x), with no direct replacement
 */
AUI.add('liferay-poller', function (A) {
  var AObject = A.Object;

  var _browserKey = Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER);

  var _enabled = false;
  var _encryptedUserId = null;
  var _supportsComet = false;
  var _delayAccessCount = 0;
  var _delayIndex = 0;
  var _delays = [1, 2, 3, 4, 5, 7, 10];

  var _getEncryptedUserId = function _getEncryptedUserId() {
    return _encryptedUserId;
  };

  var _frozen = false;
  var _locked = false;

  var _maxDelay = _delays.length - 1;

  var _portletIdsMap = {};
  var _metaData = {
    browserKey: _browserKey,
    companyId: themeDisplay.getCompanyId(),
    portletIdsMap: _portletIdsMap,
    startPolling: true
  };
  var _customDelay = null;
  var _portlets = {};
  var _requestDelay = _delays[0];
  var _sendQueue = [];
  var _suspended = false;
  var _timerId = null;

  var _url = themeDisplay.getPathContext() + '/poller';

  var _receiveChannel = _url + '/receive';

  var _sendChannel = _url + '/send';

  var _closeCurlyBrace = '}';
  var _openCurlyBrace = '{';
  var _escapedCloseCurlyBrace = '[$CLOSE_CURLY_BRACE$]';
  var _escapedOpenCurlyBrace = '[$OPEN_CURLY_BRACE$]';

  var _cancelRequestTimer = function _cancelRequestTimer() {
    clearTimeout(_timerId);
    _timerId = null;
  };

  var _createRequestTimer = function _createRequestTimer() {
    _cancelRequestTimer();

    if (_enabled) {
      if (Poller.isSupportsComet()) {
        _receive();
      } else {
        _timerId = setTimeout(_receive, Poller.getDelay());
      }
    }
  };

  var _freezeConnection = function _freezeConnection() {
    _frozen = true;

    _cancelRequestTimer();
  };

  var _getReceiveUrl = function _getReceiveUrl() {
    return _receiveChannel;
  };

  var _getSendUrl = function _getSendUrl() {
    return _sendChannel;
  };

  var _processResponse = function _processResponse(id, obj) {
    var response = JSON.parse(obj.responseText);
    var send = false;

    if (Array.isArray(response)) {
      var meta = response.shift();

      for (var i = 0; i < response.length; i++) {
        var chunk = response[i].payload;
        var chunkData = chunk.data;
        var portletId = chunk.portletId;
        var portlet = _portlets[portletId];

        if (portlet) {
          var currentPortletId = _portletIdsMap[portletId];

          if (chunkData && currentPortletId) {
            chunkData.initialRequest = portlet.initialRequest;
          }

          portlet.listener.call(portlet.scope || Poller, chunkData, chunk.chunkId);

          if (chunkData && chunkData.pollerHintHighConnectivity) {
            _requestDelay = _delays[0];
            _delayIndex = 0;
          }

          if (portlet.initialRequest && currentPortletId) {
            send = true;
            portlet.initialRequest = false;
          }
        }
      }

      if ('startPolling' in _metaData) {
        delete _metaData.startPolling;
      }

      if (send) {
        _send();
      }

      if (!meta.suspendPolling) {
        _thawConnection();
      } else {
        _freezeConnection();
      }
    }
  };

  var _receive = function _receive() {
    if (!_suspended && !_frozen) {
      _metaData.userId = _getEncryptedUserId();
      _metaData.timestamp = new Date().getTime();
      AObject.each(_portlets, _updatePortletIdsMap);
      var requestStr = JSON.stringify([_metaData]);
      var body = new URLSearchParams();
      body.append('pollerRequest', requestStr);
      Liferay.Util.fetch(_getReceiveUrl(), {
        body: body,
        method: 'POST'
      }).then(function (response) {
        return response.text();
      }).then(function (responseText) {
        _processResponse(null, {
          responseText: responseText
        });
      });
    }
  };

  var _releaseLock = function _releaseLock() {
    _locked = false;
  };

  var _sendComplete = function _sendComplete() {
    _releaseLock();

    _send();
  };

  var _send = function _send() {
    if (_enabled && !_locked && _sendQueue.length && !_suspended && !_frozen) {
      _locked = true;

      var data = _sendQueue.shift();

      _metaData.userId = _getEncryptedUserId();
      _metaData.timestamp = new Date().getTime();
      AObject.each(_portlets, _updatePortletIdsMap);
      var requestStr = JSON.stringify([_metaData].concat(data));
      var body = new URLSearchParams();
      body.append('pollerRequest', requestStr);
      Liferay.Util.fetch(_getSendUrl(), {
        body: body,
        method: 'POST'
      }).then(function (response) {
        return response.text();
      }).then(_sendComplete);
    }
  };

  var _thawConnection = function _thawConnection() {
    _frozen = false;

    _createRequestTimer();
  };

  var _updatePortletIdsMap = function _updatePortletIdsMap(item, index) {
    _portletIdsMap[index] = item.initialRequest;
  };

  var Poller = {
    addListener: function addListener(key, listener, scope) {
      _portlets[key] = {
        initialRequest: true,
        listener: listener,
        scope: scope
      };

      if (!_enabled) {
        _enabled = true;

        _receive();
      }
    },
    cancelCustomDelay: function cancelCustomDelay() {
      _customDelay = null;
    },
    getDelay: function getDelay() {
      if (_customDelay !== null) {
        _requestDelay = _customDelay;
      } else if (_delayIndex <= _maxDelay) {
        _requestDelay = _delays[_delayIndex];
        _delayAccessCount++;

        if (_delayAccessCount == 3) {
          _delayIndex++;
          _delayAccessCount = 0;
        }
      }

      return _requestDelay * 1000;
    },
    getReceiveUrl: _getReceiveUrl,
    getSendUrl: _getSendUrl,
    init: function init(options) {
      var instance = this;
      instance.setEncryptedUserId(options.encryptedUserId);
      instance.setSupportsComet(options.supportsComet);
    },
    isSupportsComet: function isSupportsComet() {
      return _supportsComet;
    },
    processResponse: _processResponse,
    removeListener: function removeListener(key) {
      if (key in _portlets) {
        delete _portlets[key];
      }

      if (AObject.keys(_portlets).length === 0) {
        _enabled = false;

        _cancelRequestTimer();
      }
    },
    resume: function resume() {
      _suspended = false;

      _createRequestTimer();
    },
    setCustomDelay: function setCustomDelay(delay) {
      if (delay === null) {
        _customDelay = delay;
      } else {
        _customDelay = delay / 1000;
      }
    },
    setDelay: function setDelay(delay) {
      _requestDelay = delay / 1000;
    },
    setEncryptedUserId: function setEncryptedUserId(encryptedUserId) {
      _encryptedUserId = encryptedUserId;
    },
    setSupportsComet: function setSupportsComet(supportsComet) {
      _supportsComet = supportsComet;
    },
    setUrl: function setUrl(url) {
      _url = url;
    },
    submitRequest: function submitRequest(key, data, chunkId) {
      if (!_frozen && key in _portlets) {
        for (var i in data) {
          if (Object.prototype.hasOwnProperty.call(data, i)) {
            var content = data[i];

            if (content.replace) {
              content = content.replace(_openCurlyBrace, _escapedOpenCurlyBrace);
              content = content.replace(_closeCurlyBrace, _escapedCloseCurlyBrace);
              data[i] = content;
            }
          }
        }

        var requestData = {
          data: data,
          portletId: key
        };

        if (chunkId) {
          requestData.chunkId = chunkId;
        }

        _sendQueue.push(requestData);

        _send();
      }
    },
    suspend: function suspend() {
      _cancelRequestTimer();

      _suspended = true;
    },
    url: _url
  };
  A.getWin().on('focus', function () {
    _metaData.startPolling = true;

    _thawConnection();
  });
  Liferay.Poller = Poller;
}, '', {
  requires: ['aui-base', 'json']
});
//# sourceMappingURL=poller.js.map
YUI.add('async-queue', function (Y, NAME) {

/**
 * <p>AsyncQueue allows you create a chain of function callbacks executed
 * via setTimeout (or synchronously) that are guaranteed to run in order.
 * Items in the queue can be promoted or removed.  Start or resume the
 * execution chain with run().  pause() to temporarily delay execution, or
 * stop() to halt and clear the queue.</p>
 *
 * @module async-queue
 */

/**
 * <p>A specialized queue class that supports scheduling callbacks to execute
 * sequentially, iteratively, even asynchronously.</p>
 *
 * <p>Callbacks can be function refs or objects with the following keys.  Only
 * the <code>fn</code> key is required.</p>
 *
 * <ul>
 * <li><code>fn</code> -- The callback function</li>
 * <li><code>context</code> -- The execution context for the callbackFn.</li>
 * <li><code>args</code> -- Arguments to pass to callbackFn.</li>
 * <li><code>timeout</code> -- Millisecond delay before executing callbackFn.
 *                     (Applies to each iterative execution of callback)</li>
 * <li><code>iterations</code> -- Number of times to repeat the callback.
 * <li><code>until</code> -- Repeat the callback until this function returns
 *                         true.  This setting trumps iterations.</li>
 * <li><code>autoContinue</code> -- Set to false to prevent the AsyncQueue from
 *                        executing the next callback in the Queue after
 *                        the callback completes.</li>
 * <li><code>id</code> -- Name that can be used to get, promote, get the
 *                        indexOf, or delete this callback.</li>
 * </ul>
 *
 * @class AsyncQueue
 * @extends EventTarget
 * @constructor
 * @param callback* {Function|Object} 0..n callbacks to seed the queue
 */
Y.AsyncQueue = function() {
    this._init();
    this.add.apply(this, arguments);
};

var Queue   = Y.AsyncQueue,
    EXECUTE = 'execute',
    SHIFT   = 'shift',
    PROMOTE = 'promote',
    REMOVE  = 'remove',

    isObject   = Y.Lang.isObject,
    isFunction = Y.Lang.isFunction;

/**
 * <p>Static default values used to populate callback configuration properties.
 * Preconfigured defaults include:</p>
 *
 * <ul>
 *  <li><code>autoContinue</code>: <code>true</code></li>
 *  <li><code>iterations</code>: 1</li>
 *  <li><code>timeout</code>: 10 (10ms between callbacks)</li>
 *  <li><code>until</code>: (function to run until iterations &lt;= 0)</li>
 * </ul>
 *
 * @property defaults
 * @type {Object}
 * @static
 */
Queue.defaults = Y.mix({
    autoContinue : true,
    iterations   : 1,
    timeout      : 10,
    until        : function () {
        this.iterations |= 0;
        return this.iterations <= 0;
    }
}, Y.config.queueDefaults || {});

Y.extend(Queue, Y.EventTarget, {
    /**
     * Used to indicate the queue is currently executing a callback.
     *
     * @property _running
     * @type {Boolean|Object} true for synchronous callback execution, the
     *                        return handle from Y.later for async callbacks.
     *                        Otherwise false.
     * @protected
     */
    _running : false,

    /**
     * Initializes the AsyncQueue instance properties and events.
     *
     * @method _init
     * @protected
     */
    _init : function () {
        Y.EventTarget.call(this, { prefix: 'queue', emitFacade: true });

        this._q = [];

        /**
         * Callback defaults for this instance.  Static defaults that are not
         * overridden are also included.
         *
         * @property defaults
         * @type {Object}
         */
        this.defaults = {};

        this._initEvents();
    },

    /**
     * Initializes the instance events.
     *
     * @method _initEvents
     * @protected
     */
    _initEvents : function () {
        this.publish({
            'execute' : { defaultFn : this._defExecFn,    emitFacade: true },
            'shift'   : { defaultFn : this._defShiftFn,   emitFacade: true },
            'add'     : { defaultFn : this._defAddFn,     emitFacade: true },
            'promote' : { defaultFn : this._defPromoteFn, emitFacade: true },
            'remove'  : { defaultFn : this._defRemoveFn,  emitFacade: true }
        });
    },

    /**
     * Returns the next callback needing execution.  If a callback is
     * configured to repeat via iterations or until, it will be returned until
     * the completion criteria is met.
     *
     * When the queue is empty, null is returned.
     *
     * @method next
     * @return {Function} the callback to execute
     */
    next : function () {
        var callback;

        while (this._q.length) {
            callback = this._q[0] = this._prepare(this._q[0]);
            if (callback && callback.until()) {
                this.fire(SHIFT, { callback: callback });
                callback = null;
            } else {
                break;
            }
        }

        return callback || null;
    },

    /**
     * Default functionality for the &quot;shift&quot; event.  Shifts the
     * callback stored in the event object's <em>callback</em> property from
     * the queue if it is the first item.
     *
     * @method _defShiftFn
     * @param e {Event} The event object
     * @protected
     */
    _defShiftFn : function (e) {
        if (this.indexOf(e.callback) === 0) {
            this._q.shift();
        }
    },

    /**
     * Creates a wrapper function to execute the callback using the aggregated
     * configuration generated by combining the static AsyncQueue.defaults, the
     * instance defaults, and the specified callback settings.
     *
     * The wrapper function is decorated with the callback configuration as
     * properties for runtime modification.
     *
     * @method _prepare
     * @param callback {Object|Function} the raw callback
     * @return {Function} a decorated function wrapper to execute the callback
     * @protected
     */
    _prepare: function (callback) {
        if (isFunction(callback) && callback._prepared) {
            return callback;
        }

        var config = Y.merge(
            Queue.defaults,
            { context : this, args: [], _prepared: true },
            this.defaults,
            (isFunction(callback) ? { fn: callback } : callback)),

            wrapper = Y.bind(function () {
                if (!wrapper._running) {
                    wrapper.iterations--;
                }
                if (isFunction(wrapper.fn)) {
                    wrapper.fn.apply(wrapper.context || Y,
                                     Y.Array(wrapper.args));
                }
            }, this);

        return Y.mix(wrapper, config);
    },

    /**
     * Sets the queue in motion.  All queued callbacks will be executed in
     * order unless pause() or stop() is called or if one of the callbacks is
     * configured with autoContinue: false.
     *
     * @method run
     * @return {AsyncQueue} the AsyncQueue instance
     * @chainable
     */
    run : function () {
        var callback,
            cont = true;

        if (this._executing) {
            this._running = true;
            return this;
        }

        for (callback = this.next();
            callback && !this.isRunning();
            callback = this.next())
        {
            cont = (callback.timeout < 0) ?
                this._execute(callback) :
                this._schedule(callback);

            // Break to avoid an extra call to next (final-expression of the
            // 'for' loop), because the until function of the next callback
            // in the queue may return a wrong result if it depends on the
            // not-yet-finished work of the previous callback.
            if (!cont) {
                break;
            }
        }

        if (!callback) {
            /**
             * Event fired when there is no remaining callback in the running queue. Also fired after stop().
             * @event complete
             */
            this.fire('complete');
        }

        return this;
    },

    /**
     * Handles the execution of callbacks. Returns a boolean indicating
     * whether it is appropriate to continue running.
     *
     * @method _execute
     * @param callback {Object} the callback object to execute
     * @return {Boolean} whether the run loop should continue
     * @protected
     */
    _execute : function (callback) {

        this._running   = callback._running = true;
        this._executing = callback;

        callback.iterations--;
        this.fire(EXECUTE, { callback: callback });

        var cont = this._running && callback.autoContinue;

        this._running   = callback._running = false;
        this._executing = false;

        return cont;
    },

    /**
     * Schedules the execution of asynchronous callbacks.
     *
     * @method _schedule
     * @param callback {Object} the callback object to execute
     * @return {Boolean} whether the run loop should continue
     * @protected
     */
    _schedule : function (callback) {
        this._running = Y.later(callback.timeout, this, function () {
            if (this._execute(callback)) {
                this.run();
            }
        });

        return false;
    },

    /**
     * Determines if the queue is waiting for a callback to complete execution.
     *
     * @method isRunning
     * @return {Boolean} true if queue is waiting for a
     *                   from any initiated transactions
     */
    isRunning : function () {
        return !!this._running;
    },

    /**
     * Default functionality for the &quot;execute&quot; event.  Executes the
     * callback function
     *
     * @method _defExecFn
     * @param e {Event} the event object
     * @protected
     */
    _defExecFn : function (e) {
        e.callback();
    },

    /**
     * Add any number of callbacks to the end of the queue. Callbacks may be
     * provided as functions or objects.
     *
     * @method add
     * @param callback* {Function|Object} 0..n callbacks
     * @return {AsyncQueue} the AsyncQueue instance
     * @chainable
     */
    add : function () {
        this.fire('add', { callbacks: Y.Array(arguments,0,true) });

        return this;
    },

    /**
     * Default functionality for the &quot;add&quot; event.  Adds the callbacks
     * in the event facade to the queue. Callbacks successfully added to the
     * queue are present in the event's <code>added</code> property in the
     * after phase.
     *
     * @method _defAddFn
     * @param e {Event} the event object
     * @protected
     */
    _defAddFn : function(e) {
        var _q = this._q,
            added = [];

        Y.Array.each(e.callbacks, function (c) {
            if (isObject(c)) {
                _q.push(c);
                added.push(c);
            }
        });

        e.added = added;
    },

    /**
     * Pause the execution of the queue after the execution of the current
     * callback completes.  If called from code outside of a queued callback,
     * clears the timeout for the pending callback. Paused queue can be
     * restarted with q.run()
     *
     * @method pause
     * @return {AsyncQueue} the AsyncQueue instance
     * @chainable
     */
    pause: function () {
        if (this._running && isObject(this._running)) {
            this._running.cancel();
        }

        this._running = false;

        return this;
    },

    /**
     * Stop and clear the queue after the current execution of the
     * current callback completes.
     *
     * @method stop
     * @return {AsyncQueue} the AsyncQueue instance
     * @chainable
     */
    stop : function () {

        this._q = [];

        if (this._running && isObject(this._running)) {
            this._running.cancel();
            this._running = false;
        }
        // otherwise don't systematically set this._running to false, because if
        // stop has been called from inside a queued callback, the _execute method
        // currenty running needs to call run() one more time for the 'complete'
        // event to be fired.

        // if stop is called from outside a callback, we need to explicitely call
        // run() once again to fire the 'complete' event.
        if (!this._executing) {
            this.run();
        }

        return this;
    },

    /**
     * Returns the current index of a callback.  Pass in either the id or
     * callback function from getCallback.
     *
     * @method indexOf
     * @param callback {String|Function} the callback or its specified id
     * @return {Number} index of the callback or -1 if not found
     */
    indexOf : function (callback) {
        var i = 0, len = this._q.length, c;

        for (; i < len; ++i) {
            c = this._q[i];
            if (c === callback || c.id === callback) {
                return i;
            }
        }

        return -1;
    },

    /**
     * Retrieve a callback by its id.  Useful to modify the configuration
     * while the queue is running.
     *
     * @method getCallback
     * @param id {String} the id assigned to the callback
     * @return {Object} the callback object
     */
    getCallback : function (id) {
        var i = this.indexOf(id);

        return (i > -1) ? this._q[i] : null;
    },

    /**
     * Promotes the named callback to the top of the queue. If a callback is
     * currently executing or looping (via until or iterations), the promotion
     * is scheduled to occur after the current callback has completed.
     *
     * @method promote
     * @param callback {String|Object} the callback object or a callback's id
     * @return {AsyncQueue} the AsyncQueue instance
     * @chainable
     */
    promote : function (callback) {
        var payload = { callback : callback },e;

        if (this.isRunning()) {
            e = this.after(SHIFT, function () {
                    this.fire(PROMOTE, payload);
                    e.detach();
                }, this);
        } else {
            this.fire(PROMOTE, payload);
        }

        return this;
    },

    /**
     * <p>Default functionality for the &quot;promote&quot; event.  Promotes the
     * named callback to the head of the queue.</p>
     *
     * <p>The event object will contain a property &quot;callback&quot;, which
     * holds the id of a callback or the callback object itself.</p>
     *
     * @method _defPromoteFn
     * @param e {Event} the custom event
     * @protected
     */
    _defPromoteFn : function (e) {
        var i = this.indexOf(e.callback),
            promoted = (i > -1) ? this._q.splice(i,1)[0] : null;

        e.promoted = promoted;

        if (promoted) {
            this._q.unshift(promoted);
        }
    },

    /**
     * Removes the callback from the queue.  If the queue is active, the
     * removal is scheduled to occur after the current callback has completed.
     *
     * @method remove
     * @param callback {String|Object} the callback object or a callback's id
     * @return {AsyncQueue} the AsyncQueue instance
     * @chainable
     */
    remove : function (callback) {
        var payload = { callback : callback },e;

        // Can't return the removed callback because of the deferral until
        // current callback is complete
        if (this.isRunning()) {
            e = this.after(SHIFT, function () {
                    this.fire(REMOVE, payload);
                    e.detach();
                },this);
        } else {
            this.fire(REMOVE, payload);
        }

        return this;
    },

    /**
     * <p>Default functionality for the &quot;remove&quot; event.  Removes the
     * callback from the queue.</p>
     *
     * <p>The event object will contain a property &quot;callback&quot;, which
     * holds the id of a callback or the callback object itself.</p>
     *
     * @method _defRemoveFn
     * @param e {Event} the custom event
     * @protected
     */
    _defRemoveFn : function (e) {
        var i = this.indexOf(e.callback);

        e.removed = (i > -1) ? this._q.splice(i,1)[0] : null;
    },

    /**
     * Returns the number of callbacks in the queue.
     *
     * @method size
     * @return {Number}
     */
    size : function () {
        // next() flushes callbacks that have met their until() criteria and
        // therefore shouldn't count since they wouldn't execute anyway.
        if (!this.isRunning()) {
            this.next();
        }

        return this._q.length;
    }
});



}, 'patched-v3.18.1', {"requires": ["event-custom"]});

YUI.add('base-build', function (Y, NAME) {

    /**
     * The base-build submodule provides Base.build functionality, which
     * can be used to create custom classes, by aggregating extensions onto
     * a main class.
     *
     * @module base
     * @submodule base-build
     * @for Base
     */
    var BaseCore = Y.BaseCore,
        Base     = Y.Base,
        L        = Y.Lang,

        INITIALIZER = "initializer",
        DESTRUCTOR  = "destructor",
        AGGREGATES  = ["_PLUG", "_UNPLUG"],

        build;

    // Utility function used in `_buildCfg` to aggregate array values into a new
    // array from the sender constructor to the receiver constructor.
    function arrayAggregator(prop, r, s) {
        if (s[prop]) {
            r[prop] = (r[prop] || []).concat(s[prop]);
        }
    }

    // Utility function used in `_buildCfg` to aggregate `_ATTR_CFG` array
    // values from the sender constructor into a new array on receiver's
    // constructor, and clear the cached hash.
    function attrCfgAggregator(prop, r, s) {
        if (s._ATTR_CFG) {
            // Clear cached hash.
            r._ATTR_CFG_HASH = null;

            arrayAggregator.apply(null, arguments);
        }
    }

    // Utility function used in `_buildCfg` to aggregate ATTRS configs from one
    // the sender constructor to the receiver constructor.
    function attrsAggregator(prop, r, s) {
        BaseCore.modifyAttrs(r, s.ATTRS);
    }

    Base._build = function(name, main, extensions, px, sx, cfg) {

        var build = Base._build,

            builtClass = build._ctor(main, cfg),
            buildCfg = build._cfg(main, cfg, extensions),

            _mixCust = build._mixCust,

            dynamic = builtClass._yuibuild.dynamic,

            i, l, extClass, extProto,
            initializer,
            destructor;

        // Augment/Aggregate
        for (i = 0, l = extensions.length; i < l; i++) {
            extClass = extensions[i];

            extProto = extClass.prototype;

            initializer = extProto[INITIALIZER];
            destructor = extProto[DESTRUCTOR];
            delete extProto[INITIALIZER];
            delete extProto[DESTRUCTOR];

            // Prototype, old non-displacing augment
            Y.mix(builtClass, extClass, true, null, 1);

            // Custom Statics
            _mixCust(builtClass, extClass, buildCfg);

            if (initializer) {
                extProto[INITIALIZER] = initializer;
            }

            if (destructor) {
                extProto[DESTRUCTOR] = destructor;
            }

            builtClass._yuibuild.exts.push(extClass);
        }

        if (px) {
            Y.mix(builtClass.prototype, px, true);
        }

        if (sx) {
            Y.mix(builtClass, build._clean(sx, buildCfg), true);
            _mixCust(builtClass, sx, buildCfg);
        }

        builtClass.prototype.hasImpl = build._impl;

        if (dynamic) {
            builtClass.NAME = name;
            builtClass.prototype.constructor = builtClass;

            // Carry along the reference to `modifyAttrs()` from `main`.
            builtClass.modifyAttrs = main.modifyAttrs;
        }

        return builtClass;
    };

    build = Base._build;

    Y.mix(build, {

        _mixCust: function(r, s, cfg) {

            var aggregates,
                custom,
                statics,
                aggr,
                l,
                i;

            if (cfg) {
                aggregates = cfg.aggregates;
                custom = cfg.custom;
                statics = cfg.statics;
            }

            if (statics) {
                Y.mix(r, s, true, statics);
            }

            if (aggregates) {
                for (i = 0, l = aggregates.length; i < l; i++) {
                    aggr = aggregates[i];
                    if (!r.hasOwnProperty(aggr) && s.hasOwnProperty(aggr)) {
                        r[aggr] = L.isArray(s[aggr]) ? [] : {};
                    }
                    Y.aggregate(r, s, true, [aggr]);
                }
            }

            if (custom) {
                for (i in custom) {
                    if (custom.hasOwnProperty(i)) {
                        custom[i](i, r, s);
                    }
                }
            }

        },

        _tmpl: function(main) {

            function BuiltClass() {
                BuiltClass.superclass.constructor.apply(this, arguments);
            }
            Y.extend(BuiltClass, main);

            return BuiltClass;
        },

        _impl : function(extClass) {
            var classes = this._getClasses(), i, l, cls, exts, ll, j;
            for (i = 0, l = classes.length; i < l; i++) {
                cls = classes[i];
                if (cls._yuibuild) {
                    exts = cls._yuibuild.exts;
                    ll = exts.length;

                    for (j = 0; j < ll; j++) {
                        if (exts[j] === extClass) {
                            return true;
                        }
                    }
                }
            }
            return false;
        },

        _ctor : function(main, cfg) {

           var dynamic = (cfg && false === cfg.dynamic) ? false : true,
               builtClass = (dynamic) ? build._tmpl(main) : main,
               buildCfg = builtClass._yuibuild;

            if (!buildCfg) {
                buildCfg = builtClass._yuibuild = {};
            }

            buildCfg.id = buildCfg.id || null;
            buildCfg.exts = buildCfg.exts || [];
            buildCfg.dynamic = dynamic;

            return builtClass;
        },

        _cfg : function(main, cfg, exts) {
            var aggr = [],
                cust = {},
                statics = [],
                buildCfg,
                cfgAggr = (cfg && cfg.aggregates),
                cfgCustBuild = (cfg && cfg.custom),
                cfgStatics = (cfg && cfg.statics),
                c = main,
                i,
                l;

            // Prototype Chain
            while (c && c.prototype) {
                buildCfg = c._buildCfg;
                if (buildCfg) {
                    if (buildCfg.aggregates) {
                        aggr = aggr.concat(buildCfg.aggregates);
                    }
                    if (buildCfg.custom) {
                        Y.mix(cust, buildCfg.custom, true);
                    }
                    if (buildCfg.statics) {
                        statics = statics.concat(buildCfg.statics);
                    }
                }
                c = c.superclass ? c.superclass.constructor : null;
            }

            // Exts
            if (exts) {
                for (i = 0, l = exts.length; i < l; i++) {
                    c = exts[i];
                    buildCfg = c._buildCfg;
                    if (buildCfg) {
                        if (buildCfg.aggregates) {
                            aggr = aggr.concat(buildCfg.aggregates);
                        }
                        if (buildCfg.custom) {
                            Y.mix(cust, buildCfg.custom, true);
                        }
                        if (buildCfg.statics) {
                            statics = statics.concat(buildCfg.statics);
                        }
                    }
                }
            }

            if (cfgAggr) {
                aggr = aggr.concat(cfgAggr);
            }

            if (cfgCustBuild) {
                Y.mix(cust, cfg.cfgBuild, true);
            }

            if (cfgStatics) {
                statics = statics.concat(cfgStatics);
            }

            return {
                aggregates: aggr,
                custom: cust,
                statics: statics
            };
        },

        _clean : function(sx, cfg) {
            var prop, i, l, sxclone = Y.merge(sx),
                aggregates = cfg.aggregates,
                custom = cfg.custom;

            for (prop in custom) {
                if (sxclone.hasOwnProperty(prop)) {
                    delete sxclone[prop];
                }
            }

            for (i = 0, l = aggregates.length; i < l; i++) {
                prop = aggregates[i];
                if (sxclone.hasOwnProperty(prop)) {
                    delete sxclone[prop];
                }
            }

            return sxclone;
        }
    });

    /**
     * <p>
     * Builds a custom constructor function (class) from the
     * main function, and array of extension functions (classes)
     * provided. The NAME field for the constructor function is
     * defined by the first argument passed in.
     * </p>
     * <p>
     * The cfg object supports the following properties
     * </p>
     * <dl>
     *    <dt>dynamic &#60;boolean&#62;</dt>
     *    <dd>
     *    <p>If true (default), a completely new class
     *    is created which extends the main class, and acts as the
     *    host on which the extension classes are augmented.</p>
     *    <p>If false, the extensions classes are augmented directly to
     *    the main class, modifying the main class' prototype.</p>
     *    </dd>
     *    <dt>aggregates &#60;String[]&#62;</dt>
     *    <dd>An array of static property names, which will get aggregated
     *    on to the built class, in addition to the default properties build
     *    will always aggregate as defined by the main class' static _buildCfg
     *    property.
     *    </dd>
     * </dl>
     *
     * @method build
     * @deprecated Use the more convenient Base.create and Base.mix methods instead
     * @static
     * @param {Function} name The name of the new class. Used to define the NAME property for the new class.
     * @param {Function} main The main class on which to base the built class
     * @param {Function[]} extensions The set of extension classes which will be
     * augmented/aggregated to the built class.
     * @param {Object} cfg Optional. Build configuration for the class (see description).
     * @return {Function} A custom class, created from the provided main and extension classes
     */
    Base.build = function(name, main, extensions, cfg) {
        return build(name, main, extensions, null, null, cfg);
    };

    /**
     * Creates a new class (constructor function) which extends the base class passed in as the second argument,
     * and mixes in the array of extensions provided.
     *
     * Prototype properties or methods can be added to the new class, using the px argument (similar to Y.extend).
     *
     * Static properties or methods can be added to the new class, using the sx argument (similar to Y.extend).
     *
     * **NOTE FOR COMPONENT DEVELOPERS**: Both the `base` class, and `extensions` can define static a `_buildCfg`
     * property, which acts as class creation meta-data, and drives how special static properties from the base
     * class, or extensions should be copied, aggregated or (custom) mixed into the newly created class.
     *
     * The `_buildCfg` property is a hash with 3 supported properties: `statics`, `aggregates` and `custom`, e.g:
     *
     *     // If the Base/Main class is the thing introducing the property:
     *
     *     MyBaseClass._buildCfg = {
     *
     *        // Static properties/methods to copy (Alias) to the built class.
     *        statics: ["CopyThisMethod", "CopyThisProperty"],
     *
     *        // Static props to aggregate onto the built class.
     *        aggregates: ["AggregateThisProperty"],
     *
     *        // Static properties which need custom handling (e.g. deep merge etc.)
     *        custom: {
     *           "CustomProperty" : function(property, Receiver, Supplier) {
     *              ...
     *              var triggers = Receiver.CustomProperty.triggers;
     *              Receiver.CustomProperty.triggers = triggers.concat(Supplier.CustomProperty.triggers);
     *              ...
     *           }
     *        }
     *     };
     *
     *     MyBaseClass.CopyThisMethod = function() {...};
     *     MyBaseClass.CopyThisProperty = "foo";
     *     MyBaseClass.AggregateThisProperty = {...};
     *     MyBaseClass.CustomProperty = {
     *        triggers: [...]
     *     }
     *
     *     // Or, if the Extension is the thing introducing the property:
     *
     *     MyExtension._buildCfg = {
     *         statics : ...
     *         aggregates : ...
     *         custom : ...
     *     }
     *
     * This way, when users pass your base or extension class to `Y.Base.create` or `Y.Base.mix`, they don't need to
     * know which properties need special handling. `Y.Base` has a buildCfg which defines `ATTRS` for custom mix handling
     * (to protect the static config objects), and `Y.Widget` has a buildCfg which specifies `HTML_PARSER` for
     * straight up aggregation.
     *
     * @method create
     * @static
     * @param {String} name The name of the newly created class. Used to define the NAME property for the new class.
     * @param {Function} main The base class which the new class should extend.
     * This class needs to be Base or a class derived from base (e.g. Widget).
     * @param {Function[]} extensions The list of extensions which will be mixed into the built class.
     * @param {Object} px The set of prototype properties/methods to add to the built class.
     * @param {Object} sx The set of static properties/methods to add to the built class.
     * @return {Function} The newly created class.
     */
    Base.create = function(name, base, extensions, px, sx) {
        return build(name, base, extensions, px, sx);
    };

    /**
     * <p>Mixes in a list of extensions to an existing class.</p>
     * @method mix
     * @static
     * @param {Function} main The existing class into which the extensions should be mixed.
     * The class needs to be Base or a class derived from Base (e.g. Widget)
     * @param {Function[]} extensions The set of extension classes which will mixed into the existing main class.
     * @return {Function} The modified main class, with extensions mixed in.
     */
    Base.mix = function(main, extensions) {

        if (main._CACHED_CLASS_DATA) {
            main._CACHED_CLASS_DATA = null;
        }

        return build(null, main, extensions, null, null, {dynamic:false});
    };

    /**
     * The build configuration for the Base class.
     *
     * Defines the static fields which need to be aggregated when the Base class
     * is used as the main class passed to the
     * <a href="#method_Base.build">Base.build</a> method.
     *
     * @property _buildCfg
     * @type Object
     * @static
     * @final
     * @private
     */
    BaseCore._buildCfg = {
        aggregates: AGGREGATES.concat(),

        custom: {
            ATTRS         : attrsAggregator,
            _ATTR_CFG     : attrCfgAggregator,
            _NON_ATTRS_CFG: arrayAggregator
        }
    };

    // Makes sure Base and BaseCore use separate `_buildCfg` objects.
    Base._buildCfg = {
        aggregates: AGGREGATES.concat(),

        custom: {
            ATTRS         : attrsAggregator,
            _ATTR_CFG     : attrCfgAggregator,
            _NON_ATTRS_CFG: arrayAggregator
        }
    };


}, 'patched-v3.18.1', {"requires": ["base-base"]});

YUI.add('cookie', function (Y, NAME) {

/**
 * Utilities for cookie management
 * @module cookie
 */

    //shortcuts
    var L       = Y.Lang,
        O       = Y.Object,
        NULL    = null,

        //shortcuts to functions
        isString    = L.isString,
        isObject    = L.isObject,
        isUndefined = L.isUndefined,
        isFunction  = L.isFunction,
        encode      = encodeURIComponent,
        decode      = decodeURIComponent,

        //shortcut to document
        doc         = Y.config.doc;

    /*
     * Throws an error message.
     */
    function error(message){
        throw new TypeError(message);
    }

    /*
     * Checks the validity of a cookie name.
     */
    function validateCookieName(name){
        if (!isString(name) || name === ""){
            error("Cookie name must be a non-empty string.");
        }
    }

    /*
     * Checks the validity of a subcookie name.
     */
    function validateSubcookieName(subName){
        if (!isString(subName) || subName === ""){
            error("Subcookie name must be a non-empty string.");
        }
    }

    /**
     * Cookie utility.
     * @class Cookie
     * @static
     */
    Y.Cookie = {

        //-------------------------------------------------------------------------
        // Private Methods
        //-------------------------------------------------------------------------

        /**
         * Creates a cookie string that can be assigned into document.cookie.
         * @param {String} name The name of the cookie.
         * @param {String} value The value of the cookie.
         * @param {Boolean} encodeValue True to encode the value, false to leave as-is.
         * @param {Object} options (Optional) Options for the cookie.
         * @return {String} The formatted cookie string.
         * @method _createCookieString
         * @private
         * @static
         */
        _createCookieString : function (name /*:String*/, value /*:Variant*/, encodeValue /*:Boolean*/, options /*:Object*/) /*:String*/ {

            options = options || {};

            var text /*:String*/ = encode(name) + "=" + (encodeValue ? encode(value) : value),
                expires = options.expires,
                path    = options.path,
                domain  = options.domain;


            if (isObject(options)){
                //expiration date
                if (expires instanceof Date){
                    text += "; expires=" + expires.toUTCString();
                }

                //path
                if (isString(path) && path !== ""){
                    text += "; path=" + path;
                }

                //domain
                if (isString(domain) && domain !== ""){
                    text += "; domain=" + domain;
                }

                //secure
                if (options.secure === true){
                    text += "; secure";
                }
            }

            return text;
        },

        /**
         * Formats a cookie value for an object containing multiple values.
         * @param {Object} hash An object of key-value pairs to create a string for.
         * @return {String} A string suitable for use as a cookie value.
         * @method _createCookieHashString
         * @private
         * @static
         */
        _createCookieHashString : function (hash /*:Object*/) /*:String*/ {
            if (!isObject(hash)){
                error("Cookie._createCookieHashString(): Argument must be an object.");
            }

            var text /*:Array*/ = [];

            O.each(hash, function(value, key){
                if (!isFunction(value) && !isUndefined(value)){
                    text.push(encode(key) + "=" + encode(String(value)));
                }
            });

            return text.join("&");
        },

        /**
         * Parses a cookie hash string into an object.
         * @param {String} text The cookie hash string to parse (format: n1=v1&n2=v2).
         * @return {Object} An object containing entries for each cookie value.
         * @method _parseCookieHash
         * @private
         * @static
         */
        _parseCookieHash : function (text) {

            var hashParts   = text.split("&"),
                hashPart    = NULL,
                hash        = {};

            if (text.length){
                for (var i=0, len=hashParts.length; i < len; i++){
                    hashPart = hashParts[i].split("=");
                    hash[decode(hashPart[0])] = decode(hashPart[1]);
                }
            }

            return hash;
        },

        /**
         * Parses a cookie string into an object representing all accessible cookies.
         * @param {String} text The cookie string to parse.
         * @param {Boolean} shouldDecode (Optional) Indicates if the cookie values should be decoded or not. Default is true.
         * @param {Object} options (Optional) Contains settings for loading the cookie.
         * @return {Object} An object containing entries for each accessible cookie.
         * @method _parseCookieString
         * @private
         * @static
         */
        _parseCookieString : function (text /*:String*/, shouldDecode /*:Boolean*/, options /*:Object*/) /*:Object*/ {

            var cookies /*:Object*/ = {};

            if (isString(text) && text.length > 0) {

                var decodeValue = (shouldDecode === false ? function(s){return s;} : decode),
                    cookieParts = text.split(/;\s/g),
                    cookieName  = NULL,
                    cookieValue = NULL,
                    cookieNameValue = NULL;

                for (var i=0, len=cookieParts.length; i < len; i++){
                    //check for normally-formatted cookie (name-value)
                    cookieNameValue = cookieParts[i].match(/([^=]+)=/i);
                    if (cookieNameValue instanceof Array){
                        try {
                            cookieName = decode(cookieNameValue[1]);
                            cookieValue = decodeValue(cookieParts[i].substring(cookieNameValue[1].length+1));
                        } catch (ex){
                            //intentionally ignore the cookie - the encoding is wrong
                        }
                    } else {
                        //means the cookie does not have an "=", so treat it as a boolean flag
                        cookieName = decode(cookieParts[i]);
                        cookieValue = "";
                    }
                    // don't overwrite an already loaded cookie if set by option
                    if (!isUndefined(options) && options.reverseCookieLoading) {
                        if (isUndefined(cookies[cookieName])) {
                            cookies[cookieName] = cookieValue;
                        }
                    } else {
                        cookies[cookieName] = cookieValue;
                    }
                }

            }

            return cookies;
        },

        /**
         * Sets the document object that the cookie utility uses for setting
         * cookies. This method is necessary to ensure that the cookie utility
         * unit tests can pass even when run on a domain instead of locally.
         * This method should not be used otherwise; you should use
         * <code>Y.config.doc</code> to change the document that the cookie
         * utility uses for everyday purposes.
         * @param {Object} newDoc The object to use as the document.
         * @method _setDoc
         * @private
         */
        _setDoc: function(newDoc){
            doc = newDoc;
        },

        //-------------------------------------------------------------------------
        // Public Methods
        //-------------------------------------------------------------------------

        /**
         * Determines if the cookie with the given name exists. This is useful for
         * Boolean cookies (those that do not follow the name=value convention).
         * @param {String} name The name of the cookie to check.
         * @return {Boolean} True if the cookie exists, false if not.
         * @method exists
         * @static
         */
        exists: function(name) {

            validateCookieName(name);   //throws error

            var cookies = this._parseCookieString(doc.cookie, true);

            return cookies.hasOwnProperty(name);
        },

        /**
         * Returns the cookie value for the given name.
         * @param {String} name The name of the cookie to retrieve.
         * @param {Function|Object} options (Optional) An object containing one or more
         *      cookie options: raw (true/false), reverseCookieLoading (true/false)
         *      and converter (a function).
         *      The converter function is run on the value before returning it. The
         *      function is not used if the cookie doesn't exist. The function can be
         *      passed instead of the options object for backwards compatibility. When
         *      raw is set to true, the cookie value is not URI decoded.
         * @return {Any} If no converter is specified, returns a string or null if
         *      the cookie doesn't exist. If the converter is specified, returns the value
         *      returned from the converter or null if the cookie doesn't exist.
         * @method get
         * @static
         */
        get : function (name, options) {

            validateCookieName(name);   //throws error

            var cookies,
                cookie,
                converter;

            //if options is a function, then it's the converter
            if (isFunction(options)) {
                converter = options;
                options = {};
            } else if (isObject(options)) {
                converter = options.converter;
            } else {
                options = {};
            }

            cookies = this._parseCookieString(doc.cookie, !options.raw, options);
            cookie = cookies[name];

            //should return null, not undefined if the cookie doesn't exist
            if (isUndefined(cookie)) {
                return NULL;
            }

            if (!isFunction(converter)){
                return cookie;
            } else {
                return converter(cookie);
            }
        },

        /**
         * Returns the value of a subcookie.
         * @param {String} name The name of the cookie to retrieve.
         * @param {String} subName The name of the subcookie to retrieve.
         * @param {Function} converter (Optional) A function to run on the value before returning
         *      it. The function is not used if the cookie doesn't exist.
         * @param {Object} options (Optional) Containing one or more settings for cookie parsing.
         * @return {Any} If the cookie doesn't exist, null is returned. If the subcookie
         *      doesn't exist, null if also returned. If no converter is specified and the
         *      subcookie exists, a string is returned. If a converter is specified and the
         *      subcookie exists, the value returned from the converter is returned.
         * @method getSub
         * @static
         */
        getSub : function (name /*:String*/, subName /*:String*/, converter /*:Function*/, options /*:Object*/) /*:Variant*/ {

            var hash /*:Variant*/ = this.getSubs(name, options);

            if (hash !== NULL) {

                validateSubcookieName(subName);   //throws error

                if (isUndefined(hash[subName])){
                    return NULL;
                }

                if (!isFunction(converter)){
                    return hash[subName];
                } else {
                    return converter(hash[subName]);
                }
            } else {
                return NULL;
            }

        },

        /**
         * Returns an object containing name-value pairs stored in the cookie with the given name.
         * @param {String} name The name of the cookie to retrieve.
         * @param {Object} options (Optional) Containing one or more settings for cookie parsing.
         * @return {Object} An object of name-value pairs if the cookie with the given name
         *      exists, null if it does not.
         * @method getSubs
         * @static
         */
        getSubs : function (name /*:String*/, options /*:Object*/) {

            validateCookieName(name);   //throws error

            var cookies = this._parseCookieString(doc.cookie, false, options);
            if (isString(cookies[name])){
                return this._parseCookieHash(cookies[name]);
            }
            return NULL;
        },

        /**
         * Removes a cookie from the machine by setting its expiration date to
         * sometime in the past.
         * @param {String} name The name of the cookie to remove.
         * @param {Object} options (Optional) An object containing one or more
         *      cookie options: path (a string), domain (a string),
         *      and secure (true/false). The expires option will be overwritten
         *      by the method.
         * @return {String} The created cookie string.
         * @method remove
         * @static
         */
        remove : function (name, options) {

            validateCookieName(name);   //throws error

            //set options
            options = Y.merge(options || {}, {
                expires: new Date(0)
            });

            //set cookie
            return this.set(name, "", options);
        },

        /**
         * Removes a sub cookie with a given name.
         * @param {String} name The name of the cookie in which the subcookie exists.
         * @param {String} subName The name of the subcookie to remove.
         * @param {Object} options (Optional) An object containing one or more
         *      cookie options: path (a string), domain (a string), expires (a Date object),
         *      removeIfEmpty (true/false), and secure (true/false). This must be the same
         *      settings as the original subcookie.
         * @return {String} The created cookie string.
         * @method removeSub
         * @static
         */
        removeSub : function(name, subName, options) {

            validateCookieName(name);   //throws error

            validateSubcookieName(subName);   //throws error

            options = options || {};

            //get all subcookies for this cookie
            var subs = this.getSubs(name);

            //delete the indicated subcookie
            if (isObject(subs) && subs.hasOwnProperty(subName)){
                delete subs[subName];

                if (!options.removeIfEmpty) {
                    //reset the cookie

                    return this.setSubs(name, subs, options);
                } else {
                    //reset the cookie if there are subcookies left, else remove
                    for (var key in subs){
                        if (subs.hasOwnProperty(key) && !isFunction(subs[key]) && !isUndefined(subs[key])){
                            return this.setSubs(name, subs, options);
                        }
                    }

                    return this.remove(name, options);
                }
            } else {
                return "";
            }

        },

        /**
         * Sets a cookie with a given name and value.
         * @param {String} name The name of the cookie to set.
         * @param {Any} value The value to set for the cookie.
         * @param {Object} options (Optional) An object containing one or more
         *      cookie options: path (a string), domain (a string), expires (a Date object),
         *      secure (true/false), and raw (true/false). Setting raw to true indicates
         *      that the cookie should not be URI encoded before being set.
         * @return {String} The created cookie string.
         * @method set
         * @static
         */
        set : function (name, value, options) {

            validateCookieName(name);   //throws error

            if (isUndefined(value)){
                error("Cookie.set(): Value cannot be undefined.");
            }

            options = options || {};

            var text = this._createCookieString(name, value, !options.raw, options);
            doc.cookie = text;
            return text;
        },

        /**
         * Sets a sub cookie with a given name to a particular value.
         * @param {String} name The name of the cookie to set.
         * @param {String} subName The name of the subcookie to set.
         * @param {Any} value The value to set.
         * @param {Object} options (Optional) An object containing one or more
         *      cookie options: path (a string), domain (a string), expires (a Date object),
         *      and secure (true/false).
         * @return {String} The created cookie string.
         * @method setSub
         * @static
         */
        setSub : function (name, subName, value, options) {

            validateCookieName(name);   //throws error

            validateSubcookieName(subName);   //throws error

            if (isUndefined(value)){
                error("Cookie.setSub(): Subcookie value cannot be undefined.");
            }

            var hash = this.getSubs(name);

            if (!isObject(hash)){
                hash = {};
            }

            hash[subName] = value;

            return this.setSubs(name, hash, options);

        },

        /**
         * Sets a cookie with a given name to contain a hash of name-value pairs.
         * @param {String} name The name of the cookie to set.
         * @param {Object} value An object containing name-value pairs.
         * @param {Object} options (Optional) An object containing one or more
         *      cookie options: path (a string), domain (a string), expires (a Date object),
         *      and secure (true/false).
         * @return {String} The created cookie string.
         * @method setSubs
         * @static
         */
        setSubs : function (name, value, options) {

            validateCookieName(name);   //throws error

            if (!isObject(value)){
                error("Cookie.setSubs(): Cookie value must be an object.");
            }

            var text /*:String*/ = this._createCookieString(name, this._createCookieHashString(value), false, options);
            doc.cookie = text;
            return text;
        }

    };


}, 'patched-v3.18.1', {"requires": ["yui-base"]});

YUI.add('event-touch', function (Y, NAME) {

/**
Adds touch event facade normalization properties (touches, changedTouches, targetTouches etc.) to the DOM event facade. Adds
touch events to the DOM events whitelist.

@example
    YUI().use('event-touch', function (Y) {
        Y.one('#myDiv').on('touchstart', function(e) {
            ...
        });
    });
@module event
@submodule event-touch
 */
var SCALE = "scale",
    ROTATION = "rotation",
    IDENTIFIER = "identifier",
    win = Y.config.win,
    GESTURE_MAP = {};

/**
 * Adds touch event facade normalization properties to the DOM event facade
 *
 * @method _touch
 * @for DOMEventFacade
 * @private
 * @param ev {Event} the DOM event
 * @param currentTarget {HTMLElement} the element the listener was attached to
 * @param wrapper {CustomEvent} the custom event wrapper for this DOM event
 */
Y.DOMEventFacade.prototype._touch = function(e, currentTarget, wrapper) {

    var i,l, etCached, et,touchCache;


    if (e.touches) {

        /**
         * Array of individual touch events for touch points that are still in
         * contact with the touch surface.
         *
         * @property touches
         * @type {DOMEventFacade[]}
         */
        this.touches = [];
        touchCache = {};

        for (i = 0, l = e.touches.length; i < l; ++i) {
            et = e.touches[i];
            touchCache[Y.stamp(et)] = this.touches[i] = new Y.DOMEventFacade(et, currentTarget, wrapper);
        }
    }

    if (e.targetTouches) {

        /**
         * Array of individual touch events still in contact with the touch
         * surface and whose `touchstart` event occurred inside the same taregt
         * element as the current target element.
         *
         * @property targetTouches
         * @type {DOMEventFacade[]}
         */
        this.targetTouches = [];

        for (i = 0, l = e.targetTouches.length; i < l; ++i) {
            et = e.targetTouches[i];
            etCached = touchCache && touchCache[Y.stamp(et, true)];

            this.targetTouches[i] = etCached || new Y.DOMEventFacade(et, currentTarget, wrapper);

        }
    }

    if (e.changedTouches) {

        /**
        An array of event-specific touch events.

        For `touchstart`, the touch points that became active with the current
        event.

        For `touchmove`, the touch points that have changed since the last
        event.

        For `touchend`, the touch points that have been removed from the touch
        surface.

        @property changedTouches
        @type {DOMEventFacade[]}
        **/
        this.changedTouches = [];

        for (i = 0, l = e.changedTouches.length; i < l; ++i) {
            et = e.changedTouches[i];
            etCached = touchCache && touchCache[Y.stamp(et, true)];

            this.changedTouches[i] = etCached || new Y.DOMEventFacade(et, currentTarget, wrapper);

        }
    }

    if (SCALE in e) {
        this[SCALE] = e[SCALE];
    }

    if (ROTATION in e) {
        this[ROTATION] = e[ROTATION];
    }

    if (IDENTIFIER in e) {
        this[IDENTIFIER] = e[IDENTIFIER];
    }
};

//Adding MSPointer events to whitelisted DOM Events. MSPointer event payloads
//have the same properties as mouse events.
if (Y.Node.DOM_EVENTS) {
    Y.mix(Y.Node.DOM_EVENTS, {
        touchstart:1,
        touchmove:1,
        touchend:1,
        touchcancel:1,
        gesturestart:1,
        gesturechange:1,
        gestureend:1,
        MSPointerDown:1,
        MSPointerUp:1,
        MSPointerMove:1,
        MSPointerCancel:1,
        pointerdown:1,
        pointerup:1,
        pointermove:1,
        pointercancel:1
    });
}

//Add properties to Y.EVENT.GESTURE_MAP based on feature detection.
if ((win && ("ontouchstart" in win)) && !(Y.UA.chrome && Y.UA.chrome < 6)) {
    GESTURE_MAP.start = ["touchstart", "mousedown"];
    GESTURE_MAP.end = ["touchend", "mouseup"];
    GESTURE_MAP.move = ["touchmove", "mousemove"];
    GESTURE_MAP.cancel = ["touchcancel", "mousecancel"];
}

else if (win && win.PointerEvent) {
    GESTURE_MAP.start = "pointerdown";
    GESTURE_MAP.end = "pointerup";
    GESTURE_MAP.move = "pointermove";
    GESTURE_MAP.cancel = "pointercancel";
}

else if (win && ("msPointerEnabled" in win.navigator)) {
    GESTURE_MAP.start = "MSPointerDown";
    GESTURE_MAP.end = "MSPointerUp";
    GESTURE_MAP.move = "MSPointerMove";
    GESTURE_MAP.cancel = "MSPointerCancel";
}

else {
    GESTURE_MAP.start = "mousedown";
    GESTURE_MAP.end = "mouseup";
    GESTURE_MAP.move = "mousemove";
    GESTURE_MAP.cancel = "mousecancel";
}

/**
 * A object literal with keys "start", "end", and "move". The value for each key is a
 * string representing the event for that environment. For touch environments, the respective
 * values are "touchstart", "touchend" and "touchmove". Mouse and MSPointer environments are also
 * supported via feature detection.
 *
 * @property _GESTURE_MAP
 * @type Object
 * @static
 */
Y.Event._GESTURE_MAP = GESTURE_MAP;


}, 'patched-v3.18.1', {"requires": ["node-base"]});

YUI.add('overlay', function (Y, NAME) {

/**
 * Provides a basic Overlay widget, with Standard Module content support. The Overlay widget
 * provides Page XY positioning support, alignment and centering support along with basic
 * stackable support (z-index and shimming).
 *
 * @module overlay
 */

/**
 * A basic Overlay Widget, which can be positioned based on Page XY co-ordinates and is stackable (z-index support).
 * It also provides alignment and centering support and uses a standard module format for it's content, with header,
 * body and footer section support.
 *
 * @class Overlay
 * @constructor
 * @extends Widget
 * @uses WidgetStdMod
 * @uses WidgetPosition
 * @uses WidgetStack
 * @uses WidgetPositionAlign
 * @uses WidgetPositionConstrain
 * @param {Object} object The user configuration for the instance.
 */
Y.Overlay = Y.Base.create("overlay", Y.Widget, [Y.WidgetStdMod, Y.WidgetPosition, Y.WidgetStack, Y.WidgetPositionAlign, Y.WidgetPositionConstrain]);


}, 'patched-v3.18.1', {
    "requires": [
        "widget",
        "widget-stdmod",
        "widget-position",
        "widget-position-align",
        "widget-stack",
        "widget-position-constrain"
    ],
    "skinnable": true
});

YUI.add('querystring-stringify', function (Y, NAME) {

/**
 * Provides Y.QueryString.stringify method for converting objects to Query Strings.
 *
 * @module querystring
 * @submodule querystring-stringify
 */

var QueryString = Y.namespace("QueryString"),
    stack = [],
    L = Y.Lang;

/**
 * Provides Y.QueryString.escape method to be able to override default encoding
 * method.  This is important in cases where non-standard delimiters are used, if
 * the delimiters would not normally be handled properly by the builtin
 * (en|de)codeURIComponent functions.
 * Default: encodeURIComponent
 *
 * @method escape
 * @for QueryString
 * @static
 **/
QueryString.escape = encodeURIComponent;

/**
 * <p>Converts an arbitrary value to a Query String representation.</p>
 *
 * <p>Objects with cyclical references will trigger an exception.</p>
 *
 * @method stringify
 * @for QueryString
 * @public
 * @param obj {Any} any arbitrary value to convert to query string
 * @param cfg {Object} (optional) Configuration object.  The three
 * supported configurations are:
 * <ul><li>sep: When defined, the value will be used as the key-value
 * separator.  The default value is "&".</li>
 * <li>eq: When defined, the value will be used to join the key to
 * the value.  The default value is "=".</li>
 * <li>arrayKey: When set to true, the key of an array will have the
 * '[]' notation appended to the key.  The default value is false.
 * </li></ul>
 * @param name {String} (optional) Name of the current key, for handling children recursively.
 * @static
 */
QueryString.stringify = function (obj, c, name) {
    var begin, end, i, l, n, s,
        sep = c && c.sep ? c.sep : "&",
        eq = c && c.eq ? c.eq : "=",
        aK = c && c.arrayKey ? c.arrayKey : false;

    if (L.isNull(obj) || L.isUndefined(obj) || L.isFunction(obj)) {
        return name ? QueryString.escape(name) + eq : '';
    }

    if (L.isBoolean(obj) || Object.prototype.toString.call(obj) === '[object Boolean]') {
        obj =+ obj;
    }

    if (L.isNumber(obj) || L.isString(obj)) {
        return QueryString.escape(name) + eq + QueryString.escape(obj);
    }

    if (L.isArray(obj)) {
        s = [];
        name = aK ? name + '[]' : name;
        l = obj.length;
        for (i = 0; i < l; i++) {
            s.push( QueryString.stringify(obj[i], c, name) );
        }

        return s.join(sep);
    }
    // now we know it's an object.

    // Check for cyclical references in nested objects
    for (i = stack.length - 1; i >= 0; --i) {
        if (stack[i] === obj) {
            throw new Error("QueryString.stringify. Cyclical reference");
        }
    }

    stack.push(obj);
    s = [];
    begin = name ? name + '[' : '';
    end = name ? ']' : '';
    for (i in obj) {
        if (obj.hasOwnProperty(i)) {
            n = begin + i + end;
            s.push(QueryString.stringify(obj[i], c, n));
        }
    }

    stack.pop();
    s = s.join(sep);
    if (!s && name) {
        return name + "=";
    }

    return s;
};


}, 'patched-v3.18.1', {"requires": ["yui-base"]});

YUI.add('widget-child', function (Y, NAME) {

/**
 * Extension enabling a Widget to be a child of another Widget.
 *
 * @module widget-child
 */

var Lang = Y.Lang;

/**
 * Widget extension providing functionality enabling a Widget to be a
 * child of another Widget.
 *
 * @class WidgetChild
 * @param {Object} config User configuration object.
*/
function Child() {

    //  Widget method overlap
    Y.after(this._syncUIChild, this, "syncUI");
    Y.after(this._bindUIChild, this, "bindUI");

}

Child.ATTRS = {

    /**
     * @attribute selected
     * @type Number
     * @default 0
     *
     * @description Number indicating if the Widget is selected.  Possible
     * values are:
     * <dl>
     * <dt>0</dt> <dd>(Default) Not selected</dd>
     * <dt>1</dt> <dd>Fully selected</dd>
     * <dt>2</dt> <dd>Partially selected</dd>
     * </dl>
    */
    selected: {
        value: 0,
        validator: Lang.isNumber
    },


    /**
     * @attribute index
     * @type Number
     * @readOnly
     *
     * @description Number representing the Widget's ordinal position in its
     * parent Widget.
     */
    index: {
        readOnly: true,
        getter: function () {

            var parent = this.get("parent"),
                index = -1;

            if (parent) {
                index = parent.indexOf(this);
            }

            return index;

        }
    },


    /**
     * @attribute parent
     * @type Widget
     * @readOnly
     *
     * @description Retrieves the parent of the Widget in the object hierarchy.
    */
    parent: {
        readOnly: true
    },


    /**
     * @attribute depth
     * @type Number
     * @default -1
     * @readOnly
     *
     * @description Number representing the depth of this Widget relative to
     * the root Widget in the object heirarchy.
     */
    depth: {
        readOnly: true,
        getter: function () {

            var parent = this.get("parent"),
                root = this.get("root"),
                depth = -1;

            while (parent) {

                depth = (depth + 1);

                if (parent == root) {
                    break;
                }

                parent = parent.get("parent");

            }

            return depth;

        }
    },

    /**
     * @attribute root
     * @type Widget
     * @readOnly
     *
     * @description Returns the root Widget in the object hierarchy.  If the
     * ROOT_TYPE property is set, the search for the root Widget will be
     * constrained to parent Widgets of the specified type.
     */
    root: {
        readOnly: true,
        getter: function () {

            var getParent = function (child) {

                var parent = child.get("parent"),
                    FnRootType = child.ROOT_TYPE,
                    criteria = parent;

                if (FnRootType) {
                    criteria = (parent && Y.instanceOf(parent, FnRootType));
                }

                return (criteria ? getParent(parent) : child);

            };

            return getParent(this);

        }
    }

};

Child.prototype = {

    /**
     * Constructor reference used to determine the root of a Widget-based
     * object tree.
     * <p>
     * Currently used to control the behavior of the <code>root</code>
     * attribute so that recursing up the object heirarchy can be constrained
     * to a specific type of Widget.  Widget authors should set this property
     * to the constructor function for a given Widget implementation.
     * </p>
     *
     * @property ROOT_TYPE
     * @type Object
     */
    ROOT_TYPE: null,

    /**
     * Returns the node on which to bind delegate listeners.
     *
     * Override of Widget's implementation of _getUIEventNode() to ensure that
     * all event listeners are bound to the Widget's topmost DOM element.
     * This ensures that the firing of each type of Widget UI event (click,
     * mousedown, etc.) is facilitated by a single, top-level, delegated DOM
     * event listener.
     *
     * @method _getUIEventNode
     * @for Widget
     * @protected
     */
    _getUIEventNode: function () {
        var root = this.get("root"),
            returnVal;

        if (root) {
            returnVal = root.get("boundingBox");
        }

        return returnVal;
    },

    /**
    * @method next
    * @description Returns the Widget's next sibling.
    * @param {Boolean} circular Boolean indicating if the parent's first child
    * should be returned if the child has no next sibling.
    * @return {Widget} Widget instance.
    */
    next: function (circular) {

        var parent = this.get("parent"),
            sibling;

        if (parent) {
            sibling = parent.item((this.get("index")+1));
        }

        if (!sibling && circular) {
            sibling = parent.item(0);
        }

        return sibling;

    },


    /**
    * @method previous
    * @description Returns the Widget's previous sibling.
    * @param {Boolean} circular Boolean indicating if the parent's last child
    * should be returned if the child has no previous sibling.
    * @return {Widget} Widget instance.
    */
    previous: function (circular) {

        var parent = this.get("parent"),
            index = this.get("index"),
            sibling;

        if (parent && index > 0) {
            sibling = parent.item([(index-1)]);
        }

        if (!sibling && circular) {
            sibling = parent.item((parent.size() - 1));
        }

        return sibling;

    },


    //  Override of Y.WidgetParent.remove()
    //  Sugar implementation allowing a child to remove itself from its parent.
    remove: function (index) {

        var parent,
            removed;

        if (Lang.isNumber(index)) {
            removed = Y.WidgetParent.prototype.remove.apply(this, arguments);
        }
        else {

            parent = this.get("parent");

            if (parent) {
                removed = parent.remove(this.get("index"));
            }

        }

        return removed;

    },


    /**
    * @method isRoot
    * @description Determines if the Widget is the root Widget in the
    * object hierarchy.
    * @return {Boolean} Boolean indicating if Widget is the root Widget in the
    * object hierarchy.
    */
    isRoot: function () {
        return (this == this.get("root"));
    },


    /**
    * @method ancestor
    * @description Returns the Widget instance at the specified depth.
    * @param {number} depth Number representing the depth of the ancestor.
    * @return {Widget} Widget instance.
    */
    ancestor: function (depth) {

        var root = this.get("root"),
            parent;

        if (this.get("depth") > depth)  {

            parent = this.get("parent");

            while (parent != root && parent.get("depth") > depth) {
                parent = parent.get("parent");
            }

        }

        return parent;

    },


    /**
     * Updates the UI to reflect the <code>selected</code> attribute value.
     *
     * @method _uiSetChildSelected
     * @protected
     * @param {number} selected The selected value to be reflected in the UI.
     */
    _uiSetChildSelected: function (selected) {

        var box = this.get("boundingBox"),
            sClassName = this.getClassName("selected");

        if (selected === 0) {
            box.removeClass(sClassName);
        }
        else {
            box.addClass(sClassName);
        }

    },


    /**
     * Default attribute change listener for the <code>selected</code>
     * attribute, responsible for updating the UI, in response to
     * attribute changes.
     *
     * @method _afterChildSelectedChange
     * @protected
     * @param {EventFacade} event The event facade for the attribute change.
     */
    _afterChildSelectedChange: function (event) {
        this._uiSetChildSelected(event.newVal);
    },


    /**
     * Synchronizes the UI to match the WidgetChild state.
     * <p>
     * This method is invoked after bindUI is invoked for the Widget class
     * using YUI's aop infrastructure.
     * </p>
     *
     * @method _syncUIChild
     * @protected
     */
    _syncUIChild: function () {
        this._uiSetChildSelected(this.get("selected"));
    },


    /**
     * Binds event listeners responsible for updating the UI state in response
     * to WidgetChild related state changes.
     * <p>
     * This method is invoked after bindUI is invoked for the Widget class
     * using YUI's aop infrastructure.
     * </p>
     * @method _bindUIChild
     * @protected
     */
    _bindUIChild: function () {
        this.after("selectedChange", this._afterChildSelectedChange);
    }

};

Y.WidgetChild = Child;


}, 'patched-v3.18.1', {"requires": ["base-build", "widget"]});

YUI.add('widget-position-align', function (Y, NAME) {

/**
Provides extended/advanced XY positioning support for Widgets, through an
extension.

It builds on top of the `widget-position` module, to provide alignment and
centering support. Future releases aim to add constrained and fixed positioning
support.

@module widget-position-align
**/
var Lang = Y.Lang,

    ALIGN        = 'align',
    ALIGN_ON     = 'alignOn',

    VISIBLE      = 'visible',
    BOUNDING_BOX = 'boundingBox',

    OFFSET_WIDTH    = 'offsetWidth',
    OFFSET_HEIGHT   = 'offsetHeight',
    REGION          = 'region',
    VIEWPORT_REGION = 'viewportRegion';

/**
Widget extension, which can be used to add extended XY positioning support to
the base Widget class, through the `Base.create` method.

**Note:** This extension requires that the `WidgetPosition` extension be added
to the Widget (before `WidgetPositionAlign`, if part of the same extension list
passed to `Base.build`).

@class WidgetPositionAlign
@param {Object} config User configuration object.
@constructor
**/
function PositionAlign (config) {}

PositionAlign.ATTRS = {

    /**
    The alignment configuration for this widget.

    The `align` attribute is used to align a reference point on the widget, with
    the reference point on another `Node`, or the viewport. The object which
    `align` expects has the following properties:

      * __`node`__: The `Node` to which the widget is to be aligned. If set to
        `null`, or not provided, the widget is aligned to the viewport.

      * __`points`__: A two element Array, defining the two points on the widget
        and `Node`/viewport which are to be aligned. The first element is the
        point on the widget, and the second element is the point on the
        `Node`/viewport. Supported alignment points are defined as static
        properties on `WidgetPositionAlign`.

    @example Aligns the top-right corner of the widget with the top-left corner
    of the viewport:

        myWidget.set('align', {
            points: [Y.WidgetPositionAlign.TR, Y.WidgetPositionAlign.TL]
        });

    @attribute align
    @type Object
    @default null
    **/
    align: {
        value: null
    },

    /**
    A convenience Attribute, which can be used as a shortcut for the `align`
    Attribute.

    If set to `true`, the widget is centered in the viewport. If set to a `Node`
    reference or valid selector String, the widget will be centered within the
    `Node`. If set to `false`, no center positioning is applied.

    @attribute centered
    @type Boolean|Node
    @default false
    **/
    centered: {
        setter : '_setAlignCenter',
        lazyAdd:false,
        value  :false
    },

    /**
    An Array of Objects corresponding to the `Node`s and events that will cause
    the alignment of this widget to be synced to the DOM.

    The `alignOn` Attribute is expected to be an Array of Objects with the
    following properties:

      * __`eventName`__: The String event name to listen for.

      * __`node`__: The optional `Node` that will fire the event, it can be a
        `Node` reference or a selector String. This will default to the widget's
        `boundingBox`.

    @example Sync this widget's alignment on window resize:

        myWidget.set('alignOn', [
            {
                node     : Y.one('win'),
                eventName: 'resize'
            }
        ]);

    @attribute alignOn
    @type Array
    @default []
    **/
    alignOn: {
        value    : [],
        validator: Y.Lang.isArray
    }
};

/**
Constant used to specify the top-left corner for alignment

@property TL
@type String
@value 'tl'
@static
**/
PositionAlign.TL = 'tl';

/**
Constant used to specify the top-right corner for alignment

@property TR
@type String
@value 'tr'
@static
**/
PositionAlign.TR = 'tr';

/**
Constant used to specify the bottom-left corner for alignment

@property BL
@type String
@value 'bl'
@static
**/
PositionAlign.BL = 'bl';

/**
Constant used to specify the bottom-right corner for alignment

@property BR
@type String
@value 'br'
@static
**/
PositionAlign.BR = 'br';

/**
Constant used to specify the top edge-center point for alignment

@property TC
@type String
@value 'tc'
@static
**/
PositionAlign.TC = 'tc';

/**
Constant used to specify the right edge, center point for alignment

@property RC
@type String
@value 'rc'
@static
**/
PositionAlign.RC = 'rc';

/**
Constant used to specify the bottom edge, center point for alignment

@property BC
@type String
@value 'bc'
@static
**/
PositionAlign.BC = 'bc';

/**
Constant used to specify the left edge, center point for alignment

@property LC
@type String
@value 'lc'
@static
**/
PositionAlign.LC = 'lc';

/**
Constant used to specify the center of widget/node/viewport for alignment

@property CC
@type String
@value 'cc'
@static
*/
PositionAlign.CC = 'cc';

PositionAlign.prototype = {
    // -- Protected Properties -------------------------------------------------


    initializer : function() {
        if (!this._posNode) {
            Y.error('WidgetPosition needs to be added to the Widget, ' +
                'before WidgetPositionAlign is added');
        }

        Y.after(this._bindUIPosAlign, this, 'bindUI');
        Y.after(this._syncUIPosAlign, this, 'syncUI');
    },

    /**
    Holds the alignment-syncing event handles.

    @property _posAlignUIHandles
    @type Array
    @default null
    @protected
    **/
    _posAlignUIHandles: null,

    // -- Lifecycle Methods ----------------------------------------------------

    destructor: function () {
        this._detachPosAlignUIHandles();
    },

    /**
    Bind event listeners responsible for updating the UI state in response to
    the widget's position-align related state changes.

    This method is invoked after `bindUI` has been invoked for the `Widget`
    class using the AOP infrastructure.

    @method _bindUIPosAlign
    @protected
    **/
    _bindUIPosAlign: function () {
        this.after('alignChange', this._afterAlignChange);
        this.after('alignOnChange', this._afterAlignOnChange);
        this.after('visibleChange', this._syncUIPosAlign);
    },

    /**
    Synchronizes the current `align` Attribute value to the DOM.

    This method is invoked after `syncUI` has been invoked for the `Widget`
    class using the AOP infrastructure.

    @method _syncUIPosAlign
    @protected
    **/
    _syncUIPosAlign: function () {
        var align = this.get(ALIGN);

        this._uiSetVisiblePosAlign(this.get(VISIBLE));

        if (align) {
            this._uiSetAlign(align.node, align.points);
        }
    },

    // -- Public Methods -------------------------------------------------------

    /**
    Aligns this widget to the provided `Node` (or viewport) using the provided
    points. This method can be invoked with no arguments which will cause the
    widget's current `align` Attribute value to be synced to the DOM.

    @example Aligning to the top-left corner of the `<body>`:

        myWidget.align('body',
            [Y.WidgetPositionAlign.TL, Y.WidgetPositionAlign.TR]);

    @method align
    @param {Node|String|null} [node] A reference (or selector String) for the
      `Node` which with the widget is to be aligned. If null is passed in, the
      widget will be aligned with the viewport.
    @param {Array[2]} [points] A two item array specifying the points on the
      widget and `Node`/viewport which will to be aligned. The first entry is
      the point on the widget, and the second entry is the point on the
      `Node`/viewport. Valid point references are defined as static constants on
      the `WidgetPositionAlign` extension.
    @chainable
    **/
    align: function (node, points) {
        if (arguments.length) {
            // Set the `align` Attribute.
            this.set(ALIGN, {
                node  : node,
                points: points
            });
        } else {
            // Sync the current `align` Attribute value to the DOM.
            this._syncUIPosAlign();
        }

        return this;
    },

    /**
    Centers the widget in the viewport, or if a `Node` is passed in, it will
    be centered to that `Node`.

    @method centered
    @param {Node|String} [node] A `Node` reference or selector String defining
      the `Node` which the widget should be centered. If a `Node` is not  passed
      in, then the widget will be centered to the viewport.
    @chainable
    **/
    centered: function (node) {
        return this.align(node, [PositionAlign.CC, PositionAlign.CC]);
    },

    // -- Protected Methods ----------------------------------------------------

    /**
    Returns coordinates realative to the passed `Node` alignment.

    @method _getAlignToXY
    @param {Node} 'Node' The node to align to.
    @param {Array} [point] The node alignment points.
    @param {Number} 'Node' x coordinate.
    @param {Number} 'Node' y coordinate.
    @return {Array} the coordinates.
    @private
    **/
    _getAlignToXY: function (node, point, x, y) {
        var xy;

        switch (point) {
        case PositionAlign.TL:
            xy = [x, y];
            break;

        case PositionAlign.TR:
            xy = [
                x - node.get(OFFSET_WIDTH),
                y
            ];
            break;

        case PositionAlign.BL:
            xy = [
                x,
                y - node.get(OFFSET_HEIGHT)
            ];
            break;

        case PositionAlign.BR:
            xy = [
                x - node.get(OFFSET_WIDTH),
                y - node.get(OFFSET_HEIGHT)
            ];
            break;

        case PositionAlign.TC:
            xy = [
                x - (node.get(OFFSET_WIDTH) / 2),
                y
            ];
            break;

        case PositionAlign.BC:
            xy = [
                x - (node.get(OFFSET_WIDTH) / 2),
                y - node.get(OFFSET_HEIGHT)
            ];
            break;

        case PositionAlign.LC:
            xy = [
                x,
                y - (node.get(OFFSET_HEIGHT) / 2)
            ];
            break;

        case PositionAlign.RC:
            xy = [
                x - node.get(OFFSET_WIDTH),
                y - (node.get(OFFSET_HEIGHT) / 2)
            ];
            break;

        case PositionAlign.CC:
            xy = [
                x - (node.get(OFFSET_WIDTH) / 2),
                y - (node.get(OFFSET_HEIGHT) / 2)
            ];
            break;

        default:
            break;

        }

        return xy;
    },

    /**
    Returns `Widget` alignment coordinates realative to the given `Node`.

    @method _getAlignedXY
    @param {Node|String|null} [node] The node to align to, or null to indicate
      the viewport.
    @param {Array} points The alignment points.
    @return {Array} the coordinates.
    @protected
    **/
    _getAlignedXY: function (node, points) {
        if ( ! Lang.isArray(points) || points.length !== 2) {
            Y.error('align: Invalid Points Arguments');
            return;
        }

        var nodeRegion = this._getRegion(node), nodePoint, xy;

        if ( ! nodeRegion) {
            // No-op, nothing to align to.
            return;
        }

        nodePoint   = points[1];

        // TODO: Optimize KWeight - Would lookup table help?
        switch (nodePoint) {
        case PositionAlign.TL:
            xy = [nodeRegion.left, nodeRegion.top];
            break;

        case PositionAlign.TR:
            xy = [nodeRegion.right, nodeRegion.top];
            break;

        case PositionAlign.BL:
            xy = [nodeRegion.left, nodeRegion.bottom];
            break;

        case PositionAlign.BR:
            xy = [nodeRegion.right, nodeRegion.bottom];
            break;

        case PositionAlign.TC:
            xy = [
                nodeRegion.left + Math.floor(nodeRegion.width / 2),
                nodeRegion.top
            ];
            break;

        case PositionAlign.BC:
            xy = [
                nodeRegion.left + Math.floor(nodeRegion.width / 2),
                nodeRegion.bottom
            ];
            break;

        case PositionAlign.LC:
            xy = [
                nodeRegion.left,
                nodeRegion.top + Math.floor(nodeRegion.height / 2)
            ];
            break;

        case PositionAlign.RC:
            xy = [
                nodeRegion.right,
                nodeRegion.top + Math.floor(nodeRegion.height / 2)
            ];
            break;

        case PositionAlign.CC:
            xy = [
                nodeRegion.left + Math.floor(nodeRegion.width / 2),
                nodeRegion.top + Math.floor(nodeRegion.height / 2)
            ];
            break;

        default:
            break;

        }

        return this._getAlignToXY(this._posNode, points[0], xy[0], xy[1]);
    },

    /**
    Default setter for `center` Attribute changes. Sets up the appropriate
    value, and passes it through the to the align attribute.

    @method _setAlignCenter
    @param {Boolean|Node} val The Attribute value being set.
    @return {Boolean|Node} the value passed in.
    @protected
    **/
    _setAlignCenter: function (val) {
        if (val) {
            this.set(ALIGN, {
                node  : val === true ? null : val,
                points: [PositionAlign.CC, PositionAlign.CC]
            });
        }

        return val;
    },

    /**
    Updates the UI to reflect the `align` value passed in.

    **Note:** See the `align` Attribute documentation, for the Object structure
    expected.

    @method _uiSetAlign
    @param {Node|String|null} [node] The node to align to, or null to indicate
      the viewport.
    @param {Array} points The alignment points.
    @protected
    **/
    _uiSetAlign: function (node, points) {
        var xy = this._getAlignedXY(node, points);

        if (xy) {
            this._doAlign(xy);
        }
    },

    /**
    Attaches or detaches alignment-syncing event handlers based on the widget's
    `visible` Attribute state.

    @method _uiSetVisiblePosAlign
    @param {Boolean} visible The current value of the widget's `visible`
      Attribute.
    @protected
    **/
    _uiSetVisiblePosAlign: function (visible) {
        if (visible) {
            this._attachPosAlignUIHandles();
        } else {
            this._detachPosAlignUIHandles();
        }
    },

    /**
    Attaches the alignment-syncing event handlers.

    @method _attachPosAlignUIHandles
    @protected
    **/
    _attachPosAlignUIHandles: function () {
        if (this._posAlignUIHandles) {
            // No-op if we have already setup the event handlers.
            return;
        }

        var bb        = this.get(BOUNDING_BOX),
            syncAlign = Y.bind(this._syncUIPosAlign, this),
            handles   = [];

        Y.Array.each(this.get(ALIGN_ON), function (o) {
            var event = o.eventName,
                node  = Y.one(o.node) || bb;

            if (event) {
                handles.push(node.on(event, syncAlign));
            }
        });

        this._posAlignUIHandles = handles;
    },

    /**
    Detaches the alignment-syncing event handlers.

    @method _detachPosAlignUIHandles
    @protected
    **/
    _detachPosAlignUIHandles: function () {
        var handles = this._posAlignUIHandles;
        if (handles) {
            new Y.EventHandle(handles).detach();
            this._posAlignUIHandles = null;
        }
    },

    // -- Private Methods ------------------------------------------------------

    /**
    Helper method, used to align the given point on the widget, with the XY page
    coordinates provided.

    @method _doAlign
    @param {Array} xy XY page coordinates to align to.
    @private
    **/
    _doAlign: function(xy) {
        if (xy) {
            this.move(xy);
        }
    },

    /**
    Returns the region of the passed-in `Node`, or the viewport region if
    calling with passing in a `Node`.

    @method _getRegion
    @param {Node} [node] The node to get the region of.
    @return {Object} The node's region.
    @private
    **/
    _getRegion: function (node) {
        var nodeRegion;

        if ( ! node) {
            nodeRegion = this._posNode.get(VIEWPORT_REGION);
        } else {
            node = Y.Node.one(node);
            if (node) {
                nodeRegion = node.get(REGION);
            }
        }

        return nodeRegion;
    },

    // -- Protected Event Handlers ---------------------------------------------

    /**
    Handles `alignChange` events by updating the UI in response to `align`
    Attribute changes.

    @method _afterAlignChange
    @param {EventFacade} e
    @protected
    **/
    _afterAlignChange: function (e) {
        var align = e.newVal;
        if (align) {
            this._uiSetAlign(align.node, align.points);
        }
    },

    /**
    Handles `alignOnChange` events by updating the alignment-syncing event
    handlers.

    @method _afterAlignOnChange
    @param {EventFacade} e
    @protected
    **/
    _afterAlignOnChange: function(e) {
        this._detachPosAlignUIHandles();

        if (this.get(VISIBLE)) {
            this._attachPosAlignUIHandles();
        }
    }
};

Y.WidgetPositionAlign = PositionAlign;


}, 'patched-v3.18.1', {"requires": ["widget-position"]});

YUI.add('widget-position-constrain', function (Y, NAME) {

/**
 * Provides constrained xy positioning support for Widgets, through an extension.
 *
 * It builds on top of the widget-position module, to provide constrained positioning support.
 *
 * @module widget-position-constrain
 */
var CONSTRAIN = "constrain",
    CONSTRAIN_XYCHANGE = "constrain|xyChange",
    CONSTRAIN_CHANGE = "constrainChange",

    PREVENT_OVERLAP = "preventOverlap",
    ALIGN = "align",

    EMPTY_STR = "",

    BINDUI = "bindUI",

    XY = "xy",
    X_COORD = "x",
    Y_COORD = "y",

    Node = Y.Node,

    VIEWPORT_REGION = "viewportRegion",
    REGION = "region",

    PREVENT_OVERLAP_MAP;

/**
 * A widget extension, which can be used to add constrained xy positioning support to the base Widget class,
 * through the <a href="Base.html#method_build">Base.build</a> method. This extension requires that
 * the WidgetPosition extension be added to the Widget (before WidgetPositionConstrain, if part of the same
 * extension list passed to Base.build).
 *
 * @class WidgetPositionConstrain
 * @param {Object} User configuration object
 */
function PositionConstrain(config) {}

/**
 * Static property used to define the default attribute
 * configuration introduced by WidgetPositionConstrain.
 *
 * @property ATTRS
 * @type Object
 * @static
 */
PositionConstrain.ATTRS = {

    /**
     * @attribute constrain
     * @type boolean | Node
     * @default null
     * @description The node to constrain the widget's bounding box to, when setting xy. Can also be
     * set to true, to constrain to the viewport.
     */
    constrain : {
        value: null,
        setter: "_setConstrain"
    },

    /**
     * @attribute preventOverlap
     * @type boolean
     * @description If set to true, and WidgetPositionAlign is also added to the Widget,
     * constrained positioning will attempt to prevent the widget's bounding box from overlapping
     * the element to which it has been aligned, by flipping the orientation of the alignment
     * for corner based alignments
     */
    preventOverlap : {
        value:false
    }
};

/**
 * @property _PREVENT_OVERLAP
 * @static
 * @protected
 * @type Object
 * @description The set of positions for which to prevent
 * overlap.
 */
PREVENT_OVERLAP_MAP = PositionConstrain._PREVENT_OVERLAP = {
    x: {
        "tltr": 1,
        "blbr": 1,
        "brbl": 1,
        "trtl": 1
    },
    y : {
        "trbr": 1,
        "tlbl": 1,
        "bltl": 1,
        "brtr": 1
    }
};

PositionConstrain.prototype = {

    initializer : function() {
        if (!this._posNode) {
            Y.error("WidgetPosition needs to be added to the Widget, before WidgetPositionConstrain is added");
        }
        Y.after(this._bindUIPosConstrained, this, BINDUI);
    },

    /**
     * Calculates the constrained positions for the XY positions provided, using
     * the provided node argument is passed in. If no node value is passed in, the value of
     * the "constrain" attribute is used.
     *
     * @method getConstrainedXY
     * @param {Array} xy The xy values to constrain
     * @param {Node | boolean} node Optional. The node to constrain to, or true for the viewport
     * @return {Array} The constrained xy values
     */
    getConstrainedXY : function(xy, node) {
        node = node || this.get(CONSTRAIN);

        var constrainingRegion = this._getRegion((node === true) ? null : node),
            nodeRegion = this._posNode.get(REGION);

        return [
            this._constrain(xy[0], X_COORD, nodeRegion, constrainingRegion),
            this._constrain(xy[1], Y_COORD, nodeRegion, constrainingRegion)
        ];
    },

    /**
     * Constrains the widget's bounding box to a node (or the viewport). If xy or node are not
     * passed in, the current position and the value of "constrain" will be used respectively.
     *
     * The widget's position will be changed to the constrained position.
     *
     * @method constrain
     * @param {Array} xy Optional. The xy values to constrain
     * @param {Node | boolean} node Optional. The node to constrain to, or true for the viewport
     */
    constrain : function(xy, node) {
        var currentXY,
            constrainedXY,
            constraint = node || this.get(CONSTRAIN);

        if (constraint) {
            currentXY = xy || this.get(XY);
            constrainedXY = this.getConstrainedXY(currentXY, constraint);

            if (constrainedXY[0] !== currentXY[0] || constrainedXY[1] !== currentXY[1]) {
                this.set(XY, constrainedXY, { constrained:true });
            }
        }
    },

    /**
     * The setter implementation for the "constrain" attribute.
     *
     * @method _setConstrain
     * @protected
     * @param {Node | boolean} val The attribute value
     */
    _setConstrain : function(val) {
        return (val === true) ? val : Node.one(val);
    },

    /**
     * The method which performs the actual constrain calculations for a given axis ("x" or "y") based
     * on the regions provided.
     *
     * @method _constrain
     * @protected
     *
     * @param {Number} val The value to constrain
     * @param {String} axis The axis to use for constrainment
     * @param {Region} nodeRegion The region of the node to constrain
     * @param {Region} constrainingRegion The region of the node (or viewport) to constrain to
     *
     * @return {Number} The constrained value
     */
    _constrain: function(val, axis, nodeRegion, constrainingRegion) {
        if (constrainingRegion) {

            if (this.get(PREVENT_OVERLAP)) {
                val = this._preventOverlap(val, axis, nodeRegion, constrainingRegion);
            }

            var x = (axis == X_COORD),

                regionSize    = (x) ? constrainingRegion.width : constrainingRegion.height,
                nodeSize      = (x) ? nodeRegion.width : nodeRegion.height,
                minConstraint = (x) ? constrainingRegion.left : constrainingRegion.top,
                maxConstraint = (x) ? constrainingRegion.right - nodeSize : constrainingRegion.bottom - nodeSize;

            if (val < minConstraint || val > maxConstraint) {
                if (nodeSize < regionSize) {
                    if (val < minConstraint) {
                        val = minConstraint;
                    } else if (val > maxConstraint) {
                        val = maxConstraint;
                    }
                } else {
                    val = minConstraint;
                }
            }
        }

        return val;
    },

    /**
     * The method which performs the preventOverlap calculations for a given axis ("x" or "y") based
     * on the value and regions provided.
     *
     * @method _preventOverlap
     * @protected
     *
     * @param {Number} val The value being constrain
     * @param {String} axis The axis to being constrained
     * @param {Region} nodeRegion The region of the node being constrained
     * @param {Region} constrainingRegion The region of the node (or viewport) we need to constrain to
     *
     * @return {Number} The constrained value
     */
    _preventOverlap : function(val, axis, nodeRegion, constrainingRegion) {

        var align = this.get(ALIGN),
            x = (axis === X_COORD),
            nodeSize,
            alignRegion,
            nearEdge,
            farEdge,
            spaceOnNearSide,
            spaceOnFarSide;

        if (align && align.points && PREVENT_OVERLAP_MAP[axis][align.points.join(EMPTY_STR)]) {

            alignRegion = this._getRegion(align.node);

            if (alignRegion) {
                nodeSize        = (x) ? nodeRegion.width : nodeRegion.height;
                nearEdge        = (x) ? alignRegion.left : alignRegion.top;
                farEdge         = (x) ? alignRegion.right : alignRegion.bottom;
                spaceOnNearSide = (x) ? alignRegion.left - constrainingRegion.left : alignRegion.top - constrainingRegion.top;
                spaceOnFarSide  = (x) ? constrainingRegion.right - alignRegion.right : constrainingRegion.bottom - alignRegion.bottom;
            }

            if (val > nearEdge) {
                if (spaceOnFarSide < nodeSize && spaceOnNearSide > nodeSize) {
                    val = nearEdge - nodeSize;
                }
            } else {
                if (spaceOnNearSide < nodeSize && spaceOnFarSide > nodeSize) {
                    val = farEdge;
                }
            }
        }

        return val;
    },

    /**
     * Binds event listeners responsible for updating the UI state in response to
     * Widget constrained positioning related state changes.
     * <p>
     * This method is invoked after bindUI is invoked for the Widget class
     * using YUI's aop infrastructure.
     * </p>
     *
     * @method _bindUIPosConstrained
     * @protected
     */
    _bindUIPosConstrained : function() {
        this.after(CONSTRAIN_CHANGE, this._afterConstrainChange);
        this._enableConstraints(this.get(CONSTRAIN));
    },

    /**
     * After change listener for the "constrain" attribute, responsible
     * for updating the UI, in response to attribute changes.
     *
     * @method _afterConstrainChange
     * @protected
     * @param {EventFacade} e The event facade
     */
    _afterConstrainChange : function(e) {
        this._enableConstraints(e.newVal);
    },

    /**
     * Updates the UI if enabling constraints, and sets up the xyChange event listeners
     * to constrain whenever the widget is moved. Disabling constraints removes the listeners.
     *
     * @method _enableConstraints
     * @private
     * @param {boolean} enable Enable or disable constraints
     */
    _enableConstraints : function(enable) {
        if (enable) {
            this.constrain();
            this._cxyHandle = this._cxyHandle || this.on(CONSTRAIN_XYCHANGE, this._constrainOnXYChange);
        } else if (this._cxyHandle) {
            this._cxyHandle.detach();
            this._cxyHandle = null;
        }
    },

    /**
     * The on change listener for the "xy" attribute. Modifies the event facade's
     * newVal property with the constrained XY value.
     *
     * @method _constrainOnXYChange
     * @protected
     * @param {EventFacade} e The event facade for the attribute change
     */
    _constrainOnXYChange : function(e) {
        if (!e.constrained) {
            e.newVal = this.getConstrainedXY(e.newVal);
        }
    },

    /**
     * Utility method to normalize region retrieval from a node instance,
     * or the viewport, if no node is provided.
     *
     * @method _getRegion
     * @private
     * @param {Node} node Optional.
     */
    _getRegion : function(node) {
        var region;
        if (!node) {
            region = this._posNode.get(VIEWPORT_REGION);
        } else {
            node = Node.one(node);
            if (node) {
                region = node.get(REGION);
            }
        }
        return region;
    }
};

Y.WidgetPositionConstrain = PositionConstrain;


}, 'patched-v3.18.1', {"requires": ["widget-position"]});

YUI.add('widget-position', function (Y, NAME) {

/**
 * Provides basic XY positioning support for Widgets, though an extension
 *
 * @module widget-position
 */
    var Lang = Y.Lang,
        Widget = Y.Widget,

        XY_COORD = "xy",

        POSITION = "position",
        POSITIONED = "positioned",
        BOUNDING_BOX = "boundingBox",
        RELATIVE = "relative",

        RENDERUI = "renderUI",
        BINDUI = "bindUI",
        SYNCUI = "syncUI",

        UI = Widget.UI_SRC,

        XYChange = "xyChange";

    /**
     * Widget extension, which can be used to add positioning support to the base Widget class,
     * through the <a href="Base.html#method_build">Base.build</a> method.
     *
     * @class WidgetPosition
     * @param {Object} config User configuration object
     */
    function Position(config) {
    }

    /**
     * Static property used to define the default attribute
     * configuration introduced by WidgetPosition.
     *
     * @property ATTRS
     * @static
     * @type Object
     */
    Position.ATTRS = {

        /**
         * @attribute x
         * @type number
         * @default 0
         *
         * @description Page X co-ordinate for the widget. This attribute acts as a facade for the
         * xy attribute. Changes in position can be monitored by listening for xyChange events.
         */
        x: {
            setter: function(val) {
                this._setX(val);
            },
            getter: function() {
                return this._getX();
            },
            lazyAdd:false
        },

        /**
         * @attribute y
         * @type number
         * @default 0
         *
         * @description Page Y co-ordinate for the widget. This attribute acts as a facade for the
         * xy attribute. Changes in position can be monitored by listening for xyChange events.
         */
        y: {
            setter: function(val) {
                this._setY(val);
            },
            getter: function() {
                return this._getY();
            },
            lazyAdd: false
        },

        /**
         * @attribute xy
         * @type Array
         * @default [0,0]
         *
         * @description Page XY co-ordinate pair for the widget.
         */
        xy: {
            value:[0,0],
            validator: function(val) {
                return this._validateXY(val);
            }
        }
    };

    /**
     * Default class used to mark the boundingBox of a positioned widget.
     *
     * @property POSITIONED_CLASS_NAME
     * @type String
     * @default "yui-widget-positioned"
     * @static
     */
    Position.POSITIONED_CLASS_NAME = Widget.getClassName(POSITIONED);

    Position.prototype = {

        initializer : function() {
            this._posNode = this.get(BOUNDING_BOX);

            // WIDGET METHOD OVERLAP
            Y.after(this._renderUIPosition, this, RENDERUI);
            Y.after(this._syncUIPosition, this, SYNCUI);
            Y.after(this._bindUIPosition, this, BINDUI);
        },

        /**
         * Creates/Initializes the DOM to support xy page positioning.
         * <p>
         * This method in invoked after renderUI is invoked for the Widget class
         * using YUI's aop infrastructure.
         * </p>
         * @method _renderUIPosition
         * @protected
         */
        _renderUIPosition : function() {
            this._posNode.addClass(Position.POSITIONED_CLASS_NAME);
        },

        /**
         * Synchronizes the UI to match the Widgets xy page position state.
         * <p>
         * This method in invoked after syncUI is invoked for the Widget class
         * using YUI's aop infrastructure.
         * </p>
         * @method _syncUIPosition
         * @protected
         */
        _syncUIPosition : function() {
            var posNode = this._posNode;
            if (posNode.getStyle(POSITION) === RELATIVE) {
                this.syncXY();
            }
            this._uiSetXY(this.get(XY_COORD));
        },

        /**
         * Binds event listeners responsible for updating the UI state in response to
         * Widget position related state changes.
         * <p>
         * This method in invoked after bindUI is invoked for the Widget class
         * using YUI's aop infrastructure.
         * </p>
         * @method _bindUIPosition
         * @protected
         */
        _bindUIPosition :function() {
            this.after(XYChange, this._afterXYChange);
        },

        /**
         * Moves the Widget to the specified page xy co-ordinate position.
         *
         * @method move
         *
         * @param {Number|Number[]} x The new x position or [x, y] values passed
         * as an array to support simple pass through of Node.getXY results
         * @param {Number} [y] The new y position
         */
        move: function () {
            var args = arguments,
                coord = (Lang.isArray(args[0])) ? args[0] : [args[0], args[1]];
                this.set(XY_COORD, coord);
        },

        /**
         * Synchronizes the Panel's "xy", "x", and "y" properties with the
         * Widget's position in the DOM.
         *
         * @method syncXY
         */
        syncXY : function () {
            this.set(XY_COORD, this._posNode.getXY(), {src: UI});
        },

        /**
         * Default validator for the XY attribute
         *
         * @method _validateXY
         * @protected
         * @param {Array} val The XY page co-ordinate value which is being set.
         * @return {boolean} true if valid, false if not.
         */
        _validateXY : function(val) {
            return (Lang.isArray(val) && Lang.isNumber(val[0]) && Lang.isNumber(val[1]));
        },

        /**
         * Default setter for the X attribute. The setter passes the X value through
         * to the XY attribute, which is the sole store for the XY state.
         *
         * @method _setX
         * @protected
         * @param {Number} val The X page co-ordinate value
         */
        _setX : function(val) {
            this.set(XY_COORD, [val, this.get(XY_COORD)[1]]);
        },

        /**
         * Default setter for the Y attribute. The setter passes the Y value through
         * to the XY attribute, which is the sole store for the XY state.
         *
         * @method _setY
         * @protected
         * @param {Number} val The Y page co-ordinate value
         */
        _setY : function(val) {
            this.set(XY_COORD, [this.get(XY_COORD)[0], val]);
        },

        /**
         * Default getter for the X attribute. The value is retrieved from
         * the XY attribute, which is the sole store for the XY state.
         *
         * @method _getX
         * @protected
         * @return {Number} The X page co-ordinate value
         */
        _getX : function() {
            return this.get(XY_COORD)[0];
        },

        /**
         * Default getter for the Y attribute. The value is retrieved from
         * the XY attribute, which is the sole store for the XY state.
         *
         * @method _getY
         * @protected
         * @return {Number} The Y page co-ordinate value
         */
        _getY : function() {
            return this.get(XY_COORD)[1];
        },

        /**
         * Default attribute change listener for the xy attribute, responsible
         * for updating the UI, in response to attribute changes.
         *
         * @method _afterXYChange
         * @protected
         * @param {EventFacade} e The event facade for the attribute change
         */
        _afterXYChange : function(e) {
            if (e.src != UI) {
                this._uiSetXY(e.newVal);
            }
        },

        /**
         * Updates the UI to reflect the XY page co-ordinates passed in.
         *
         * @method _uiSetXY
         * @protected
         * @param {String} val The XY page co-ordinates value to be reflected in the UI
         */
        _uiSetXY : function(val) {
            this._posNode.setXY(val);
        }
    };

    Y.WidgetPosition = Position;


}, 'patched-v3.18.1', {"requires": ["base-build", "node-screen", "widget"]});

YUI.add('widget-stack', function (Y, NAME) {

/**
 * Provides stackable (z-index) support for Widgets through an extension.
 *
 * @module widget-stack
 */
    var L = Y.Lang,
        UA = Y.UA,
        Node = Y.Node,
        Widget = Y.Widget,

        ZINDEX = "zIndex",
        SHIM = "shim",
        VISIBLE = "visible",

        BOUNDING_BOX = "boundingBox",

        RENDER_UI = "renderUI",
        BIND_UI = "bindUI",
        SYNC_UI = "syncUI",

        OFFSET_WIDTH = "offsetWidth",
        OFFSET_HEIGHT = "offsetHeight",
        PARENT_NODE = "parentNode",
        FIRST_CHILD = "firstChild",
        OWNER_DOCUMENT = "ownerDocument",

        WIDTH = "width",
        HEIGHT = "height",
        PX = "px",

        // HANDLE KEYS
        SHIM_DEFERRED = "shimdeferred",
        SHIM_RESIZE = "shimresize",

        // Events
        VisibleChange = "visibleChange",
        WidthChange = "widthChange",
        HeightChange = "heightChange",
        ShimChange = "shimChange",
        ZIndexChange = "zIndexChange",
        ContentUpdate = "contentUpdate",

        // CSS
        STACKED = "stacked";

    /**
     * Widget extension, which can be used to add stackable (z-index) support to the
     * base Widget class along with a shimming solution, through the
     * <a href="Base.html#method_build">Base.build</a> method.
     *
     * @class WidgetStack
     * @param {Object} User configuration object
     */
    function Stack(config) {}

    // Static Properties
    /**
     * Static property used to define the default attribute
     * configuration introduced by WidgetStack.
     *
     * @property ATTRS
     * @type Object
     * @static
     */
    Stack.ATTRS = {
        /**
         * @attribute shim
         * @type boolean
         * @default false, for all browsers other than IE6, for which a shim is enabled by default.
         *
         * @description Boolean flag to indicate whether or not a shim should be added to the Widgets
         * boundingBox, to protect it from select box bleedthrough.
         */
        shim: {
            value: (UA.ie == 6)
        },

        /**
         * @attribute zIndex
         * @type number
         * @default 0
         * @description The z-index to apply to the Widgets boundingBox. Non-numerical values for
         * zIndex will be converted to 0
         */
        zIndex: {
            value : 0,
            setter: '_setZIndex'
        }
    };

    /**
     * The HTML parsing rules for the WidgetStack class.
     *
     * @property HTML_PARSER
     * @static
     * @type Object
     */
    Stack.HTML_PARSER = {
        zIndex: function (srcNode) {
            return this._parseZIndex(srcNode);
        }
    };

    /**
     * Default class used to mark the shim element
     *
     * @property SHIM_CLASS_NAME
     * @type String
     * @static
     * @default "yui3-widget-shim"
     */
    Stack.SHIM_CLASS_NAME = Widget.getClassName(SHIM);

    /**
     * Default class used to mark the boundingBox of a stacked widget.
     *
     * @property STACKED_CLASS_NAME
     * @type String
     * @static
     * @default "yui3-widget-stacked"
     */
    Stack.STACKED_CLASS_NAME = Widget.getClassName(STACKED);

    /**
     * Default markup template used to generate the shim element.
     *
     * @property SHIM_TEMPLATE
     * @type String
     * @static
     */
    Stack.SHIM_TEMPLATE = '<iframe class="' + Stack.SHIM_CLASS_NAME + '" frameborder="0" title="Widget Stacking Shim" src="javascript:false" tabindex="-1" role="presentation"></iframe>';

    Stack.prototype = {

        initializer : function() {
            this._stackNode = this.get(BOUNDING_BOX);
            this._stackHandles = {};

            // WIDGET METHOD OVERLAP
            Y.after(this._renderUIStack, this, RENDER_UI);
            Y.after(this._syncUIStack, this, SYNC_UI);
            Y.after(this._bindUIStack, this, BIND_UI);
        },

        /**
         * Synchronizes the UI to match the Widgets stack state. This method in
         * invoked after syncUI is invoked for the Widget class using YUI's aop infrastructure.
         *
         * @method _syncUIStack
         * @protected
         */
        _syncUIStack: function() {
            this._uiSetShim(this.get(SHIM));
            this._uiSetZIndex(this.get(ZINDEX));
        },

        /**
         * Binds event listeners responsible for updating the UI state in response to
         * Widget stack related state changes.
         * <p>
         * This method is invoked after bindUI is invoked for the Widget class
         * using YUI's aop infrastructure.
         * </p>
         * @method _bindUIStack
         * @protected
         */
        _bindUIStack: function() {
            this.after(ShimChange, this._afterShimChange);
            this.after(ZIndexChange, this._afterZIndexChange);
        },

        /**
         * Creates/Initializes the DOM to support stackability.
         * <p>
         * This method in invoked after renderUI is invoked for the Widget class
         * using YUI's aop infrastructure.
         * </p>
         * @method _renderUIStack
         * @protected
         */
        _renderUIStack: function() {
            this._stackNode.addClass(Stack.STACKED_CLASS_NAME);
        },

        /**
        Parses a `zIndex` attribute value from this widget's `srcNode`.

        @method _parseZIndex
        @param {Node} srcNode The node to parse a `zIndex` value from.
        @return {Mixed} The parsed `zIndex` value.
        @protected
        **/
        _parseZIndex: function (srcNode) {
            var zIndex;

            // Prefers how WebKit handles `z-index` which better matches the
            // spec:
            //
            // * http://www.w3.org/TR/CSS2/visuren.html#z-index
            // * https://bugs.webkit.org/show_bug.cgi?id=15562
            //
            // When a node isn't rendered in the document, and/or when a
            // node is not positioned, then it doesn't have a context to derive
            // a valid `z-index` value from.
            if (!srcNode.inDoc() || srcNode.getStyle('position') === 'static') {
                zIndex = 'auto';
            } else {
                // Uses `getComputedStyle()` because it has greater accuracy in
                // more browsers than `getStyle()` does for `z-index`.
                zIndex = srcNode.getComputedStyle('zIndex');
            }

            // This extension adds a stacking context to widgets, therefore a
            // `srcNode` witout a stacking context (i.e. "auto") will return
            // `null` from this DOM parser. This way the widget's default or
            // user provided value for `zIndex` will be used.
            return zIndex === 'auto' ? null : zIndex;
        },

        /**
         * Default setter for zIndex attribute changes. Normalizes zIndex values to
         * numbers, converting non-numerical values to 0.
         *
         * @method _setZIndex
         * @protected
         * @param {String | Number} zIndex
         * @return {Number} Normalized zIndex
         */
        _setZIndex: function(zIndex) {
            if (L.isString(zIndex)) {
                zIndex = parseInt(zIndex, 10);
            }
            if (!L.isNumber(zIndex)) {
                zIndex = 0;
            }
            return zIndex;
        },

        /**
         * Default attribute change listener for the shim attribute, responsible
         * for updating the UI, in response to attribute changes.
         *
         * @method _afterShimChange
         * @protected
         * @param {EventFacade} e The event facade for the attribute change
         */
        _afterShimChange : function(e) {
            this._uiSetShim(e.newVal);
        },

        /**
         * Default attribute change listener for the zIndex attribute, responsible
         * for updating the UI, in response to attribute changes.
         *
         * @method _afterZIndexChange
         * @protected
         * @param {EventFacade} e The event facade for the attribute change
         */
        _afterZIndexChange : function(e) {
            this._uiSetZIndex(e.newVal);
        },

        /**
         * Updates the UI to reflect the zIndex value passed in.
         *
         * @method _uiSetZIndex
         * @protected
         * @param {number} zIndex The zindex to be reflected in the UI
         */
        _uiSetZIndex: function (zIndex) {
            this._stackNode.setStyle(ZINDEX, zIndex);
        },

        /**
         * Updates the UI to enable/disable the shim. If the widget is not currently visible,
         * creation of the shim is deferred until it is made visible, for performance reasons.
         *
         * @method _uiSetShim
         * @protected
         * @param {boolean} enable If true, creates/renders the shim, if false, removes it.
         */
        _uiSetShim: function (enable) {
            if (enable) {
                // Lazy creation
                if (this.get(VISIBLE)) {
                    this._renderShim();
                } else {
                    this._renderShimDeferred();
                }

                // Eagerly attach resize handlers
                //
                // Required because of Event stack behavior, commit ref: cd8dddc
                // Should be revisted after Ticket #2531067 is resolved.
                if (UA.ie == 6) {
                    this._addShimResizeHandlers();
                }
            } else {
                this._destroyShim();
            }
        },

        /**
         * Sets up change handlers for the visible attribute, to defer shim creation/rendering
         * until the Widget is made visible.
         *
         * @method _renderShimDeferred
         * @private
         */
        _renderShimDeferred : function() {

            this._stackHandles[SHIM_DEFERRED] = this._stackHandles[SHIM_DEFERRED] || [];

            var handles = this._stackHandles[SHIM_DEFERRED],
                createBeforeVisible = function(e) {
                    if (e.newVal) {
                        this._renderShim();
                    }
                };

            handles.push(this.on(VisibleChange, createBeforeVisible));
            // Depending how how Ticket #2531067 is resolved, a reversal of
            // commit ref: cd8dddc could lead to a more elagent solution, with
            // the addition of this line here:
            //
            // handles.push(this.after(VisibleChange, this.sizeShim));
        },

        /**
         * Sets up event listeners to resize the shim when the size of the Widget changes.
         * <p>
         * NOTE: This method is only used for IE6 currently, since IE6 doesn't support a way to
         * resize the shim purely through CSS, when the Widget does not have an explicit width/height
         * set.
         * </p>
         * @method _addShimResizeHandlers
         * @private
         */
        _addShimResizeHandlers : function() {

            this._stackHandles[SHIM_RESIZE] = this._stackHandles[SHIM_RESIZE] || [];

            var sizeShim = this.sizeShim,
                handles = this._stackHandles[SHIM_RESIZE];

            handles.push(this.after(VisibleChange, sizeShim));
            handles.push(this.after(WidthChange, sizeShim));
            handles.push(this.after(HeightChange, sizeShim));
            handles.push(this.after(ContentUpdate, sizeShim));
        },

        /**
         * Detaches any handles stored for the provided key
         *
         * @method _detachStackHandles
         * @param String handleKey The key defining the group of handles which should be detached
         * @private
         */
        _detachStackHandles : function(handleKey) {
            var handles = this._stackHandles[handleKey],
                handle;

            if (handles && handles.length > 0) {
                while((handle = handles.pop())) {
                    handle.detach();
                }
            }
        },

        /**
         * Creates the shim element and adds it to the DOM
         *
         * @method _renderShim
         * @private
         */
        _renderShim : function() {
            var shimEl = this._shimNode,
                stackEl = this._stackNode;

            if (!shimEl) {
                shimEl = this._shimNode = this._getShimTemplate();
                stackEl.insertBefore(shimEl, stackEl.get(FIRST_CHILD));

                this._detachStackHandles(SHIM_DEFERRED);
                this.sizeShim();
            }
        },

        /**
         * Removes the shim from the DOM, and detaches any related event
         * listeners.
         *
         * @method _destroyShim
         * @private
         */
        _destroyShim : function() {
            if (this._shimNode) {
                this._shimNode.get(PARENT_NODE).removeChild(this._shimNode);
                this._shimNode = null;

                this._detachStackHandles(SHIM_DEFERRED);
                this._detachStackHandles(SHIM_RESIZE);
            }
        },

        /**
         * For IE6, synchronizes the size and position of iframe shim to that of
         * Widget bounding box which it is protecting. For all other browsers,
         * this method does not do anything.
         *
         * @method sizeShim
         */
        sizeShim: function () {
            var shim = this._shimNode,
                node = this._stackNode;

            if (shim && UA.ie === 6 && this.get(VISIBLE)) {
                shim.setStyle(WIDTH, node.get(OFFSET_WIDTH) + PX);
                shim.setStyle(HEIGHT, node.get(OFFSET_HEIGHT) + PX);
            }
        },

        /**
         * Creates a cloned shim node, using the SHIM_TEMPLATE html template, for use on a new instance.
         *
         * @method _getShimTemplate
         * @private
         * @return {Node} node A new shim Node instance.
         */
        _getShimTemplate : function() {
            return Node.create(Stack.SHIM_TEMPLATE, this._stackNode.get(OWNER_DOCUMENT));
        }
    };

    Y.WidgetStack = Stack;


}, 'patched-v3.18.1', {"requires": ["base-build", "widget"], "skinnable": true});

