[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/tree-node/ -> tree-node-debug.js (source)

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


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1