Show:
                            /*jshint expr:true, onevar:false */
                            
                            /**
                            Provides the `Tree.Node` class, which represents a tree node contained in a
                            `Tree` data structure.
                            
                            @module tree
                            @submodule tree-node
                            **/
                            
                            /**
                            Represents a tree node in a `Tree` data structure.
                            
                            @class Tree.Node
                            @param {Tree} tree `Tree` instance with which this node should be associated.
                            @param {Object} [config] Configuration hash for this node.
                            
                                @param {Boolean} [config.canHaveChildren=false] Whether or not this node can
                                    contain child nodes. Will be automatically set to `true` if not
                                    specified and `config.children` contains one or more children.
                            
                                @param {Tree.Node[]} [config.children] Array of `Tree.Node` instances
                                    for child nodes of this node.
                            
                                @param {Object} [config.data] Implementation-specific data related to this
                                    node. You may add arbitrary properties to this hash for your own use.
                            
                                @param {String} [config.id] Unique id for this node. This id must be unique
                                    among all tree nodes on the entire page, and will also be used as this
                                    node's DOM id when it's rendered by a TreeView. A unique id will be
                                    automatically generated unless you specify a custom value.
                            
                                @param {Object} [config.state] State hash for this node. You may add
                                    arbitrary state properties to this hash for your own use. See the
                                    docs for `Tree.Node`'s `state` property for details on state values used
                                    internally by `Tree.Node`.
                            
                            @constructor
                            **/
                            
                            function TreeNode(tree, config) {
                                config || (config = {});
                            
                                this.id   = this._yuid = config.id || this.id || Y.guid('treeNode-');
                                this.tree = tree;
                            
                                this.children = config.children || [];
                                this.data     = config.data || {};
                                this.state    = config.state || {};
                            
                                if (config.canHaveChildren) {
                                    this.canHaveChildren = config.canHaveChildren;
                                } else if (this.children.length) {
                                    this.canHaveChildren = true;
                                }
                            
                                // Mix in arbitrary properties on the config object, but don't overwrite any
                                // existing properties of this node.
                                Y.mix(this, config);
                            
                                // If this node has children, loop through them and ensure their parent
                                // references are all set to this node.
                                for (var i = 0, len = this.children.length; i < len; i++) {
                                    this.children[i].parent = this;
                                }
                            }
                            
                            TreeNode.prototype = {
                                // -- Public Properties ----------------------------------------------------
                            
                                /**
                                Whether or not this node can contain child nodes.
                            
                                This value is falsy by default unless child nodes are added at instantiation
                                time, in which case it will be automatically set to `true`. You can also
                                manually set it to `true` to indicate that a node can have children even
                                though it might not currently have any children.
                            
                                Note that regardless of the value of this property, appending, prepending,
                                or inserting a node into this node will cause `canHaveChildren` to be set to
                                true automatically.
                            
                                @property {Boolean} canHaveChildren
                                **/
                            
                                /**
                                Child nodes contained within this node.
                            
                                @property {Tree.Node[]} children
                                @default []
                                @readOnly
                                **/
                            
                                /**
                                Arbitrary serializable data related to this node.
                            
                                Use this property to store any data that should accompany this node when it
                                is serialized to JSON.
                            
                                @property {Object} data
                                @default {}
                                **/
                            
                                /**
                                Unique id for this node.
                            
                                @property {String} id
                                @readOnly
                                **/
                            
                                /**
                                Parent node of this node, or `undefined` if this is an unattached node or
                                the root node.
                            
                                @property {Tree.Node} parent
                                @readOnly
                                **/
                            
                                /**
                                Current state of this node.
                            
                                Use this property to store state-specific info -- such as whether this node
                                is "open", "selected", or any other arbitrary state -- that should accompany
                                this node when it is serialized to JSON.
                            
                                @property {Object} state
                                **/
                            
                                /**
                                The Tree instance with which this node is associated.
                            
                                @property {Tree} tree
                                @readOnly
                                **/
                            
                                // -- Protected Properties -------------------------------------------------
                            
                                /**
                                Mapping of child node ids to indices.
                            
                                @property {Object} _indexMap
                                @protected
                                **/
                            
                                /**
                                Flag indicating whether the `_indexMap` is stale and needs to be rebuilt.
                            
                                @property {Boolean} _isIndexStale
                                @default true
                                @protected
                                **/
                                _isIndexStale: true,
                            
                                /**
                                Simple way to type-check that this is an instance of Tree.Node.
                            
                                @property {Boolean} _isYUITreeNode
                                @default true
                                @protected
                                **/
                                _isYUITreeNode: true,
                            
                                /**
                                Array of property names on this node that should be serialized to JSON when
                                `toJSON()` is called.
                            
                                Note that the `children` property is a special case that is managed
                                separately.
                            
                                @property {String[]} _serializable
                                @protected
                                **/
                                _serializable: ['canHaveChildren', 'data', 'id', 'state'],
                            
                                // -- Public Methods -------------------------------------------------------
                            
                                /**
                                Appends the given tree node or array of nodes to the end of this node's
                                children.
                            
                                @method append
                                @param {Object|Object[]|Tree.Node|Tree.Node[]} node Child node, node config
                                    object, array of child nodes, or array of node config objects to append
                                    to the given parent. Node config objects will automatically be converted
                                    into node instances.
                                @param {Object} [options] Options.
                                    @param {Boolean} [options.silent=false] If `true`, the `add` event will
                                        be suppressed.
                                @return {Tree.Node|Tree.Node[]} Node or array of nodes that were appended.
                                **/
                                append: function (node, options) {
                                    return this.tree.appendNode(this, node, options);
                                },
                            
                                /**
                                Returns this node's depth.
                            
                                The root node of a tree always has a depth of 0. A child of the root has a
                                depth of 1, a child of that child will have a depth of 2, and so on.
                            
                                @method depth
                                @return {Number} This node's depth.
                                @since 3.11.0
                                **/
                                depth: function () {
                                    if (this.isRoot()) {
                                        return 0;
                                    }
                            
                                    var depth  = 0,
                                        parent = this.parent;
                            
                                    while (parent) {
                                        depth += 1;
                                        parent = parent.parent;
                                    }
                            
                                    return depth;
                                },
                            
                                /**
                                Removes all children from this node. The removed children will still be
                                reusable unless the `destroy` option is truthy.
                            
                                @method empty
                                @param {Object} [options] Options.
                                    @param {Boolean} [options.destroy=false] If `true`, the children will
                                        also be destroyed, which makes them available for garbage collection
                                        and means they can't be reused.
                                    @param {Boolean} [options.silent=false] If `true`, `remove` events will
                                        be suppressed.
                                    @param {String} [options.src] Source of the change, to be passed along
                                        to the event facade of the resulting event. This can be used to
                                        distinguish between changes triggered by a user and changes
                                        triggered programmatically, for example.
                                @return {Tree.Node[]} Array of removed child nodes.
                                **/
                                empty: function (options) {
                                    return this.tree.emptyNode(this, options);
                                },
                            
                                /**
                                Performs a depth-first traversal of this node, passing it and each of its
                                descendants to the specified _callback_, and returning the first node for
                                which the callback returns a truthy value.
                            
                                Traversal will stop as soon as a truthy value is returned from the callback.
                            
                                See `Tree#traverseNode()` for more details on how depth-first traversal
                                works.
                            
                                @method find
                                @param {Object} [options] Options.
                                    @param {Number} [options.depth] Depth limit. If specified, descendants
                                        will only be traversed to this depth before backtracking and moving
                                        on.
                                @param {Function} callback Callback function to call with the traversed
                                    node and each of its descendants. If this function returns a truthy
                                    value, traversal will be stopped and the current node will be returned.
                            
                                    @param {Tree.Node} callback.node Node being traversed.
                            
                                @param {Object} [thisObj] `this` object to use when executing _callback_.
                                @return {Tree.Node|null} Returns the first node for which the _callback_
                                    returns a truthy value, or `null` if the callback never returns a truthy
                                    value.
                                **/
                                find: function (options, callback, thisObj) {
                                    return this.tree.findNode(this, options, callback, thisObj);
                                },
                            
                                /**
                                Returns `true` if this node has one or more child nodes.
                            
                                @method hasChildren
                                @return {Boolean} `true` if this node has one or more child nodes, `false`
                                    otherwise.
                                **/
                                hasChildren: function () {
                                    return !!this.children.length;
                                },
                            
                                /**
                                Returns the numerical index of this node within its parent node, or `-1` if
                                this node doesn't have a parent node.
                            
                                @method index
                                @return {Number} Index of this node within its parent node, or `-1` if this
                                    node doesn't have a parent node.
                                **/
                                index: function () {
                                    return this.parent ? this.parent.indexOf(this) : -1;
                                },
                            
                                /**
                                Returns the numerical index of the given child node, or `-1` if the node is
                                not a child of this node.
                            
                                @method indexOf
                                @param {Tree.Node} node Child node.
                                @return {Number} Index of the child, or `-1` if the node is not a child of
                                    this node.
                                **/
                                indexOf: function (node) {
                                    var index;
                            
                                    if (this._isIndexStale) {
                                        this._reindex();
                                    }
                            
                                    index = this._indexMap[node.id];
                            
                                    return typeof index === 'undefined' ? -1 : index;
                                },
                            
                                /**
                                Inserts a node or array of nodes at the specified index under this node, or
                                appends them to this node if no index is specified.
                            
                                If a node being inserted is from another tree, it and all its children will
                                be removed from that tree and moved to this one.
                            
                                @method insert
                                @param {Object|Object[]|Tree.Node|Tree.Node[]} node Child node, node config
                                    object, array of child nodes, or array of node config objects to insert
                                    under the given parent. Node config objects will automatically be
                                    converted into node instances.
                            
                                @param {Object} [options] Options.
                                    @param {Number} [options.index] Index at which to insert the child node.
                                        If not specified, the node will be appended as the last child of the
                                        parent.
                                    @param {Boolean} [options.silent=false] If `true`, the `add` event will
                                        be suppressed.
                                    @param {String} [options.src='insert'] Source of the change, to be
                                        passed along to the event facade of the resulting event. This can be
                                        used to distinguish between changes triggered by a user and changes
                                        triggered programmatically, for example.
                            
                                @return {Tree.Node[]} Node or array of nodes that were inserted.
                                **/
                                insert: function (node, options) {
                                    return this.tree.insertNode(this, node, options);
                                },
                            
                                /**
                                Returns `true` if this node has been inserted into a tree, `false` if it is
                                merely associated with a tree and has not yet been inserted.
                            
                                @method isInTree
                                @return {Boolean} `true` if this node has been inserted into a tree, `false`
                                    otherwise.
                                **/
                                isInTree: function () {
                                    if (this.tree && this.tree.rootNode === this) {
                                        return true;
                                    }
                            
                                    return !!(this.parent && this.parent.isInTree());
                                },
                            
                                /**
                                Returns `true` if this node is the root of the tree.
                            
                                @method isRoot
                                @return {Boolean} `true` if this node is the root of the tree, `false`
                                    otherwise.
                                **/
                                isRoot: function () {
                                    return !!(this.tree && this.tree.rootNode === this);
                                },
                            
                                /**
                                Returns this node's next sibling, or `undefined` if this node is the last
                                child.
                            
                                @method next
                                @return {Tree.Node} This node's next sibling, or `undefined` if this node is
                                    the last child.
                                **/
                                next: function () {
                                    if (this.parent) {
                                        return this.parent.children[this.index() + 1];
                                    }
                                },
                            
                                /**
                                Prepends a node or array of nodes at the beginning of this node's children.
                            
                                If a node being prepended is from another tree, it and all its children will
                                be removed from that tree and moved to this one.
                            
                                @method prepend
                                @param {Object|Object[]|Tree.Node|Tree.Node[]} node Child node, node config
                                    object, array of child nodes, or array of node config objects to prepend
                                    to this node. Node config objects will automatically be converted into
                                    node instances.
                                @param {Object} [options] Options.
                                    @param {Boolean} [options.silent=false] If `true`, the `add` event will
                                        be suppressed.
                                @return {Tree.Node|Tree.Node[]} Node or array of nodes that were prepended.
                                **/
                                prepend: function (node, options) {
                                    return this.tree.prependNode(this, node, options);
                                },
                            
                                /**
                                Returns this node's previous sibling, or `undefined` if this node is the
                                first child
                            
                                @method previous
                                @return {Tree.Node} This node's previous sibling, or `undefined` if this
                                    node is the first child.
                                **/
                                previous: function () {
                                    if (this.parent) {
                                        return this.parent.children[this.index() - 1];
                                    }
                                },
                            
                                /**
                                Removes this node from its parent node.
                            
                                @method remove
                                @param {Object} [options] Options.
                                    @param {Boolean} [options.destroy=false] If `true`, this node and all
                                        its children will also be destroyed, which makes them available for
                                        garbage collection and means they can't be reused.
                                    @param {Boolean} [options.silent=false] If `true`, the `remove` event
                                        will be suppressed.
                                    @param {String} [options.src] Source of the change, to be passed along
                                        to the event facade of the resulting event. This can be used to
                                        distinguish between changes triggered by a user and changes
                                        triggered programmatically, for example.
                                @chainable
                                **/
                                remove: function (options) {
                                    return this.tree.removeNode(this, options);
                                },
                            
                                /**
                                Returns the total number of nodes contained within this node, including all
                                descendants of this node's children.
                            
                                @method size
                                @return {Number} Total number of nodes contained within this node, including
                                    all descendants.
                                **/
                                size: function () {
                                    var children = this.children,
                                        len      = children.length,
                                        total    = len;
                            
                                    for (var i = 0; i < len; i++) {
                                        total += children[i].size();
                                    }
                            
                                    return total;
                                },
                            
                                /**
                                Serializes this node to an object suitable for use in JSON.
                            
                                @method toJSON
                                @return {Object} Serialized node object.
                                **/
                                toJSON: function () {
                                    var obj   = {},
                                        state = this.state,
                                        i, key, len;
                            
                                    // Do nothing if this node is marked as destroyed.
                                    if (state.destroyed) {
                                        return null;
                                    }
                            
                                    // Serialize properties explicitly marked as serializable.
                                    for (i = 0, len = this._serializable.length; i < len; i++) {
                                        key = this._serializable[i];
                            
                                        if (key in this) {
                                            obj[key] = this[key];
                                        }
                                    }
                            
                                    // Serialize child nodes.
                                    if (this.canHaveChildren) {
                                        obj.children = [];
                            
                                        for (i = 0, len = this.children.length; i < len; i++) {
                                            obj.children.push(this.children[i].toJSON());
                                        }
                                    }
                            
                                    return obj;
                                },
                            
                                /**
                                Performs a depth-first traversal of this node, passing it and each of its
                                descendants to the specified _callback_.
                            
                                If the callback function returns `Tree.STOP_TRAVERSAL`, traversal will be
                                stopped immediately. Otherwise, it will continue until the deepest
                                descendant of _node_ has been traversed, or until each branch has been
                                traversed to the optional maximum depth limit.
                            
                                Since traversal is depth-first, that means nodes are traversed like this:
                            
                                            1
                                          / | \
                                         2  8  9
                                        / \     \
                                       3   7    10
                                     / | \      / \
                                    4  5  6    11 12
                            
                                @method traverse
                                @param {Object} [options] Options.
                                    @param {Number} [options.depth] Depth limit. If specified, descendants
                                        will only be traversed to this depth before backtracking and moving
                                        on.
                                @param {Function} callback Callback function to call with the traversed
                                    node and each of its descendants.
                            
                                    @param {Tree.Node} callback.node Node being traversed.
                            
                                @param {Object} [thisObj] `this` object to use when executing _callback_.
                                @return {Mixed} Returns `Tree.STOP_TRAVERSAL` if traversal was stopped;
                                    otherwise returns `undefined`.
                                **/
                                traverse: function (options, callback, thisObj) {
                                    return this.tree.traverseNode(this, options, callback, thisObj);
                                },
                            
                                // -- Protected Methods ----------------------------------------------------
                                _reindex: function () {
                                    var children = this.children,
                                        indexMap = {},
                                        i, len;
                            
                                    for (i = 0, len = children.length; i < len; i++) {
                                        indexMap[children[i].id] = i;
                                    }
                            
                                    this._indexMap     = indexMap;
                                    this._isIndexStale = false;
                                }
                            };
                            
                            Y.namespace('Tree').Node = TreeNode;