src/cm/media/js/lib/yui/yui3-3.15.0/build/tree-node/tree-node-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('tree-node', function (Y, NAME) {
       
     2 
       
     3 /*jshint expr:true, onevar:false */
       
     4 
       
     5 /**
       
     6 Provides the `Tree.Node` class, which represents a tree node contained in a
       
     7 `Tree` data structure.
       
     8 
       
     9 @module tree
       
    10 @submodule tree-node
       
    11 **/
       
    12 
       
    13 /**
       
    14 Represents a tree node in a `Tree` data structure.
       
    15 
       
    16 @class Tree.Node
       
    17 @param {Tree} tree `Tree` instance with which this node should be associated.
       
    18 @param {Object} [config] Configuration hash for this node.
       
    19 
       
    20     @param {Boolean} [config.canHaveChildren=false] Whether or not this node can
       
    21         contain child nodes. Will be automatically set to `true` if not
       
    22         specified and `config.children` contains one or more children.
       
    23 
       
    24     @param {Tree.Node[]} [config.children] Array of `Tree.Node` instances
       
    25         for child nodes of this node.
       
    26 
       
    27     @param {Object} [config.data] Implementation-specific data related to this
       
    28         node. You may add arbitrary properties to this hash for your own use.
       
    29 
       
    30     @param {String} [config.id] Unique id for this node. This id must be unique
       
    31         among all tree nodes on the entire page, and will also be used as this
       
    32         node's DOM id when it's rendered by a TreeView. A unique id will be
       
    33         automatically generated unless you specify a custom value.
       
    34 
       
    35     @param {Object} [config.state] State hash for this node. You may add
       
    36         arbitrary state properties to this hash for your own use. See the
       
    37         docs for `Tree.Node`'s `state` property for details on state values used
       
    38         internally by `Tree.Node`.
       
    39 
       
    40 @constructor
       
    41 **/
       
    42 
       
    43 function TreeNode(tree, config) {
       
    44     config || (config = {});
       
    45 
       
    46     this.id   = this._yuid = config.id || this.id || Y.guid('treeNode-');
       
    47     this.tree = tree;
       
    48 
       
    49     this.children = config.children || [];
       
    50     this.data     = config.data || {};
       
    51     this.state    = config.state || {};
       
    52 
       
    53     if (config.canHaveChildren) {
       
    54         this.canHaveChildren = config.canHaveChildren;
       
    55     } else if (this.children.length) {
       
    56         this.canHaveChildren = true;
       
    57     }
       
    58 
       
    59     // Mix in arbitrary properties on the config object, but don't overwrite any
       
    60     // existing properties of this node.
       
    61     Y.mix(this, config);
       
    62 
       
    63     // If this node has children, loop through them and ensure their parent
       
    64     // references are all set to this node.
       
    65     for (var i = 0, len = this.children.length; i < len; i++) {
       
    66         this.children[i].parent = this;
       
    67     }
       
    68 }
       
    69 
       
    70 TreeNode.prototype = {
       
    71     // -- Public Properties ----------------------------------------------------
       
    72 
       
    73     /**
       
    74     Whether or not this node can contain child nodes.
       
    75 
       
    76     This value is falsy by default unless child nodes are added at instantiation
       
    77     time, in which case it will be automatically set to `true`. You can also
       
    78     manually set it to `true` to indicate that a node can have children even
       
    79     though it might not currently have any children.
       
    80 
       
    81     Note that regardless of the value of this property, appending, prepending,
       
    82     or inserting a node into this node will cause `canHaveChildren` to be set to
       
    83     true automatically.
       
    84 
       
    85     @property {Boolean} canHaveChildren
       
    86     **/
       
    87 
       
    88     /**
       
    89     Child nodes contained within this node.
       
    90 
       
    91     @property {Tree.Node[]} children
       
    92     @default []
       
    93     @readOnly
       
    94     **/
       
    95 
       
    96     /**
       
    97     Arbitrary serializable data related to this node.
       
    98 
       
    99     Use this property to store any data that should accompany this node when it
       
   100     is serialized to JSON.
       
   101 
       
   102     @property {Object} data
       
   103     @default {}
       
   104     **/
       
   105 
       
   106     /**
       
   107     Unique id for this node.
       
   108 
       
   109     @property {String} id
       
   110     @readOnly
       
   111     **/
       
   112 
       
   113     /**
       
   114     Parent node of this node, or `undefined` if this is an unattached node or
       
   115     the root node.
       
   116 
       
   117     @property {Tree.Node} parent
       
   118     @readOnly
       
   119     **/
       
   120 
       
   121     /**
       
   122     Current state of this node.
       
   123 
       
   124     Use this property to store state-specific info -- such as whether this node
       
   125     is "open", "selected", or any other arbitrary state -- that should accompany
       
   126     this node when it is serialized to JSON.
       
   127 
       
   128     @property {Object} state
       
   129     **/
       
   130 
       
   131     /**
       
   132     The Tree instance with which this node is associated.
       
   133 
       
   134     @property {Tree} tree
       
   135     @readOnly
       
   136     **/
       
   137 
       
   138     // -- Protected Properties -------------------------------------------------
       
   139 
       
   140     /**
       
   141     Mapping of child node ids to indices.
       
   142 
       
   143     @property {Object} _indexMap
       
   144     @protected
       
   145     **/
       
   146 
       
   147     /**
       
   148     Flag indicating whether the `_indexMap` is stale and needs to be rebuilt.
       
   149 
       
   150     @property {Boolean} _isIndexStale
       
   151     @default true
       
   152     @protected
       
   153     **/
       
   154     _isIndexStale: true,
       
   155 
       
   156     /**
       
   157     Simple way to type-check that this is an instance of Tree.Node.
       
   158 
       
   159     @property {Boolean} _isYUITreeNode
       
   160     @default true
       
   161     @protected
       
   162     **/
       
   163     _isYUITreeNode: true,
       
   164 
       
   165     /**
       
   166     Array of property names on this node that should be serialized to JSON when
       
   167     `toJSON()` is called.
       
   168 
       
   169     Note that the `children` property is a special case that is managed
       
   170     separately.
       
   171 
       
   172     @property {String[]} _serializable
       
   173     @protected
       
   174     **/
       
   175     _serializable: ['canHaveChildren', 'data', 'id', 'state'],
       
   176 
       
   177     // -- Public Methods -------------------------------------------------------
       
   178 
       
   179     /**
       
   180     Appends the given tree node or array of nodes to the end of this node's
       
   181     children.
       
   182 
       
   183     @method append
       
   184     @param {Object|Object[]|Tree.Node|Tree.Node[]} node Child node, node config
       
   185         object, array of child nodes, or array of node config objects to append
       
   186         to the given parent. Node config objects will automatically be converted
       
   187         into node instances.
       
   188     @param {Object} [options] Options.
       
   189         @param {Boolean} [options.silent=false] If `true`, the `add` event will
       
   190             be suppressed.
       
   191     @return {Tree.Node|Tree.Node[]} Node or array of nodes that were appended.
       
   192     **/
       
   193     append: function (node, options) {
       
   194         return this.tree.appendNode(this, node, options);
       
   195     },
       
   196 
       
   197     /**
       
   198     Returns this node's depth.
       
   199 
       
   200     The root node of a tree always has a depth of 0. A child of the root has a
       
   201     depth of 1, a child of that child will have a depth of 2, and so on.
       
   202 
       
   203     @method depth
       
   204     @return {Number} This node's depth.
       
   205     @since 3.11.0
       
   206     **/
       
   207     depth: function () {
       
   208         if (this.isRoot()) {
       
   209             return 0;
       
   210         }
       
   211 
       
   212         var depth  = 0,
       
   213             parent = this.parent;
       
   214 
       
   215         while (parent) {
       
   216             depth += 1;
       
   217             parent = parent.parent;
       
   218         }
       
   219 
       
   220         return depth;
       
   221     },
       
   222 
       
   223     /**
       
   224     Removes all children from this node. The removed children will still be
       
   225     reusable unless the `destroy` option is truthy.
       
   226 
       
   227     @method empty
       
   228     @param {Object} [options] Options.
       
   229         @param {Boolean} [options.destroy=false] If `true`, the children will
       
   230             also be destroyed, which makes them available for garbage collection
       
   231             and means they can't be reused.
       
   232         @param {Boolean} [options.silent=false] If `true`, `remove` events will
       
   233             be suppressed.
       
   234         @param {String} [options.src] Source of the change, to be passed along
       
   235             to the event facade of the resulting event. This can be used to
       
   236             distinguish between changes triggered by a user and changes
       
   237             triggered programmatically, for example.
       
   238     @return {Tree.Node[]} Array of removed child nodes.
       
   239     **/
       
   240     empty: function (options) {
       
   241         return this.tree.emptyNode(this, options);
       
   242     },
       
   243 
       
   244     /**
       
   245     Performs a depth-first traversal of this node, passing it and each of its
       
   246     descendants to the specified _callback_, and returning the first node for
       
   247     which the callback returns a truthy value.
       
   248 
       
   249     Traversal will stop as soon as a truthy value is returned from the callback.
       
   250 
       
   251     See `Tree#traverseNode()` for more details on how depth-first traversal
       
   252     works.
       
   253 
       
   254     @method find
       
   255     @param {Object} [options] Options.
       
   256         @param {Number} [options.depth] Depth limit. If specified, descendants
       
   257             will only be traversed to this depth before backtracking and moving
       
   258             on.
       
   259     @param {Function} callback Callback function to call with the traversed
       
   260         node and each of its descendants. If this function returns a truthy
       
   261         value, traversal will be stopped and the current node will be returned.
       
   262 
       
   263         @param {Tree.Node} callback.node Node being traversed.
       
   264 
       
   265     @param {Object} [thisObj] `this` object to use when executing _callback_.
       
   266     @return {Tree.Node|null} Returns the first node for which the _callback_
       
   267         returns a truthy value, or `null` if the callback never returns a truthy
       
   268         value.
       
   269     **/
       
   270     find: function (options, callback, thisObj) {
       
   271         return this.tree.findNode(this, options, callback, thisObj);
       
   272     },
       
   273 
       
   274     /**
       
   275     Returns `true` if this node has one or more child nodes.
       
   276 
       
   277     @method hasChildren
       
   278     @return {Boolean} `true` if this node has one or more child nodes, `false`
       
   279         otherwise.
       
   280     **/
       
   281     hasChildren: function () {
       
   282         return !!this.children.length;
       
   283     },
       
   284 
       
   285     /**
       
   286     Returns the numerical index of this node within its parent node, or `-1` if
       
   287     this node doesn't have a parent node.
       
   288 
       
   289     @method index
       
   290     @return {Number} Index of this node within its parent node, or `-1` if this
       
   291         node doesn't have a parent node.
       
   292     **/
       
   293     index: function () {
       
   294         return this.parent ? this.parent.indexOf(this) : -1;
       
   295     },
       
   296 
       
   297     /**
       
   298     Returns the numerical index of the given child node, or `-1` if the node is
       
   299     not a child of this node.
       
   300 
       
   301     @method indexOf
       
   302     @param {Tree.Node} node Child node.
       
   303     @return {Number} Index of the child, or `-1` if the node is not a child of
       
   304         this node.
       
   305     **/
       
   306     indexOf: function (node) {
       
   307         var index;
       
   308 
       
   309         if (this._isIndexStale) {
       
   310             this._reindex();
       
   311         }
       
   312 
       
   313         index = this._indexMap[node.id];
       
   314 
       
   315         return typeof index === 'undefined' ? -1 : index;
       
   316     },
       
   317 
       
   318     /**
       
   319     Inserts a node or array of nodes at the specified index under this node, or
       
   320     appends them to this node if no index is specified.
       
   321 
       
   322     If a node being inserted is from another tree, it and all its children will
       
   323     be removed from that tree and moved to this one.
       
   324 
       
   325     @method insert
       
   326     @param {Object|Object[]|Tree.Node|Tree.Node[]} node Child node, node config
       
   327         object, array of child nodes, or array of node config objects to insert
       
   328         under the given parent. Node config objects will automatically be
       
   329         converted into node instances.
       
   330 
       
   331     @param {Object} [options] Options.
       
   332         @param {Number} [options.index] Index at which to insert the child node.
       
   333             If not specified, the node will be appended as the last child of the
       
   334             parent.
       
   335         @param {Boolean} [options.silent=false] If `true`, the `add` event will
       
   336             be suppressed.
       
   337         @param {String} [options.src='insert'] Source of the change, to be
       
   338             passed along to the event facade of the resulting event. This can be
       
   339             used to distinguish between changes triggered by a user and changes
       
   340             triggered programmatically, for example.
       
   341 
       
   342     @return {Tree.Node[]} Node or array of nodes that were inserted.
       
   343     **/
       
   344     insert: function (node, options) {
       
   345         return this.tree.insertNode(this, node, options);
       
   346     },
       
   347 
       
   348     /**
       
   349     Returns `true` if this node has been inserted into a tree, `false` if it is
       
   350     merely associated with a tree and has not yet been inserted.
       
   351 
       
   352     @method isInTree
       
   353     @return {Boolean} `true` if this node has been inserted into a tree, `false`
       
   354         otherwise.
       
   355     **/
       
   356     isInTree: function () {
       
   357         if (this.tree && this.tree.rootNode === this) {
       
   358             return true;
       
   359         }
       
   360 
       
   361         return !!(this.parent && this.parent.isInTree());
       
   362     },
       
   363 
       
   364     /**
       
   365     Returns `true` if this node is the root of the tree.
       
   366 
       
   367     @method isRoot
       
   368     @return {Boolean} `true` if this node is the root of the tree, `false`
       
   369         otherwise.
       
   370     **/
       
   371     isRoot: function () {
       
   372         return !!(this.tree && this.tree.rootNode === this);
       
   373     },
       
   374 
       
   375     /**
       
   376     Returns this node's next sibling, or `undefined` if this node is the last
       
   377     child.
       
   378 
       
   379     @method next
       
   380     @return {Tree.Node} This node's next sibling, or `undefined` if this node is
       
   381         the last child.
       
   382     **/
       
   383     next: function () {
       
   384         if (this.parent) {
       
   385             return this.parent.children[this.index() + 1];
       
   386         }
       
   387     },
       
   388 
       
   389     /**
       
   390     Prepends a node or array of nodes at the beginning of this node's children.
       
   391 
       
   392     If a node being prepended is from another tree, it and all its children will
       
   393     be removed from that tree and moved to this one.
       
   394 
       
   395     @method prepend
       
   396     @param {Object|Object[]|Tree.Node|Tree.Node[]} node Child node, node config
       
   397         object, array of child nodes, or array of node config objects to prepend
       
   398         to this node. Node config objects will automatically be converted into
       
   399         node instances.
       
   400     @param {Object} [options] Options.
       
   401         @param {Boolean} [options.silent=false] If `true`, the `add` event will
       
   402             be suppressed.
       
   403     @return {Tree.Node|Tree.Node[]} Node or array of nodes that were prepended.
       
   404     **/
       
   405     prepend: function (node, options) {
       
   406         return this.tree.prependNode(this, node, options);
       
   407     },
       
   408 
       
   409     /**
       
   410     Returns this node's previous sibling, or `undefined` if this node is the
       
   411     first child
       
   412 
       
   413     @method previous
       
   414     @return {Tree.Node} This node's previous sibling, or `undefined` if this
       
   415         node is the first child.
       
   416     **/
       
   417     previous: function () {
       
   418         if (this.parent) {
       
   419             return this.parent.children[this.index() - 1];
       
   420         }
       
   421     },
       
   422 
       
   423     /**
       
   424     Removes this node from its parent node.
       
   425 
       
   426     @method remove
       
   427     @param {Object} [options] Options.
       
   428         @param {Boolean} [options.destroy=false] If `true`, this node and all
       
   429             its children will also be destroyed, which makes them available for
       
   430             garbage collection and means they can't be reused.
       
   431         @param {Boolean} [options.silent=false] If `true`, the `remove` event
       
   432             will be suppressed.
       
   433         @param {String} [options.src] Source of the change, to be passed along
       
   434             to the event facade of the resulting event. This can be used to
       
   435             distinguish between changes triggered by a user and changes
       
   436             triggered programmatically, for example.
       
   437     @chainable
       
   438     **/
       
   439     remove: function (options) {
       
   440         return this.tree.removeNode(this, options);
       
   441     },
       
   442 
       
   443     /**
       
   444     Returns the total number of nodes contained within this node, including all
       
   445     descendants of this node's children.
       
   446 
       
   447     @method size
       
   448     @return {Number} Total number of nodes contained within this node, including
       
   449         all descendants.
       
   450     **/
       
   451     size: function () {
       
   452         var children = this.children,
       
   453             len      = children.length,
       
   454             total    = len;
       
   455 
       
   456         for (var i = 0; i < len; i++) {
       
   457             total += children[i].size();
       
   458         }
       
   459 
       
   460         return total;
       
   461     },
       
   462 
       
   463     /**
       
   464     Serializes this node to an object suitable for use in JSON.
       
   465 
       
   466     @method toJSON
       
   467     @return {Object} Serialized node object.
       
   468     **/
       
   469     toJSON: function () {
       
   470         var obj   = {},
       
   471             state = this.state,
       
   472             i, key, len;
       
   473 
       
   474         // Do nothing if this node is marked as destroyed.
       
   475         if (state.destroyed) {
       
   476             return null;
       
   477         }
       
   478 
       
   479         // Serialize properties explicitly marked as serializable.
       
   480         for (i = 0, len = this._serializable.length; i < len; i++) {
       
   481             key = this._serializable[i];
       
   482 
       
   483             if (key in this) {
       
   484                 obj[key] = this[key];
       
   485             }
       
   486         }
       
   487 
       
   488         // Serialize child nodes.
       
   489         if (this.canHaveChildren) {
       
   490             obj.children = [];
       
   491 
       
   492             for (i = 0, len = this.children.length; i < len; i++) {
       
   493                 obj.children.push(this.children[i].toJSON());
       
   494             }
       
   495         }
       
   496 
       
   497         return obj;
       
   498     },
       
   499 
       
   500     /**
       
   501     Performs a depth-first traversal of this node, passing it and each of its
       
   502     descendants to the specified _callback_.
       
   503 
       
   504     If the callback function returns `Tree.STOP_TRAVERSAL`, traversal will be
       
   505     stopped immediately. Otherwise, it will continue until the deepest
       
   506     descendant of _node_ has been traversed, or until each branch has been
       
   507     traversed to the optional maximum depth limit.
       
   508 
       
   509     Since traversal is depth-first, that means nodes are traversed like this:
       
   510 
       
   511                 1
       
   512               / | \
       
   513              2  8  9
       
   514             / \     \
       
   515            3   7    10
       
   516          / | \      / \
       
   517         4  5  6    11 12
       
   518 
       
   519     @method traverse
       
   520     @param {Object} [options] Options.
       
   521         @param {Number} [options.depth] Depth limit. If specified, descendants
       
   522             will only be traversed to this depth before backtracking and moving
       
   523             on.
       
   524     @param {Function} callback Callback function to call with the traversed
       
   525         node and each of its descendants.
       
   526 
       
   527         @param {Tree.Node} callback.node Node being traversed.
       
   528 
       
   529     @param {Object} [thisObj] `this` object to use when executing _callback_.
       
   530     @return {Mixed} Returns `Tree.STOP_TRAVERSAL` if traversal was stopped;
       
   531         otherwise returns `undefined`.
       
   532     **/
       
   533     traverse: function (options, callback, thisObj) {
       
   534         return this.tree.traverseNode(this, options, callback, thisObj);
       
   535     },
       
   536 
       
   537     // -- Protected Methods ----------------------------------------------------
       
   538     _reindex: function () {
       
   539         var children = this.children,
       
   540             indexMap = {},
       
   541             i, len;
       
   542 
       
   543         for (i = 0, len = children.length; i < len; i++) {
       
   544             indexMap[children[i].id] = i;
       
   545         }
       
   546 
       
   547         this._indexMap     = indexMap;
       
   548         this._isIndexStale = false;
       
   549     }
       
   550 };
       
   551 
       
   552 Y.namespace('Tree').Node = TreeNode;
       
   553 
       
   554 
       
   555 }, '@VERSION@');