Show:
                            /**
                             * Extension enabling a Widget to be a parent of another Widget.
                             *
                             * @module widget-parent
                             */
                            
                            var Lang = Y.Lang,
                                RENDERED = "rendered",
                                BOUNDING_BOX = "boundingBox";
                            
                            /**
                             * Widget extension providing functionality enabling a Widget to be a
                             * parent of another Widget.
                             *
                             * <p>In addition to the set of attributes supported by WidgetParent, the constructor
                             * configuration object can also contain a <code>children</code> which can be used
                             * to add child widgets to the parent during construction. The <code>children</code>
                             * property is an array of either child widget instances or child widget configuration
                             * objects, and is sugar for the <a href="#method_add">add</a> method. See the
                             * <a href="#method_add">add</a> for details on the structure of the child widget
                             * configuration object.
                             * @class WidgetParent
                             * @constructor
                             * @uses ArrayList
                             * @param {Object} config User configuration object.
                             */
                            function Parent(config) {
                            
                                /**
                                * Fires when a Widget is add as a child.  The event object will have a
                                * 'child' property that returns a reference to the child Widget, as well
                                * as an 'index' property that returns a reference to the index specified
                                * when the add() method was called.
                                * <p>
                                * Subscribers to the "on" moment of this event, will be notified
                                * before a child is added.
                                * </p>
                                * <p>
                                * Subscribers to the "after" moment of this event, will be notified
                                * after a child is added.
                                * </p>
                                *
                                * @event addChild
                                * @preventable _defAddChildFn
                                * @param {EventFacade} e The Event Facade
                                */
                                this.publish("addChild", {
                                    defaultTargetOnly: true,
                                    defaultFn: this._defAddChildFn
                                });
                            
                            
                                /**
                                * Fires when a child Widget is removed.  The event object will have a
                                * 'child' property that returns a reference to the child Widget, as well
                                * as an 'index' property that returns a reference child's ordinal position.
                                * <p>
                                * Subscribers to the "on" moment of this event, will be notified
                                * before a child is removed.
                                * </p>
                                * <p>
                                * Subscribers to the "after" moment of this event, will be notified
                                * after a child is removed.
                                * </p>
                                *
                                * @event removeChild
                                * @preventable _defRemoveChildFn
                                * @param {EventFacade} e The Event Facade
                                */
                                this.publish("removeChild", {
                                    defaultTargetOnly: true,
                                    defaultFn: this._defRemoveChildFn
                                });
                            
                                this._items = [];
                            
                                var children,
                                    handle;
                            
                                if (config && config.children) {
                            
                                    children = config.children;
                            
                                    handle = this.after("initializedChange", function (e) {
                                        this._add(children);
                                        handle.detach();
                                    });
                            
                                }
                            
                                //  Widget method overlap
                                Y.after(this._renderChildren, this, "renderUI");
                                Y.after(this._bindUIParent, this, "bindUI");
                            
                                this.after("selectionChange", this._afterSelectionChange);
                                this.after("selectedChange", this._afterParentSelectedChange);
                                this.after("activeDescendantChange", this._afterActiveDescendantChange);
                            
                                this._hDestroyChild = this.after("*:destroy", this._afterDestroyChild);
                                this.after("*:focusedChange", this._updateActiveDescendant);
                            
                            }
                            
                            Parent.ATTRS = {
                            
                                /**
                                 * @attribute defaultChildType
                                 * @type {String|Object}
                                 *
                                 * @description String representing the default type of the children
                                 * managed by this Widget.  Can also supply default type as a constructor
                                 * reference.
                                 */
                                defaultChildType: {
                                    setter: function (val) {
                            
                                        var returnVal = Y.Attribute.INVALID_VALUE,
                                            FnConstructor = Lang.isString(val) ? Y[val] : val;
                            
                                        if (Lang.isFunction(FnConstructor)) {
                                            returnVal = FnConstructor;
                                        }
                            
                                        return returnVal;
                                    }
                                },
                            
                                /**
                                 * @attribute activeDescendant
                                 * @type Widget
                                 * @readOnly
                                 *
                                 * @description Returns the Widget's currently focused descendant Widget.
                                 */
                                activeDescendant: {
                                    readOnly: true
                                },
                            
                                /**
                                 * @attribute multiple
                                 * @type Boolean
                                 * @default false
                                 * @writeOnce
                                 *
                                 * @description Boolean indicating if multiple children can be selected at
                                 * once.  Whether or not multiple selection is enabled is always delegated
                                 * to the value of the <code>multiple</code> attribute of the root widget
                                 * in the object hierarchy.
                                 */
                                multiple: {
                                    value: false,
                                    validator: Lang.isBoolean,
                                    writeOnce: true,
                                    getter: function (value) {
                                        var root = this.get("root");
                                        return (root && root != this) ? root.get("multiple") : value;
                                    }
                                },
                            
                            
                                /**
                                 * @attribute selection
                                 * @type {ArrayList|Widget}
                                 * @readOnly
                                 *
                                 * @description Returns the currently selected child Widget.  If the
                                 * <code>mulitple</code> attribte is set to <code>true</code> will
                                 * return an Y.ArrayList instance containing the currently selected
                                 * children.  If no children are selected, will return null.
                                 */
                                selection: {
                                    readOnly: true,
                                    setter: "_setSelection",
                                    getter: function (value) {
                                        var selection = Lang.isArray(value) ?
                                                (new Y.ArrayList(value)) : value;
                                        return selection;
                                    }
                                },
                            
                                selected: {
                                    setter: function (value) {
                            
                                        //  Enforces selection behavior on for parent Widgets.  Parent's
                                        //  selected attribute can be set to the following:
                                        //  0 - Not selected
                                        //  1 - Fully selected (all children are selected).  In order for
                                        //  all children to be selected, multiple selection must be
                                        //  enabled.  Therefore, you cannot set the "selected" attribute
                                        //  on a parent Widget to 1 unless multiple selection is enabled.
                                        //  2 - Partially selected, meaning one ore more (but not all)
                                        //  children are selected.
                            
                                        var returnVal = value;
                            
                                        if (value === 1 && !this.get("multiple")) {
                                            Y.log('The selected attribute can only be set to 1 if the "multiple" attribute is set to true.', "error", "widget");
                                            returnVal = Y.Attribute.INVALID_VALUE;
                                        }
                            
                                        return returnVal;
                                    }
                                }
                            
                            };
                            
                            Parent.prototype = {
                            
                                /**
                                 * The destructor implementation for Parent widgets. Destroys all children.
                                 * @method destructor
                                 */
                                destructor: function() {
                                    this._destroyChildren();
                                },
                            
                                /**
                                 * Destroy event listener for each child Widget, responsible for removing
                                 * the destroyed child Widget from the parent's internal array of children
                                 * (_items property).
                                 *
                                 * @method _afterDestroyChild
                                 * @protected
                                 * @param {EventFacade} event The event facade for the attribute change.
                                 */
                                _afterDestroyChild: function (event) {
                                    var child = event.target;
                            
                                    if (child.get("parent") == this) {
                                        child.remove();
                                    }
                                },
                            
                                /**
                                 * Attribute change listener for the <code>selection</code>
                                 * attribute, responsible for setting the value of the
                                 * parent's <code>selected</code> attribute.
                                 *
                                 * @method _afterSelectionChange
                                 * @protected
                                 * @param {EventFacade} event The event facade for the attribute change.
                                 */
                                _afterSelectionChange: function (event) {
                            
                                    if (event.target == this && event.src != this) {
                            
                                        var selection = event.newVal,
                                            selectedVal = 0;    //  Not selected
                            
                            
                                        if (selection) {
                            
                                            selectedVal = 2;    //  Assume partially selected, confirm otherwise
                            
                            
                                            if (Y.instanceOf(selection, Y.ArrayList) &&
                                                (selection.size() === this.size())) {
                            
                                                selectedVal = 1;    //  Fully selected
                            
                                            }
                            
                                        }
                            
                                        this.set("selected", selectedVal, { src: this });
                            
                                    }
                                },
                            
                            
                                /**
                                 * Attribute change listener for the <code>activeDescendant</code>
                                 * attribute, responsible for setting the value of the
                                 * parent's <code>activeDescendant</code> attribute.
                                 *
                                 * @method _afterActiveDescendantChange
                                 * @protected
                                 * @param {EventFacade} event The event facade for the attribute change.
                                 */
                                _afterActiveDescendantChange: function (event) {
                                    var parent = this.get("parent");
                            
                                    if (parent) {
                                        parent._set("activeDescendant", event.newVal);
                                    }
                                },
                            
                                /**
                                 * Attribute change listener for the <code>selected</code>
                                 * attribute, responsible for syncing the selected state of all children to
                                 * match that of their parent Widget.
                                 *
                                 *
                                 * @method _afterParentSelectedChange
                                 * @protected
                                 * @param {EventFacade} event The event facade for the attribute change.
                                 */
                                _afterParentSelectedChange: function (event) {
                            
                                    var value = event.newVal;
                            
                                    if (this == event.target && event.src != this &&
                                        (value === 0 || value === 1)) {
                            
                                        this.each(function (child) {
                            
                                            //  Specify the source of this change as the parent so that
                                            //  value of the parent's "selection" attribute isn't
                                            //  recalculated
                            
                                            child.set("selected", value, { src: this });
                            
                                        }, this);
                            
                                    }
                            
                                },
                            
                            
                                /**
                                 * Default setter for <code>selection</code> attribute changes.
                                 *
                                 * @method _setSelection
                                 * @protected
                                 * @param child {Widget|Array} Widget or Array of Widget instances.
                                 * @return {Widget|Array} Widget or Array of Widget instances.
                                 */
                                _setSelection: function (child) {
                            
                                    var selection = null,
                                        selected;
                            
                                    if (this.get("multiple") && !this.isEmpty()) {
                            
                                        selected = [];
                            
                                        this.each(function (v) {
                            
                                           if (v.get("selected") > 0) {
                                               selected.push(v);
                                           }
                            
                                        });
                            
                                        if (selected.length > 0) {
                                            selection = selected;
                                        }
                            
                                    }
                                    else {
                            
                                        if (child.get("selected") > 0) {
                                            selection = child;
                                        }
                            
                                    }
                            
                                    return selection;
                            
                                },
                            
                            
                                /**
                                 * Attribute change listener for the <code>selected</code>
                                 * attribute of child Widgets, responsible for setting the value of the
                                 * parent's <code>selection</code> attribute.
                                 *
                                 * @method _updateSelection
                                 * @protected
                                 * @param {EventFacade} event The event facade for the attribute change.
                                 */
                                _updateSelection: function (event) {
                            
                                    var child = event.target,
                                        selection;
                            
                                    if (child.get("parent") == this) {
                            
                                        if (event.src != "_updateSelection") {
                            
                                            selection = this.get("selection");
                            
                                            if (!this.get("multiple") && selection && event.newVal > 0) {
                            
                                                //  Deselect the previously selected child.
                                                //  Set src equal to the current context to prevent
                                                //  unnecessary re-calculation of the selection.
                            
                                                selection.set("selected", 0, { src: "_updateSelection" });
                            
                                            }
                            
                                            this._set("selection", child);
                            
                                        }
                            
                                        if (event.src == this) {
                                            this._set("selection", child, { src: this });
                                        }
                            
                                    }
                            
                                },
                            
                                /**
                                 * Attribute change listener for the <code>focused</code>
                                 * attribute of child Widgets, responsible for setting the value of the
                                 * parent's <code>activeDescendant</code> attribute.
                                 *
                                 * @method _updateActiveDescendant
                                 * @protected
                                 * @param {EventFacade} event The event facade for the attribute change.
                                 */
                                _updateActiveDescendant: function (event) {
                                    var activeDescendant = (event.newVal === true) ? event.target : null;
                                    this._set("activeDescendant", activeDescendant);
                                },
                            
                                /**
                                 * Creates an instance of a child Widget using the specified configuration.
                                 * By default Widget instances will be created of the type specified
                                 * by the <code>defaultChildType</code> attribute.  Types can be explicitly
                                 * defined via the <code>childType</code> property of the configuration object
                                 * literal. The use of the <code>type</code> property has been deprecated, but
                                 * will still be used as a fallback, if <code>childType</code> is not defined,
                                 * for backwards compatibility.
                                 *
                                 * @method _createChild
                                 * @protected
                                 * @param config {Object} Object literal representing the configuration
                                 * used to create an instance of a Widget.
                                 */
                                _createChild: function (config) {
                            
                                    var defaultType = this.get("defaultChildType"),
                                        altType = config.childType || config.type,
                                        child,
                                        Fn,
                                        FnConstructor;
                            
                                    if (altType) {
                                        Fn = Lang.isString(altType) ? Y[altType] : altType;
                                    }
                            
                                    if (Lang.isFunction(Fn)) {
                                        FnConstructor = Fn;
                                    } else if (defaultType) {
                                        // defaultType is normalized to a function in it's setter
                                        FnConstructor = defaultType;
                                    }
                            
                                    if (FnConstructor) {
                                        child = new FnConstructor(config);
                                    } else {
                                        Y.error("Could not create a child instance because its constructor is either undefined or invalid.");
                                    }
                            
                                    return child;
                            
                                },
                            
                                /**
                                 * Default addChild handler
                                 *
                                 * @method _defAddChildFn
                                 * @protected
                                 * @param event {EventFacade} The Event object
                                 * @param child {Widget} The Widget instance, or configuration
                                 * object for the Widget to be added as a child.
                                 * @param index {Number} Number representing the position at
                                 * which the child will be inserted.
                                 */
                                _defAddChildFn: function (event) {
                            
                                    var child = event.child,
                                        index = event.index,
                                        children = this._items;
                            
                                    if (child.get("parent")) {
                                        child.remove();
                                    }
                            
                                    if (Lang.isNumber(index)) {
                                        children.splice(index, 0, child);
                                    }
                                    else {
                                        children.push(child);
                                    }
                            
                                    child._set("parent", this);
                                    child.addTarget(this);
                            
                                    // Update index in case it got normalized after addition
                                    // (e.g. user passed in 10, and there are only 3 items, the actual index would be 3. We don't want to pass 10 around in the event facade).
                                    event.index = child.get("index");
                            
                                    //  TO DO: Remove in favor of using event bubbling
                                    child.after("selectedChange", Y.bind(this._updateSelection, this));
                                },
                            
                            
                                /**
                                 * Default removeChild handler
                                 *
                                 * @method _defRemoveChildFn
                                 * @protected
                                 * @param event {EventFacade} The Event object
                                 * @param child {Widget} The Widget instance to be removed.
                                 * @param index {Number} Number representing the index of the Widget to
                                 * be removed.
                                 */
                                _defRemoveChildFn: function (event) {
                            
                                    var child = event.child,
                                        index = event.index,
                                        children = this._items;
                            
                                    if (child.get("focused")) {
                                        child.blur(); // focused is readOnly, so use the public i/f to unset it
                                    }
                            
                                    if (child.get("selected")) {
                                        child.set("selected", 0);
                                    }
                            
                                    children.splice(index, 1);
                            
                                    child.removeTarget(this);
                                    child._oldParent = child.get("parent");
                                    child._set("parent", null);
                                },
                            
                                /**
                                * @method _add
                                * @protected
                                * @param child {Widget|Object|Array} The Widget instance, or configuration
                                * object for the Widget, or Array of Widget instances to be added as a child.
                                * @param index {Number} Number representing the position at which the child
                                * should be inserted.
                                * @description Adds a Widget as a child.  If the specified Widget already
                                * has a parent it will be removed from its current parent before
                                * being added as a child.
                                * @return {Widget|Array} Successfully added Widget or Array containing the
                                * successfully added Widget instance(s). If no children where added, will
                                * will return undefined.
                                */
                                _add: function (child, index) {
                            
                                    var children,
                                        oChild,
                                        returnVal;
                            
                            
                                    if (Lang.isArray(child)) {
                            
                                        children = [];
                            
                                        Y.each(child, function (v, k) {
                            
                                            oChild = this._add(v, (index + k));
                            
                                            if (oChild) {
                                                children.push(oChild);
                                            }
                            
                                        }, this);
                            
                            
                                        if (children.length > 0) {
                                            returnVal = children;
                                        }
                            
                                    }
                                    else {
                            
                                        if (Y.instanceOf(child, Y.Widget)) {
                                            oChild = child;
                                        }
                                        else {
                                            oChild = this._createChild(child);
                                        }
                            
                                        if (oChild && this.fire("addChild", { child: oChild, index: index })) {
                                            returnVal = oChild;
                                        }
                            
                                    }
                            
                                    return returnVal;
                            
                                },
                            
                            
                                /**
                                * @method add
                                * @param child {Widget|Object|Array} The Widget instance, or configuration
                                * object for the Widget, or Array of Widget instances to be added as a child.
                                * The configuration object for the child can include a <code>childType</code>
                                * property, which is either a constructor function or a string which names
                                * a constructor function on the Y instance (e.g. "Tab" would refer to Y.Tab).
                                * <code>childType</code> used to be named <code>type</code>, support for
                                * which has been deprecated, but is still maintained for backward compatibility.
                                * <code>childType</code> takes precedence over <code>type</code> if both are defined.
                                * @param index {Number} Number representing the position at which the child
                                * should be inserted.
                                * @description Adds a Widget as a child.  If the specified Widget already
                                * has a parent it will be removed from its current parent before
                                * being added as a child.
                                * @return {ArrayList} Y.ArrayList containing the successfully added
                                * Widget instance(s).  If no children where added, will return an empty
                                * Y.ArrayList instance.
                                */
                                add: function () {
                            
                                    var added = this._add.apply(this, arguments),
                                        children = added ? (Lang.isArray(added) ? added : [added]) : [];
                            
                                    return (new Y.ArrayList(children));
                            
                                },
                            
                            
                                /**
                                * @method remove
                                * @param index {Number} (Optional.)  Number representing the index of the
                                * child to be removed.
                                * @description Removes the Widget from its parent.  Optionally, can remove
                                * a child by specifying its index.
                                * @return {Widget} Widget instance that was successfully removed, otherwise
                                * undefined.
                                */
                                remove: function (index) {
                            
                                    var child = this._items[index],
                                        returnVal;
                            
                                    if (child && this.fire("removeChild", { child: child, index: index })) {
                                        returnVal = child;
                                    }
                            
                                    return returnVal;
                            
                                },
                            
                            
                                /**
                                * @method removeAll
                                * @description Removes all of the children from the Widget.
                                * @return {ArrayList} Y.ArrayList instance containing Widgets that were
                                * successfully removed.  If no children where removed, will return an empty
                                * Y.ArrayList instance.
                                */
                                removeAll: function () {
                            
                                    var removed = [],
                                        child;
                            
                                    Y.each(this._items.concat(), function () {
                            
                                        child = this.remove(0);
                            
                                        if (child) {
                                            removed.push(child);
                                        }
                            
                                    }, this);
                            
                                    return (new Y.ArrayList(removed));
                            
                                },
                            
                                /**
                                 * Selects the child at the given index (zero-based).
                                 *
                                 * @method selectChild
                                 * @param {Number} i the index of the child to be selected
                                 */
                                selectChild: function(i) {
                                    this.item(i).set('selected', 1);
                                },
                            
                                /**
                                 * Selects all children.
                                 *
                                 * @method selectAll
                                 */
                                selectAll: function () {
                                    this.set("selected", 1);
                                },
                            
                                /**
                                 * Deselects all children.
                                 *
                                 * @method deselectAll
                                 */
                                deselectAll: function () {
                                    this.set("selected", 0);
                                },
                            
                                /**
                                 * Updates the UI in response to a child being added.
                                 *
                                 * @method _uiAddChild
                                 * @protected
                                 * @param child {Widget} The child Widget instance to render.
                                 * @param parentNode {Object} The Node under which the
                                 * child Widget is to be rendered.
                                 */
                                _uiAddChild: function (child, parentNode) {
                            
                                    child.render(parentNode);
                            
                                    // TODO: Ideally this should be in Child's render UI.
                            
                                    var childBB = child.get("boundingBox"),
                                        siblingBB,
                                        nextSibling = child.next(false),
                                        prevSibling;
                            
                                    // Insert or Append to last child.
                            
                                    // Avoiding index, and using the current sibling
                                    // state (which should be accurate), means we don't have
                                    // to worry about decorator elements which may be added
                                    // to the _childContainer node.
                            
                                    if (nextSibling && nextSibling.get(RENDERED)) {
                            
                                        siblingBB = nextSibling.get(BOUNDING_BOX);
                                        siblingBB.insert(childBB, "before");
                            
                                    } else {
                            
                                        prevSibling = child.previous(false);
                            
                                        if (prevSibling && prevSibling.get(RENDERED)) {
                            
                                            siblingBB = prevSibling.get(BOUNDING_BOX);
                                            siblingBB.insert(childBB, "after");
                            
                                        } else if (!parentNode.contains(childBB)) {
                            
                                            // Based on pull request from andreas-karlsson
                                            // https://github.com/yui/yui3/pull/25#issuecomment-2103536
                            
                                            // Account for case where a child was rendered independently of the
                                            // parent-child framework, to a node outside of the parentNode,
                                            // and there are no siblings.
                            
                                            parentNode.appendChild(childBB);
                                        }
                                    }
                            
                                },
                            
                                /**
                                 * Updates the UI in response to a child being removed.
                                 *
                                 * @method _uiRemoveChild
                                 * @protected
                                 * @param child {Widget} The child Widget instance to render.
                                 */
                                _uiRemoveChild: function (child) {
                                    child.get("boundingBox").remove();
                                },
                            
                                _afterAddChild: function (event) {
                                    var child = event.child;
                            
                                    if (child.get("parent") == this) {
                                        this._uiAddChild(child, this._childrenContainer);
                                    }
                                },
                            
                                _afterRemoveChild: function (event) {
                                    var child = event.child;
                            
                                    if (child._oldParent == this) {
                                        this._uiRemoveChild(child);
                                    }
                                },
                            
                                /**
                                 * Sets up DOM and CustomEvent listeners for the parent widget.
                                 * <p>
                                 * This method in invoked after bindUI is invoked for the Widget class
                                 * using YUI's aop infrastructure.
                                 * </p>
                                 *
                                 * @method _bindUIParent
                                 * @protected
                                 */
                                _bindUIParent: function () {
                                    this.after("addChild", this._afterAddChild);
                                    this.after("removeChild", this._afterRemoveChild);
                                },
                            
                                /**
                                 * Renders all child Widgets for the parent.
                                 * <p>
                                 * This method in invoked after renderUI is invoked for the Widget class
                                 * using YUI's aop infrastructure.
                                 * </p>
                                 * @method _renderChildren
                                 * @protected
                                 */
                                _renderChildren: function () {
                            
                                    /**
                                     * <p>By default WidgetParent will render it's children to the parent's content box.</p>
                                     *
                                     * <p>If the children need to be rendered somewhere else, the _childrenContainer property
                                     * can be set to the Node which the children should be rendered to. This property should be
                                     * set before the _renderChildren method is invoked, ideally in your renderUI method,
                                     * as soon as you create the element to be rendered to.</p>
                                     *
                                     * @protected
                                     * @property _childrenContainer
                                     * @value The content box
                                     * @type Node
                                     */
                                    var renderTo = this._childrenContainer || this.get("contentBox");
                            
                                    this._childrenContainer = renderTo;
                            
                                    this.each(function (child) {
                                        child.render(renderTo);
                                    });
                                },
                            
                                /**
                                 * Destroys all child Widgets for the parent.
                                 * <p>
                                 * This method is invoked before the destructor is invoked for the Widget
                                 * class using YUI's aop infrastructure.
                                 * </p>
                                 * @method _destroyChildren
                                 * @protected
                                 */
                                _destroyChildren: function () {
                            
                                    //  Detach the handler responsible for removing children in
                                    //  response to destroying them since:
                                    //  1)  It is unnecessary/inefficient at this point since we are doing
                                    //      a batch destroy of all children.
                                    //  2)  Removing each child will affect our ability to iterate the
                                    //      children since the size of _items will be changing as we
                                    //      iterate.
                                    this._hDestroyChild.detach();
                            
                                    //  Need to clone the _items array since
                                    this.each(function (child) {
                                        child.destroy();
                                    });
                                }
                            
                            };
                            
                            Y.augment(Parent, Y.ArrayList);
                            
                            Y.WidgetParent = Parent;