--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cm/media/js/lib/yui/yui_3.10.3/build/tree/tree-debug.js Tue Jul 16 14:29:46 2013 +0200
@@ -0,0 +1,888 @@
+/*
+YUI 3.10.3 (build 2fb5187)
+Copyright 2013 Yahoo! Inc. All rights reserved.
+Licensed under the BSD License.
+http://yuilibrary.com/license/
+*/
+
+YUI.add('tree', function (Y, NAME) {
+
+/*jshint expr:true, onevar:false */
+
+/**
+Provides a generic tree data structure and related functionality.
+
+A tree has a root node, which may contain any number of child nodes, which may
+themselves contain child nodes, ad infinitum.
+
+Child nodes are lightweight function instances which delegate to the tree for
+all significant functionality, so trees remain performant and memory-efficient
+even with thousands and thousands of nodes.
+
+@module tree
+@main tree
+**/
+
+/**
+The `Tree` class represents a generic tree data structure. A tree has a root
+node, which may contain any number of child nodes, which may themselves contain
+child nodes, ad infinitum.
+
+This class doesn't expose any UI, but is intended to be used as a data structure
+or base class for other components. For example, the SmugMug TreeView gallery
+module extends Tree and provides a TreeView UI.
+
+@class Tree
+@param {Object} [config] Config options.
+ @param {Object[]|Tree.Node[]} [config.nodes] Array of tree node config
+ objects or `Tree.Node` instances to add to this tree at initialization
+ time.
+ @param {Object|Tree.Node} [config.rootNode] Node to use as the root node of
+ this tree.
+@constructor
+@extends Base
+**/
+
+var Lang = Y.Lang,
+
+ /**
+ Fired when a node is added to this Tree. The `src` property will indicate
+ how the node was added ("append", "insert", "prepend", etc.).
+
+ @event add
+ @param {Number} index Index at which the node will be added.
+ @param {Tree.Node} node Node being added.
+ @param {Tree.Node} parent Parent node to which the node will be added.
+ @param {String} src Source of the event ("append", "insert", "prepend",
+ etc.).
+ @preventable _defAddFn
+ **/
+ EVT_ADD = 'add',
+
+ /**
+ Fired when this Tree is cleared.
+
+ @event clear
+ @param {Tree.Node} rootNode New root node of this tree (the old root node is
+ always destroyed when a tree is cleared).
+ @param {String} src Source of the event.
+ @preventable _defClearFn
+ **/
+ EVT_CLEAR = 'clear',
+
+ /**
+ Fired when a node is removed from this Tree.
+
+ @event remove
+ @param {Boolean} destroy Whether or not the node will be destroyed after
+ being removed from this tree.
+ @param {Tree.Node} node Node being removed.
+ @param {Tree.Node} parent Parent node from which the node will be removed.
+ @param {String} src Source of the event.
+ @preventable _defRemoveFn
+ **/
+ EVT_REMOVE = 'remove';
+
+var Tree = Y.Base.create('tree', Y.Base, [], {
+ // -- Public Properties ----------------------------------------------------
+
+ /**
+ Reference to the `children` array of this Tree's `rootNode`.
+
+ This is a convenience property to allow you to type `tree.children` instead
+ of `tree.rootNode.children`.
+
+ @property {Tree.Node[]} children
+ @readOnly
+ **/
+
+ /**
+ The `Tree.Node` class or subclass that should be used for nodes created by
+ this tree.
+
+ You may specify an actual class reference or a string that resolves to a
+ class reference at runtime.
+
+ @property {String|Tree.Node} nodeClass
+ @default Y.Tree.Node
+ **/
+ nodeClass: Y.Tree.Node,
+
+ /**
+ Optional array containing one or more extension classes that should be mixed
+ into the `nodeClass` when this Tree is instantiated. The resulting composed
+ node class will be unique to this Tree instance and will not affect any
+ other instances, nor will it modify the defined `nodeClass` itself.
+
+ This provides a late-binding extension mechanism for nodes that doesn't
+ require them to extend `Y.Base`, which would incur a significant performance
+ hit.
+
+ @property {Array} nodeExtensions
+ @default []
+ **/
+ nodeExtensions: [],
+
+ /**
+ Root node of this Tree.
+
+ @property {Tree.Node} rootNode
+ @readOnly
+ **/
+
+ // -- Protected Properties -------------------------------------------------
+
+ /**
+ Simple way to type-check that this is a Tree instance.
+
+ @property {Boolean} _isYUITree
+ @default true
+ @protected
+ **/
+ _isYUITree: true,
+
+ /**
+ Composed node class based on `nodeClass` that mixes in any extensions
+ specified in `nodeExtensions`. If there are no extensions, this will just be
+ a reference to `nodeClass`.
+
+ @property {Tree.Node} _nodeClass
+ @protected
+ **/
+
+ /**
+ Mapping of node ids to node instances for nodes in this tree.
+
+ @property {Object} _nodeMap
+ @protected
+ **/
+
+ /**
+ Default config object for the root node.
+
+ @property {Object} _rootNodeConfig
+ @protected
+ **/
+ _rootNodeConfig: {canHaveChildren: true},
+
+ // -- Lifecycle ------------------------------------------------------------
+ initializer: function (config) {
+ config || (config = {});
+
+ if (config.nodeClass) {
+ this.nodeClass = config.nodeClass;
+ }
+
+ if (config.nodeExtensions) {
+ this.nodeExtensions = this.nodeExtensions.concat(config.nodeExtensions);
+ }
+
+ /**
+ Hash of published custom events.
+
+ @property {Object} _published
+ @default {}
+ @protected
+ **/
+ this._published || (this._published = {});
+ this._nodeMap = {};
+
+ // Allow all extensions to initialize, then finish up.
+ this.onceAfter('initializedChange', function () {
+ this._composeNodeClass();
+
+ this.clear(config.rootNode, {silent: true});
+
+ if (config.nodes) {
+ this.insertNode(this.rootNode, config.nodes, {silent: true});
+ }
+ });
+ },
+
+ destructor: function () {
+ this.destroyNode(this.rootNode, {silent: true});
+
+ this.children = null;
+ this.rootNode = null;
+ this._nodeClass = null;
+ this._nodeMap = null;
+ this._published = null;
+ },
+
+ // -- Public Methods -------------------------------------------------------
+
+ /**
+ Appends a node or array of nodes as the last child of the specified parent
+ node.
+
+ If a node being appended is from another tree, it and all its children will
+ be removed from that tree and moved to this one.
+
+ @method appendNode
+ @param {Tree.Node} parent Parent node.
+ @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.
+ **/
+ appendNode: function (parent, node, options) {
+ return this.insertNode(parent, node, Y.merge(options, {
+ index: parent.children.length,
+ src : 'append'
+ }));
+ },
+
+ /**
+ Clears this tree by destroying the root node and all its children. If a
+ `rootNode` argument is provided, that node will become the root node of this
+ tree; otherwise, a new root node will be created.
+
+ @method clear
+ @param {Object|Tree.Node} [rootNode] If specified, this node will be used as
+ the new root node.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.silent=false] If `true`, the `clear` 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
+ **/
+ clear: function (rootNode, options) {
+ return this._fireTreeEvent(EVT_CLEAR, {
+ rootNode: this.createNode(rootNode || this._rootNodeConfig),
+ src : options && options.src
+ }, {
+ defaultFn: this._defClearFn,
+ silent : options && options.silent
+ });
+ },
+
+ /**
+ Creates and returns a new `Tree.Node` instance associated with (but not
+ yet appended to) this tree.
+
+ @method createNode
+ @param {Object|Tree.Node} [config] Node configuration. If a `Tree.Node`
+ instance is specified instead of a config object, that node will be
+ adopted into this tree (if it doesn't already belong to this tree) and
+ removed from any other tree to which it belongs.
+ @return {Tree.Node} New node.
+ **/
+ createNode: function (config) {
+ /*jshint boss:true */
+ config || (config = {});
+
+ // If `config` is already a node, just ensure it's in the node map and
+ // return it.
+ if (config._isYUITreeNode) {
+ this._adoptNode(config);
+ return config;
+ }
+
+ // First, create nodes for any children of this node.
+ if (config.children) {
+ var children = [];
+
+ for (var i = 0, len = config.children.length; i < len; i++) {
+ children.push(this.createNode(config.children[i]));
+ }
+
+ config = Y.merge(config, {children: children});
+ }
+
+ var node = new this._nodeClass(this, config);
+
+ return this._nodeMap[node.id] = node;
+ },
+
+ /**
+ Removes and destroys a node and all its child nodes. Once destroyed, a node
+ is eligible for garbage collection and cannot be reused or re-added to the
+ tree.
+
+ @method destroyNode
+ @param {Tree.Node} node Node to destroy.
+ @param {Object} [options] Options.
+ @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 events. This can be used to
+ distinguish between changes triggered by a user and changes
+ triggered programmatically, for example.
+ @chainable
+ **/
+ destroyNode: function (node, options) {
+ var child, i, len;
+
+ options || (options = {});
+
+ for (i = 0, len = node.children.length; i < len; i++) {
+ child = node.children[i];
+
+ // Manually remove the child from its parent; this makes destroying
+ // all children of the parent much faster since there's no splicing
+ // involved.
+ child.parent = null;
+
+ // Destroy the child.
+ this.destroyNode(child, options);
+ }
+
+ if (node.parent) {
+ this.removeNode(node, options);
+ }
+
+ node.children = null;
+ node.data = null;
+ node.state = {destroyed: true};
+ node.tree = null;
+ node._htmlNode = null;
+ node._indexMap = null;
+
+ delete this._nodeMap[node.id];
+
+ return this;
+ },
+
+ /**
+ Removes all children from the specified node. The removed children will
+ still be reusable unless the `destroy` option is truthy.
+
+ @method emptyNode
+ @param {Tree.Node} node Node to 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 events. 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.
+ **/
+ emptyNode: function (node, options) {
+ var removed = [];
+
+ while (node.children.length) {
+ removed.push(this.removeNode(node.children[0], options));
+ }
+
+ return removed;
+ },
+
+ /**
+ Performs a depth-first traversal of _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 `traverseNode()` for more details on how depth-first traversal works.
+
+ @method findNode
+ @param {Tree.Node} node Node to 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. 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.
+ **/
+ findNode: function (node, options, callback, thisObj) {
+ var match = null;
+
+ // Allow callback as second argument.
+ if (typeof options === 'function') {
+ thisObj = callback;
+ callback = options;
+ options = {};
+ }
+
+ this.traverseNode(node, options, function (descendant) {
+ if (callback.call(thisObj, descendant)) {
+ match = descendant;
+ return Tree.STOP_TRAVERSAL;
+ }
+ });
+
+ return match;
+ },
+
+ /**
+ Returns the tree node with the specified id, or `undefined` if the node
+ doesn't exist in this tree.
+
+ @method getNodeById
+ @param {String} id Node id.
+ @return {Tree.Node} Node, or `undefined` if not found.
+ **/
+ getNodeById: function (id) {
+ return this._nodeMap[id];
+ },
+
+ /**
+ Inserts a node or array of nodes at the specified index under the given
+ parent node, or appends them to the parent 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 insertNode
+ @param {Tree.Node} parent Parent node.
+ @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.
+ **/
+ insertNode: function (parent, node, options) {
+ options || (options = {});
+ parent || (parent = this.rootNode);
+
+ // If `node` is an array, recurse to insert each node it contains.
+ //
+ // Note: If you're getting an exception here because `node` is null when
+ // you've passed in a reference to some other node's `children` array,
+ // that's happening because nodes must be removed from their current
+ // parent before being added to the new one, and the `children` array is
+ // being modified while the nodes are inserted.
+ //
+ // Solution: pass a copy of the other node's `children` array instead of
+ // the original. Doing the copy operation here would have a negative
+ // impact on performance, so you're on your own since this is such a
+ // rare edge case.
+ if ('length' in node && Lang.isArray(node)) {
+ var inserted = [];
+
+ for (var i = 0, len = node.length; i < len; i++) {
+ inserted.push(this.insertNode(parent, node[i], options));
+
+ if ('index' in options) {
+ options.index += 1;
+ }
+ }
+
+ return inserted;
+ }
+
+ node = this.createNode(node);
+
+ var index = options.index;
+
+ if (typeof index === 'undefined') {
+ index = this._getDefaultNodeIndex(parent, node, options);
+ }
+
+ this._fireTreeEvent(EVT_ADD, {
+ index : index,
+ node : node,
+ parent: parent,
+ src : options.src || 'insert'
+ }, {
+ defaultFn: this._defAddFn,
+ silent : options.silent
+ });
+
+ return node;
+ },
+
+ /**
+ Prepends a node or array of nodes at the beginning of the specified parent
+ node.
+
+ 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 prependNode
+ @param {Tree.Node} parent Parent node.
+ @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 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
+ prepended.
+ **/
+ prependNode: function (parent, node, options) {
+ return this.insertNode(parent, node, Y.merge(options, {
+ index: 0,
+ src : 'prepend'
+ }));
+ },
+
+ /**
+ Removes the specified node from its parent node. The removed node will still
+ be reusable unless the `destroy` option is truthy.
+
+ @method removeNode
+ @param {Tree.Node} node Node to remove.
+ @param {Object} [options] Options.
+ @param {Boolean} [options.destroy=false] If `true`, the 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.
+ @return {Tree.Node} Node that was removed.
+ **/
+ removeNode: function (node, options) {
+ options || (options = {});
+
+ this._fireTreeEvent(EVT_REMOVE, {
+ destroy: !!options.destroy,
+ node : node,
+ parent : node.parent,
+ src : options.src || 'remove'
+ }, {
+ defaultFn: this._defRemoveFn,
+ silent : options.silent
+ });
+
+ return node;
+ },
+
+ /**
+ Returns the total number of nodes in this tree, at all levels.
+
+ Use `rootNode.children.length` to get only the number of top-level nodes.
+
+ @method size
+ @return {Number} Total number of nodes in this tree.
+ **/
+ size: function () {
+ return this.rootNode.size() + 1;
+ },
+
+ /**
+ Serializes this tree to an object suitable for use in JSON.
+
+ @method toJSON
+ @return {Object} Serialized tree object.
+ **/
+ toJSON: function () {
+ return this.rootNode.toJSON();
+ },
+
+ /**
+ Performs a depth-first traversal of _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 traverseNode
+ @param {Tree.Node} node Node to 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`.
+ **/
+ traverseNode: function (node, options, callback, thisObj) {
+ // Allow callback as second argument.
+ if (typeof options === 'function') {
+ thisObj = callback;
+ callback = options;
+ options = {};
+ }
+
+ options || (options = {});
+
+ var stop = Tree.STOP_TRAVERSAL,
+ unlimited = typeof options.depth === 'undefined';
+
+ if (callback.call(thisObj, node) === stop) {
+ return stop;
+ }
+
+ var children = node.children;
+
+ if (unlimited || options.depth > 0) {
+ var childOptions = unlimited ? options : {depth: options.depth - 1};
+
+ for (var i = 0, len = children.length; i < len; i++) {
+ if (this.traverseNode(children[i], childOptions, callback, thisObj) === stop) {
+ return stop;
+ }
+ }
+ }
+ },
+
+ // -- Protected Methods ----------------------------------------------------
+
+ /**
+ Moves the specified node and all its children from another tree to this
+ tree.
+
+ @method _adoptNode
+ @param {Tree.Node} node Node to adopt.
+ @param {Object} [options] Options to pass along to `removeNode()`.
+ @protected
+ **/
+ _adoptNode: function (node, options) {
+ var oldTree = node.tree;
+
+ if (oldTree === this) {
+ return;
+ }
+
+ for (var i = 0, len = node.children.length; i < len; i++) {
+ this._adoptNode(node.children[i], {silent: true});
+ }
+
+ oldTree.removeNode(node, options);
+ delete oldTree._nodeMap[node.id];
+
+ // If this node isn't an instance of this tree's composed _nodeClass,
+ // then we need to recreate it to avoid potentially breaking things in
+ // really weird ways.
+ if (!(node instanceof this._nodeClass)
+ || oldTree._nodeClass !== this._nodeClass) {
+
+ node = this.createNode(node.toJSON());
+ }
+
+ node.tree = this;
+ this._nodeMap[node.id] = node;
+ },
+
+ /**
+ Composes a custom late-bound tree node class (if necessary) based on the
+ classes specified in this Tree's `nodeClass` and `nodeExtensions`
+ properties.
+
+ The composed class is stored in this Tree's `_nodeClass` property. If
+ composition wasn't necessary, then `_nodeClass` will just be a reference to
+ `nodeClass`.
+
+ @method _composeNodeClass
+ @protected
+ **/
+ _composeNodeClass: function () {
+ var nodeClass = this.nodeClass,
+ nodeExtensions = this.nodeExtensions,
+ composedClass;
+
+ if (typeof nodeClass === 'string') {
+ // Look for a namespaced node class on `Y`.
+ nodeClass = Y.Object.getValue(Y, nodeClass.split('.'));
+
+ if (nodeClass) {
+ this.nodeClass = nodeClass;
+ } else {
+ Y.error('Tree: Node class not found: ' + nodeClass);
+ return;
+ }
+ }
+
+ if (!nodeExtensions.length) {
+ this._nodeClass = nodeClass;
+ return;
+ }
+
+ // Compose a new class by mixing extensions into nodeClass.
+ composedClass = function () {
+ var extensions = composedClass._nodeExtensions;
+
+ nodeClass.apply(this, arguments);
+
+ for (var i = 0, len = extensions.length; i < len; i++) {
+ extensions[i].apply(this, arguments);
+ }
+ };
+
+ Y.extend(composedClass, nodeClass);
+
+ for (var i = 0, len = nodeExtensions.length; i < len; i++) {
+ Y.mix(composedClass.prototype, nodeExtensions[i].prototype, true);
+ }
+
+ composedClass._nodeExtensions = nodeExtensions;
+ this._nodeClass = composedClass;
+ },
+
+ /**
+ Utility method for lazily publishing and firing events.
+
+ @method _fireTreeEvent
+ @param {String} name Event name to fire.
+ @param {Object} facade Event facade.
+ @param {Object} [options] Options.
+ @param {Function} [options.defaultFn] Default handler for this event.
+ @param {Boolean} [options.silent=false] Whether the default handler
+ should be executed directly without actually firing the event.
+ @chainable
+ @protected
+ **/
+ _fireTreeEvent: function (name, facade, options) {
+ if (options && options.silent) {
+ if (options.defaultFn) {
+ options.defaultFn.call(this, facade);
+ }
+ } else {
+ if (options && options.defaultFn && !this._published[name]) {
+ this._published[name] = this.publish(name, {
+ defaultFn: options.defaultFn
+ });
+ }
+
+ this.fire(name, facade);
+ }
+
+ return this;
+ },
+
+ /**
+ Returns the default insertion index that should be used when _node_ is
+ inserted as a child of _parent_ without an explicit index.
+
+ The primary purpose of this method is to serve as a hook point for
+ extensions and plugins that need to customize insertion order.
+
+ @method _getDefaultNodeIndex
+ @param {Tree.Node} parent Parent node.
+ @param {Tree.Node} node Node being inserted.
+ @param {Object} [options] Options passed to `insertNode()`.
+ @return {Number} Index at which _node_ should be inserted into _parent_'s
+ `children` array.
+ @protected
+ **/
+ _getDefaultNodeIndex: function (parent/*, node, options*/) {
+ return parent.children.length;
+ },
+
+ /**
+ Removes the specified node from its parent node if it has one.
+
+ @method _removeNodeFromParent
+ @param {Tree.Node} node Node to remove.
+ @protected
+ **/
+ _removeNodeFromParent: function (node) {
+ var parent = node.parent,
+ index;
+
+ if (parent) {
+ index = parent.indexOf(node);
+
+ if (index > -1) {
+ parent.children.splice(index, 1);
+ parent._isIndexStale = true;
+ node.parent = null;
+ }
+ }
+ },
+
+ // -- Default Event Handlers -----------------------------------------------
+ _defAddFn: function (e) {
+ var node = e.node,
+ parent = e.parent;
+
+ // Remove the node from its existing parent if it has one.
+ if (node.parent) {
+ this._removeNodeFromParent(node);
+ }
+
+ // Add the node to its new parent at the desired index.
+ node.parent = parent;
+ parent.children.splice(e.index, 0, node);
+
+ parent.canHaveChildren = true;
+ parent._isIndexStale = true;
+ },
+
+ _defClearFn: function (e) {
+ var newRootNode = e.rootNode;
+
+ if (this.rootNode) {
+ this.destroyNode(this.rootNode, {silent: true});
+ }
+
+ this._nodeMap = {};
+ this._nodeMap[newRootNode.id] = newRootNode;
+
+ this.rootNode = newRootNode;
+ this.children = newRootNode.children;
+ },
+
+ _defRemoveFn: function (e) {
+ var node = e.node;
+
+ if (e.destroy) {
+ this.destroyNode(node, {silent: true});
+ } else if (e.parent) {
+ this._removeNodeFromParent(node);
+ } else if (this.rootNode === node) {
+ // Guess we'll need a new root node!
+ this.rootNode = this.createNode(this._rootNodeConfig);
+ this.children = this.rootNode.children;
+ }
+ }
+}, {
+ /**
+ Return this value from a `Tree#traverseNode()` or `Tree.Node#traverse()`
+ callback to immediately stop traversal.
+
+ @property STOP_TRAVERSAL
+ @static
+ **/
+ STOP_TRAVERSAL: {}
+});
+
+Y.Tree = Y.mix(Tree, Y.Tree);
+
+
+}, '3.10.3', {"requires": ["base-build", "tree-node"]});