[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/templates/default/YahooUI/treeview/ -> treeview.js (source)

   1  /*
   2  Copyright (c) 2006 Yahoo! Inc. All rights reserved.
   3  version 0.9.0
   4  */
   5  
   6  /**
   7   * @class Contains the tree view metadata and the root node.  This is an
   8   * ordered tree; child nodes will be displayed in the order created, and
   9   * there currently is no way to change this.
  10   *
  11   * @constructor
  12   * @todo prune, graft, reload, repaint
  13   * @param {string} id The id of the element that the tree will be inserted
  14   * into.
  15   */
  16  YAHOO.widget.TreeView = function(id) {
  17      if (id) { this.init(id); }
  18  };
  19  
  20  YAHOO.widget.TreeView.prototype = {
  21  
  22      /**
  23       * The id of tree container element
  24       *
  25       * @type String
  26       */
  27      id: null,
  28  
  29      /**
  30       * Flat collection of all nodes in this tree
  31       *
  32       * @type YAHOO.widget.Node[]
  33       * @private
  34       */
  35      _nodes: null,
  36  
  37      /**
  38       * We lock the tree control while waiting for the dynamic loader to return
  39       *
  40       * @type boolean
  41       */
  42      locked: false,
  43  
  44      /**
  45       * The animation to use for expanding children, if any
  46       *
  47       * @type string
  48       * @private
  49       */
  50      _expandAnim: null,
  51  
  52      /**
  53       * The animation to use for collapsing children, if any
  54       *
  55       * @type string
  56       * @private
  57       */
  58      _collapseAnim: null,
  59  
  60      /**
  61       * The current number of animations that are executing
  62       *
  63       * @type int
  64       * @private
  65       */
  66      _animCount: 0,
  67  
  68      /**
  69       * The maximum number of animations to run at one time.
  70       *
  71       * @type int
  72       */
  73      _maxAnim: 2,
  74  
  75      /**
  76       * Sets up the animation for expanding children
  77       *
  78       * @param {string} the type of animation (acceptable constants in YAHOO.widget.TVAnim)
  79       */
  80      setExpandAnim: function(type) {
  81          if (YAHOO.widget.TVAnim.isValid(type)) {
  82              this._expandAnim = type;
  83          }
  84      },
  85  
  86      /**
  87       * Sets up the animation for collapsing children
  88       *
  89       * @param {string} the type of animation (acceptable constants in YAHOO.widget.TVAnim)
  90       */
  91      setCollapseAnim: function(type) {
  92          if (YAHOO.widget.TVAnim.isValid(type)) {
  93              this._collapseAnim = type;
  94          }
  95      },
  96  
  97      /**
  98       * Perform the expand animation if configured, or just show the
  99       * element if not configured or too many animations are in progress
 100       *
 101       * @param el {HTMLElement} the element to animate
 102       * @return {boolean} true if animation could be invoked, false otherwise
 103       */
 104      animateExpand: function(el) {
 105  
 106          if (this._expandAnim && this._animCount < this._maxAnim) {
 107              // this.locked = true;
 108              var tree = this;
 109              var a = YAHOO.widget.TVAnim.getAnim(this._expandAnim, el,
 110                              function() { tree.expandComplete(); });
 111              if (a) {
 112                  ++this._animCount;
 113                  a.animate();
 114              }
 115  
 116              return true;
 117          }
 118  
 119          return false;
 120      },
 121  
 122      /**
 123       * Perform the collapse animation if configured, or just show the
 124       * element if not configured or too many animations are in progress
 125       *
 126       * @param el {HTMLElement} the element to animate
 127       * @return {boolean} true if animation could be invoked, false otherwise
 128       */
 129      animateCollapse: function(el) {
 130  
 131          if (this._collapseAnim && this._animCount < this._maxAnim) {
 132              // this.locked = true;
 133              var tree = this;
 134              var a = YAHOO.widget.TVAnim.getAnim(this._collapseAnim, el,
 135                              function() { tree.collapseComplete(); });
 136              if (a) {
 137                  ++this._animCount;
 138                  a.animate();
 139              }
 140  
 141              return true;
 142          }
 143  
 144          return false;
 145      },
 146  
 147      /**
 148       * Function executed when the expand animation completes
 149       */
 150      expandComplete: function() {
 151          --this._animCount;
 152          // this.locked = false;
 153      },
 154  
 155      /**
 156       * Function executed when the collapse animation completes
 157       */
 158      collapseComplete: function() {
 159          --this._animCount;
 160          // this.locked = false;
 161      },
 162  
 163      /**
 164       * Initializes the tree
 165       *
 166       * @parm {string} id the id of the element that will hold the tree
 167       * @private
 168       */
 169      init: function(id) {
 170  
 171          this.id = id;
 172          this._nodes = new Array();
 173  
 174          // store a global reference
 175          YAHOO.widget.TreeView.trees[id] = this;
 176  
 177          // Set up the root node
 178          this.root = new YAHOO.widget.RootNode(this);
 179  
 180  
 181      },
 182  
 183      /**
 184       * Renders the tree boilerplate and visible nodes
 185       */
 186      draw: function() {
 187          var html = this.root.getHtml();
 188          document.getElementById(this.id).innerHTML = html;
 189          this.firstDraw = false;
 190      },
 191  
 192      /**
 193       * Nodes register themselves with the tree instance when they are created.
 194       *
 195       * @param node {YAHOO.widget.Node} the node to register
 196       * @private
 197       */
 198      regNode: function(node) {
 199          this._nodes[node.index] = node;
 200      },
 201  
 202      /**
 203       * Returns the root node of this tree
 204       *
 205       * @return {YAHOO.widget.Node} the root node
 206       */
 207      getRoot: function() {
 208          return this.root;
 209      },
 210  
 211      /**
 212       * Configures this tree to dynamically load all child data
 213       *
 214       * @param {function} fnDataLoader the function that will be called to get the data
 215       */
 216      setDynamicLoad: function(fnDataLoader) {
 217          // this.root.dataLoader = fnDataLoader;
 218          // this.root._dynLoad = true;
 219          this.root.setDynamicLoad(fnDataLoader);
 220      },
 221  
 222      /**
 223       * Expands all child nodes.  Note: this conflicts with the "multiExpand"
 224       * node property.  If expand all is called in a tree with nodes that
 225       * do not allow multiple siblings to be displayed, only the last sibling
 226       * will be expanded.
 227       */
 228      expandAll: function() {
 229          if (!this.locked) {
 230              this.root.expandAll();
 231          }
 232      },
 233  
 234      /**
 235       * Collapses all expanded child nodes in the entire tree.
 236       */
 237      collapseAll: function() {
 238          if (!this.locked) {
 239              this.root.collapseAll();
 240          }
 241      },
 242  
 243      /**
 244       * Returns a node in the tree that has the specified index (this index
 245       * is created internally, so this function probably will only be used
 246       * in html generated for a given node.)
 247       *
 248       * @param {int} nodeIndex the index of the node wanted
 249       * @return {YAHOO.widget.Node} the node with index=nodeIndex, null if no match
 250       */
 251      getNodeByIndex: function(nodeIndex) {
 252          var n = this._nodes[nodeIndex];
 253          return (n) ? n : null;
 254      },
 255  
 256      /**
 257       * Returns a node that has a matching property and value in the data
 258       * object that was passed into its constructor.  Provides a flexible
 259       * way for the implementer to get a particular node.
 260       *
 261       * @param {object} property the property to search (usually a string)
 262       * @param {object} value the value we want to find (usuall an int or string)
 263       * @return {YAHOO.widget.Node} the matching node, null if no match
 264       */
 265      getNodeByProperty: function(property, value) {
 266          for (var i in this._nodes) {
 267              var n = this._nodes[i];
 268              if (n.data && value == n.data[property]) {
 269                  return n;
 270              }
 271          }
 272  
 273          return null;
 274      },
 275  
 276      /**
 277       * Abstract method that is executed when a node is expanded
 278       *
 279       * @param node {YAHOO.widget.Node} the node that was expanded
 280       */
 281      onExpand: function(node) { },
 282  
 283      /**
 284       * Abstract method that is executed when a node is collapsed
 285       *
 286       * @param node {YAHOO.widget.Node} the node that was collapsed.
 287       */
 288      onCollapse: function(node) { }
 289  
 290  };
 291  
 292  /**
 293   * Global cache of tree instances
 294   *
 295   * @type Array
 296   * @private
 297   */
 298  YAHOO.widget.TreeView.trees = [];
 299  
 300  /**
 301   * Global method for getting a tree by its id.  Used in the generated
 302   * tree html.
 303   *
 304   * @param treeId {String} the id of the tree instance
 305   * @return {TreeView} the tree instance requested, null if not found.
 306   */
 307  YAHOO.widget.TreeView.getTree = function(treeId) {
 308      var t = YAHOO.widget.TreeView.trees[treeId];
 309      return (t) ? t : null;
 310  };
 311  
 312  YAHOO.widget.TreeView.nodeCount = 0;
 313  
 314  /**
 315   * Global method for getting a node by its id.  Used in the generated
 316   * tree html.
 317   *
 318   * @param treeId {String} the id of the tree instance
 319   * @param nodeIndex {String} the index of the node to return
 320   * @param return {YAHOO.widget.Node} the node instance requested, null if not found
 321   */
 322  YAHOO.widget.TreeView.getNode = function(treeId, nodeIndex) {
 323      var t = YAHOO.widget.TreeView.getTree(treeId);
 324      return (t) ? t.getNodeByIndex(nodeIndex) : null;
 325  };
 326  
 327  /**
 328   * Adds an event.  Replace with event manager when available
 329   *
 330   * @param el the elment to bind the handler to
 331   * @param {string} sType the type of event handler
 332   * @param {function} fn the callback to invoke
 333   * @param {boolean} capture if true event is capture phase, bubble otherwise
 334   */
 335  YAHOO.widget.TreeView.addHandler = function (el, sType, fn, capture) {
 336      capture = (capture) ? true : false;
 337      if (el.addEventListener) {
 338          el.addEventListener(sType, fn, capture);
 339      } else if (el.attachEvent) {
 340          el.attachEvent("on" + sType, fn);
 341      } else {
 342          el["on" + sType] = fn;
 343      }
 344  };
 345  
 346  /**
 347   * Attempts to preload the images defined in the styles used to draw the tree by
 348   * rendering off-screen elements that use the styles.
 349   */
 350  YAHOO.widget.TreeView.preload = function() {
 351  
 352      var styles = [
 353          "ygtvtn",
 354          "ygtvtm",
 355          "ygtvtmh",
 356          "ygtvtp",
 357          "ygtvtph",
 358          "ygtvln",
 359          "ygtvlm",
 360          "ygtvlmh",
 361          "ygtvlp",
 362          "ygtvlph",
 363          "ygtvloading"
 364          ];
 365  
 366      var sb = [];
 367  
 368      for (var i = 0; i < styles.length; ++i) {
 369          sb[sb.length] = '<span class="' + styles[i] + '">&nbsp;</span>';
 370      }
 371  
 372      var f = document.createElement("div");
 373      var s = f.style;
 374      s.position = "absolute";
 375      s.top = "-1000px";
 376      s.left = "-1000px";
 377      f.innerHTML = sb.join("");
 378  
 379      document.body.appendChild(f);
 380  };
 381  
 382  YAHOO.widget.TreeView.addHandler(window,
 383                  "load", YAHOO.widget.TreeView.preload);
 384  
 385  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
 386  
 387  /**
 388   * @class Abstract node class
 389   * @constructor
 390   * @param oData {object} a string or object containing the data that will
 391   * be used to render this node
 392   * @param oParent {YAHOO.widget.Node} this node's parent node
 393   * @param expanded {boolean} the initial expanded/collapsed state
 394   */
 395  YAHOO.widget.Node = function(oData, oParent, expanded) {
 396      if (oParent) { this.init(oData, oParent, expanded); }
 397  };
 398  
 399  YAHOO.widget.Node.prototype = {
 400  
 401      /**
 402       * The index for this instance obtained from global counter in YAHOO.widget.TreeView.
 403       *
 404       * @type int
 405       */
 406      index: 0,
 407  
 408      /**
 409       * This node's child node collection.
 410       *
 411       * @type YAHOO.widget.Node[]
 412       */
 413      children: null,
 414  
 415      /**
 416       * Tree instance this node is part of
 417       *
 418       * @type YAHOO.widget.TreeView
 419       */
 420      tree: null,
 421  
 422      /**
 423       * The data linked to this node.  This can be any object or primitive
 424       * value, and the data can be used in getNodeHtml().
 425       *
 426       * @type object
 427       */
 428      data: null,
 429  
 430      /**
 431       * Parent node
 432       *
 433       * @type YAHOO.widget.Node
 434       */
 435      parent: null,
 436  
 437      /**
 438       * The depth of this node.  We start at -1 for the root node.
 439       *
 440       * @type int
 441       */
 442      depth: -1,
 443  
 444      /**
 445       * The href for the node's label.  If one is not specified, the href will
 446       * be set so that it toggles the node.
 447       *
 448       * @type string
 449       */
 450      href: null,
 451  
 452      /**
 453       * The label href target, defaults to current window
 454       *
 455       * @type string
 456       */
 457      target: "_self",
 458  
 459      /**
 460       * The node's expanded/collapsed state
 461       *
 462       * @type boolean
 463       */
 464      expanded: false,
 465  
 466      /**
 467       * Can multiple children be expanded at once?
 468       *
 469       * @type boolean
 470       */
 471      multiExpand: true,
 472  
 473      /**
 474       * Should we render children for a collapsed node?  It is possible that the
 475       * implementer will want to render the hidden data...  @todo verify that we
 476       * need this, and implement it if we do.
 477       *
 478       * @type boolean
 479       */
 480      renderHidden: false,
 481  
 482      /**
 483       * Flag that is set to true the first time this node's children are rendered.
 484       *
 485       * @type boolean
 486       */
 487      childrenRendered: false,
 488  
 489      /**
 490       * This node's previous sibling
 491       *
 492       * @type YAHOO.widget.Node
 493       */
 494      previousSibling: null,
 495  
 496      /**
 497       * This node's next sibling
 498       *
 499       * @type YAHOO.widget.Node
 500       */
 501      nextSibling: null,
 502  
 503      /**
 504       * We can set the node up to call an external method to get the child
 505       * data dynamically.
 506       *
 507       * @type boolean
 508       * @private
 509       */
 510      _dynLoad: false,
 511  
 512      /**
 513       * Function to execute when we need to get this node's child data.
 514       *
 515       * @type function
 516       */
 517      dataLoader: null,
 518  
 519      /**
 520       * This is true for dynamically loading nodes while waiting for the
 521       * callback to return.
 522       *
 523       * @type boolean
 524       */
 525      isLoading: false,
 526  
 527      /**
 528       * The toggle/branch icon will not show if this is set to false.  This
 529       * could be useful if the implementer wants to have the child contain
 530       * extra info about the parent, rather than an actual node.
 531       *
 532       * @type boolean
 533       */
 534      hasIcon: true,
 535  
 536      /**
 537       * Initializes this node, gets some of the properties from the parent
 538       *
 539       * @param oData {object} a string or object containing the data that will
 540       * be used to render this node
 541       * @param oParent {YAHOO.widget.Node} this node's parent node
 542       * @param expanded {boolean} the initial expanded/collapsed state
 543       */
 544      init: function(oData, oParent, expanded) {
 545          this.data        = oData;
 546          this.children    = [];
 547          this.index        = YAHOO.widget.TreeView.nodeCount;
 548          ++YAHOO.widget.TreeView.nodeCount;
 549          this.expanded    = expanded;
 550  
 551          // oParent should never be null except when we create the root node.
 552          if (oParent) {
 553              this.tree            = oParent.tree;
 554              this.parent            = oParent;
 555              this.href            = "javascript:" + this.getToggleLink();
 556              this.depth            = oParent.depth + 1;
 557              this.multiExpand    = oParent.multiExpand;
 558  
 559              oParent.appendChild(this);
 560          }
 561      },
 562  
 563      /**
 564       * Appends a node to the child collection.
 565       *
 566       * @param node {YAHOO.widget.Node} the new node
 567       * @return {YAHOO.widget.Node} the child node
 568       * @private
 569       */
 570      appendChild: function(node) {
 571          if (this.hasChildren()) {
 572              var sib = this.children[this.children.length - 1];
 573              sib.nextSibling = node;
 574              node.previousSibling = sib;
 575          }
 576  
 577          this.tree.regNode(node);
 578          this.children[this.children.length] = node;
 579          return node;
 580  
 581      },
 582  
 583      /**
 584       * Returns a node array of this node's siblings, null if none.
 585       *
 586       * @return YAHOO.widget.Node[]
 587       */
 588      getSiblings: function() {
 589          return this.parent.children;
 590      },
 591  
 592      /**
 593       * Shows this node's children
 594       */
 595      showChildren: function() {
 596          if (!this.tree.animateExpand(this.getChildrenEl())) {
 597              if (this.hasChildren()) {
 598                  this.getChildrenEl().style.display = "";
 599              }
 600          }
 601      },
 602  
 603      /**
 604       * Hides this node's children
 605       */
 606      hideChildren: function() {
 607  
 608          if (!this.tree.animateCollapse(this.getChildrenEl())) {
 609              this.getChildrenEl().style.display = "none";
 610          }
 611      },
 612  
 613      /**
 614       * Returns the id for this node's container div
 615       *
 616       * @return {string} the element id
 617       */
 618      getElId: function() {
 619          return "ygtv" + this.index;
 620      },
 621  
 622      /**
 623       * Returns the id for this node's children div
 624       *
 625       * @return {string} the element id for this node's children div
 626       */
 627      getChildrenElId: function() {
 628          return "ygtvc" + this.index;
 629      },
 630  
 631      /**
 632       * Returns the id for this node's toggle element
 633       *
 634       * @return {string} the toggel element id
 635       */
 636      getToggleElId: function() {
 637          return "ygtvt" + this.index;
 638      },
 639  
 640      /**
 641       * Returns this node's container html element
 642       *
 643       * @return {Object} the container html element
 644       */
 645      getEl: function() {
 646          return document.getElementById(this.getElId());
 647      },
 648  
 649      /**
 650       * Returns the div that was generated for this node's children
 651       *
 652       * @return {Object} this node's children div
 653       */
 654      getChildrenEl: function() {
 655          return document.getElementById(this.getChildrenElId());
 656      },
 657  
 658      /**
 659       * Returns the element that is being used for this node's toggle.
 660       *
 661       * @return {Object} this node's toggel html element
 662       */
 663      getToggleEl: function() {
 664          return document.getElementById(this.getToggleElId());
 665      },
 666  
 667      /**
 668       * Generates the link that will invoke this node's toggle method
 669       *
 670       * @return {string} the javascript url for toggling this node
 671       */
 672      getToggleLink: function() {
 673          return "YAHOO.widget.TreeView.getNode(\'" + this.tree.id + "\'," +
 674              this.index + ").toggle()";
 675      },
 676  
 677      /**
 678       * Hides this nodes children (creating them if necessary), changes the
 679       * toggle style.
 680       */
 681      collapse: function() {
 682          // Only collapse if currently expanded
 683          if (!this.expanded) { return; }
 684  
 685          if (!this.getEl()) {
 686              this.expanded = false;
 687              return;
 688          }
 689  
 690          // hide the child div
 691          this.hideChildren();
 692          this.expanded = false;
 693  
 694          if (this.hasIcon) {
 695              this.getToggleEl().className = this.getStyle();
 696          }
 697  
 698          // fire the collapse event handler
 699          this.tree.onCollapse(this);
 700      },
 701  
 702      /**
 703       * Shows this nodes children (creating them if necessary), changes the
 704       * toggle style, and collapses its siblings if multiExpand is not set.
 705       */
 706      expand: function() {
 707          // Only expand if currently collapsed.
 708          if (this.expanded) { return; }
 709  
 710          if (!this.getEl()) {
 711              this.expanded = true;
 712              return;
 713          }
 714  
 715          if (! this.childrenRendered) {
 716              this.getChildrenEl().innerHTML = this.renderChildren();
 717          }
 718  
 719          this.expanded = true;
 720          if (this.hasIcon) {
 721              this.getToggleEl().className = this.getStyle();
 722          }
 723  
 724          // We do an extra check for children here because the lazy
 725          // load feature can expose nodes that have no children.
 726  
 727          // if (!this.hasChildren()) {
 728          if (this.isLoading) {
 729              this.expanded = false;
 730              return;
 731          }
 732  
 733          if (! this.multiExpand) {
 734              var sibs = this.getSiblings();
 735              for (var i=0; i<sibs.length; ++i) {
 736                  if (sibs[i] != this && sibs[i].expanded) {
 737                      sibs[i].collapse();
 738                  }
 739              }
 740          }
 741  
 742          this.showChildren();
 743  
 744          // fire the expand event handler
 745          this.tree.onExpand(this);
 746      },
 747  
 748      /**
 749       * Returns the css style name for the toggle
 750       *
 751       * @return {string} the css class for this node's toggle
 752       */
 753      getStyle: function() {
 754          if (this.isLoading) {
 755              return "ygtvloading";
 756          } else {
 757              // location top or bottom, middle nodes also get the top style
 758              var loc = (this.nextSibling) ? "t" : "l";
 759  
 760              // type p=plus(expand), m=minus(collapase), n=none(no children)
 761              var type = "n";
 762              if (this.hasChildren(true) || this.isDynamic()) {
 763                  type = (this.expanded) ? "m" : "p";
 764              }
 765  
 766              return "ygtv" + loc + type;
 767          }
 768      },
 769  
 770      /**
 771       * Returns the hover style for the icon
 772       * @return {string} the css class hover state
 773       */
 774      getHoverStyle: function() {
 775          var s = this.getStyle();
 776          if (this.hasChildren(true) && !this.isLoading) {
 777              s += "h";
 778          }
 779          return s;
 780      },
 781  
 782      /**
 783       * Recursively expands all of this node's children.
 784       */
 785      expandAll: function() {
 786          for (var i=0;i<this.children.length;++i) {
 787              var c = this.children[i];
 788              if (c.isDynamic()) {
 789                  alert("Not supported (lazy load + expand all)");
 790                  break;
 791              } else if (! c.multiExpand) {
 792                  alert("Not supported (no multi-expand + expand all)");
 793                  break;
 794              } else {
 795                  c.expand();
 796                  c.expandAll();
 797              }
 798          }
 799      },
 800  
 801      /**
 802       * Recursively collapses all of this node's children.
 803       */
 804      collapseAll: function() {
 805          for (var i=0;i<this.children.length;++i) {
 806              this.children[i].collapse();
 807              this.children[i].collapseAll();
 808          }
 809      },
 810  
 811      /**
 812       * Configures this node for dynamically obtaining the child data
 813       * when the node is first expanded.
 814       *
 815       * @param fmDataLoader {function} the function that will be used to get the data.
 816       */
 817      setDynamicLoad: function(fnDataLoader) {
 818          this.dataLoader = fnDataLoader;
 819          this._dynLoad = true;
 820      },
 821  
 822      /**
 823       * Evaluates if this node is the root node of the tree
 824       *
 825       * @return {boolean} true if this is the root node
 826       */
 827      isRoot: function() {
 828          return (this == this.tree.root);
 829      },
 830  
 831      /**
 832       * Evaluates if this node's children should be loaded dynamically.  Looks for
 833       * the property both in this instance and the root node.  If the tree is
 834       * defined to load all children dynamically, the data callback function is
 835       * defined in the root node
 836       *
 837       * @return {boolean} true if this node's children are to be loaded dynamically
 838       */
 839      isDynamic: function() {
 840          var lazy = (!this.isRoot() && (this._dynLoad || this.tree.root._dynLoad));
 841          return lazy;
 842      },
 843  
 844      /**
 845       * Checks if this node has children.  If this node is lazy-loading and the
 846       * children have not been rendered, we do not know whether or not there
 847       * are actual children.  In most cases, we need to assume that there are
 848       * children (for instance, the toggle needs to show the expandable
 849       * presentation state).  In other times we want to know if there are rendered
 850       * children.  For the latter, "checkForLazyLoad" should be false.
 851       *
 852       * @param checkForLazyLoad {boolean} should we check for unloaded children?
 853       * @return {boolean} true if this has children or if it might and we are
 854       * checking for this condition.
 855       */
 856      hasChildren: function(checkForLazyLoad) {
 857          return ( this.children.length > 0 ||
 858                  (checkForLazyLoad && this.isDynamic() && !this.childrenRendered) );
 859      },
 860  
 861      /**
 862       * Expands if node is collapsed, collapses otherwise.
 863       */
 864      toggle: function() {
 865          if (!this.tree.locked && ( this.hasChildren(true) || this.isDynamic()) ) {
 866              if (this.expanded) { this.collapse(); } else { this.expand(); }
 867          }
 868      },
 869  
 870      /**
 871       * Returns the markup for this node and its children.
 872       *
 873       * @return {string} the markup for this node and its expanded children.
 874       */
 875      getHtml: function() {
 876          var sb = [];
 877          sb[sb.length] = '<div class="ygtvitem" id="' + this.getElId() + '">';
 878          sb[sb.length] = this.getNodeHtml();
 879          sb[sb.length] = this.getChildrenHtml();
 880          sb[sb.length] = '</div>';
 881          return sb.join("");
 882      },
 883  
 884      /**
 885       * Called when first rendering the tree.  We always build the div that will
 886       * contain this nodes children, but we don't render the children themselves
 887       * unless this node is expanded.
 888       *
 889       * @return {string} the children container div html and any expanded children
 890       * @private
 891       */
 892      getChildrenHtml: function() {
 893          var sb = [];
 894          sb[sb.length] = '<div class="ygtvchildren"';
 895          sb[sb.length] = ' id="' + this.getChildrenElId() + '"';
 896          if (!this.expanded) {
 897              sb[sb.length] = ' style="display:none;"';
 898          }
 899          sb[sb.length] = '>';
 900  
 901          // Don't render the actual child node HTML unless this node is expanded.
 902          if (this.hasChildren(true) && this.expanded) {
 903              sb[sb.length] = this.renderChildren();
 904          }
 905  
 906          sb[sb.length] = '</div>';
 907  
 908          return sb.join("");
 909      },
 910  
 911      /**
 912       * Generates the markup for the child nodes.  This is not done until the node
 913       * is expanded.
 914       *
 915       * @return {string} the html for this node's children
 916       * @private
 917       */
 918      renderChildren: function() {
 919  
 920  
 921          var node = this;
 922  
 923          if (this.isDynamic() && !this.childrenRendered) {
 924              this.isLoading = true;
 925              this.tree.locked = true;
 926  
 927              if (this.dataLoader) {
 928                  setTimeout(
 929                      function() {
 930                          node.dataLoader(node,
 931                              function() {
 932                                  node.loadComplete();
 933                              });
 934                      }, 10);
 935  
 936              } else if (this.tree.root.dataLoader) {
 937  
 938                  setTimeout(
 939                      function() {
 940                          node.tree.root.dataLoader(node,
 941                              function() {
 942                                  node.loadComplete();
 943                              });
 944                      }, 10);
 945  
 946              } else {
 947                  return "Error: data loader not found or not specified.";
 948              }
 949  
 950              return "";
 951  
 952          } else {
 953              return this.completeRender();
 954          }
 955      },
 956  
 957      /**
 958       * Called when we know we have all the child data.
 959       * @return {string} children html
 960       */
 961      completeRender: function() {
 962          var sb = [];
 963  
 964          for (var i=0; i < this.children.length; ++i) {
 965              sb[sb.length] = this.children[i].getHtml();
 966          }
 967  
 968          this.childrenRendered = true;
 969  
 970          return sb.join("");
 971      },
 972  
 973      /**
 974       * Load complete is the callback function we pass to the data provider
 975       * in dynamic load situations.
 976       */
 977      loadComplete: function() {
 978          this.getChildrenEl().innerHTML = this.completeRender();
 979          this.isLoading = false;
 980          this.expand();
 981          this.tree.locked = false;
 982      },
 983  
 984      /**
 985       * Returns this node's ancestor at the specified depth.
 986       *
 987       * @param {int} depth the depth of the ancestor.
 988       * @return {YAHOO.widget.Node} the ancestor
 989       */
 990      getAncestor: function(depth) {
 991          if (depth >= this.depth || depth < 0)  {
 992              return null;
 993          }
 994  
 995          var p = this.parent;
 996  
 997          while (p.depth > depth) {
 998              p = p.parent;
 999          }
1000  
1001          return p;
1002      },
1003  
1004      /**
1005       * Returns the css class for the spacer at the specified depth for
1006       * this node.  If this node's ancestor at the specified depth
1007       * has a next sibling the presentation is different than if it
1008       * does not have a next sibling
1009       *
1010       * @param {int} depth the depth of the ancestor.
1011       * @return {string} the css class for the spacer
1012       */
1013      getDepthStyle: function(depth) {
1014          return (this.getAncestor(depth).nextSibling) ?
1015              "ygtvdepthcell" : "ygtvblankdepthcell";
1016      },
1017  
1018      /**
1019       * Get the markup for the node.  This is designed to be overrided so that we can
1020       * support different types of nodes.
1021       *
1022       * @return {string} the html for this node
1023       */
1024      getNodeHtml: function() {
1025          return "";
1026      }
1027  
1028  };
1029  
1030  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1031  
1032  /**
1033   * @class A custom YAHOO.widget.Node that handles the unique nature of
1034   * the virtual, presentationless root node.
1035   *
1036   * @extends YAHOO.widget.Node
1037   * @constructor
1038   */
1039  YAHOO.widget.RootNode = function(oTree) {
1040      // Initialize the node with null params.  The root node is a
1041      // special case where the node has no presentation.  So we have
1042      // to alter the standard properties a bit.
1043      this.init(null, null, true);
1044  
1045      /**
1046       * For the root node, we get the tree reference from as a param
1047       * to the constructor instead of from the parent element.
1048       *
1049       * @type YAHOO.widget.TreeView
1050       */
1051      this.tree = oTree;
1052  };
1053  YAHOO.widget.RootNode.prototype = new YAHOO.widget.Node();
1054  
1055  // overrides YAHOO.widget.Node
1056  YAHOO.widget.RootNode.prototype.getNodeHtml = function() {
1057      return "";
1058  };
1059  
1060  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1061  
1062  /**
1063   * @class The default node presentation.  The first parameter should be
1064   * either a string that will be used as the node's label, or an object
1065   * that has a string propery called label.  By default, the clicking the
1066   * label will toggle the expanded/collapsed state of the node.  By
1067   * changing the href property of the instance, this behavior can be
1068   * changed so that the label will go to the specified href.
1069   *
1070   * @extends YAHOO.widget.Node
1071   * @constructor
1072   * @param oData {object} a string or object containing the data that will
1073   * be used to render this node
1074   * @param oParent {YAHOO.widget.Node} this node's parent node
1075   * @param expanded {boolean} the initial expanded/collapsed state
1076   */
1077  YAHOO.widget.TextNode = function(oData, oParent, expanded) {
1078      if (oParent) {
1079          this.init(oData, oParent, expanded);
1080          this.setUpLabel(oData);
1081      }
1082  };
1083  
1084  YAHOO.widget.TextNode.prototype = new YAHOO.widget.Node();
1085  
1086  /**
1087   * The CSS class for the label href.  Defaults to ygtvlabel, but can be
1088   * overridden to provide a custom presentation for a specific node.
1089   *
1090   * @type string
1091   */
1092  YAHOO.widget.TextNode.prototype.labelStyle = "ygtvlabel";
1093  
1094  /**
1095   * The derived element id of the label for this node
1096   *
1097   * @type string
1098   */
1099  YAHOO.widget.TextNode.prototype.labelElId = null;
1100  
1101  /**
1102   * The text for the label.  It is assumed that the oData parameter will
1103   * either be a string that will be used as the label, or an object that
1104   * has a property called "label" that we will use.
1105   *
1106   * @type string
1107   */
1108  YAHOO.widget.TextNode.prototype.label = null;
1109  
1110  /**
1111   * Sets up the node label
1112   *
1113   * @param oData string containing the label, or an object with a label property
1114   */
1115  YAHOO.widget.TextNode.prototype.setUpLabel = function(oData) {
1116      if (typeof oData == "string") {
1117          oData = { label: oData };
1118      }
1119      this.label = oData.label;
1120  
1121      // update the link
1122      if (oData.href) {
1123          this.href = oData.href;
1124      }
1125  
1126      // set the target
1127      if (oData.target) {
1128          this.target = oData.target;
1129      }
1130  
1131      this.labelElId = "ygtvlabelel" + this.index;
1132  };
1133  
1134  /**
1135   * Returns the label element
1136   *
1137   * @return {object} the element
1138   */
1139  YAHOO.widget.TextNode.prototype.getLabelEl = function() {
1140      return document.getElementById(this.labelElId);
1141  };
1142  
1143  // overrides YAHOO.widget.Node
1144  YAHOO.widget.TextNode.prototype.getNodeHtml = function() {
1145      var sb = new Array();
1146  
1147      sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
1148      sb[sb.length] = '<tr>';
1149  
1150      for (i=0;i<this.depth;++i) {
1151          // sb[sb.length] = '<td class="ygtvdepthcell">&nbsp;</td>';
1152          sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&nbsp;</td>';
1153      }
1154  
1155      var getNode = 'YAHOO.widget.TreeView.getNode(\'' +
1156                      this.tree.id + '\',' + this.index + ')';
1157  
1158      sb[sb.length] = '<td';
1159      // sb[sb.length] = ' onselectstart="return false"';
1160      sb[sb.length] = ' id="' + this.getToggleElId() + '"';
1161      sb[sb.length] = ' class="' + this.getStyle() + '"';
1162      if (this.hasChildren(true)) {
1163          sb[sb.length] = ' onmouseover="this.className=';
1164          sb[sb.length] = getNode + '.getHoverStyle()"';
1165          sb[sb.length] = ' onmouseout="this.className=';
1166          sb[sb.length] = getNode + '.getStyle()"';
1167      }
1168      sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">&nbsp;';
1169      sb[sb.length] = '</td>';
1170      sb[sb.length] = '<td>';
1171      sb[sb.length] = '<a';
1172      sb[sb.length] = ' id="' + this.labelElId + '"';
1173      sb[sb.length] = ' class="' + this.labelStyle + '"';
1174      sb[sb.length] = ' href="' + this.href + '"';
1175      sb[sb.length] = ' target="' + this.target + '"';
1176      if (this.hasChildren(true)) {
1177          sb[sb.length] = ' onmouseover="document.getElementById(\'';
1178          sb[sb.length] = this.getToggleElId() + '\').className=';
1179          sb[sb.length] = getNode + '.getHoverStyle()"';
1180          sb[sb.length] = ' onmouseout="document.getElementById(\'';
1181          sb[sb.length] = this.getToggleElId() + '\').className=';
1182          sb[sb.length] = getNode + '.getStyle()"';
1183      }
1184      sb[sb.length] = ' >';
1185      sb[sb.length] = this.label;
1186      sb[sb.length] = '</a>';
1187      sb[sb.length] = '</td>';
1188      sb[sb.length] = '</tr>';
1189      sb[sb.length] = '</table>';
1190  
1191      return sb.join("");
1192  };
1193  
1194  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1195  
1196  /**
1197   * @class menu-specific implementation that differs in that only one sibling
1198   * can be expanded at a time.
1199   * @extends YAHOO.widget.TextNode
1200   * @constructor
1201   */
1202  YAHOO.widget.MenuNode = function(oData, oParent, expanded) {
1203      if (oParent) {
1204          this.init(oData, oParent, expanded);
1205          this.setUpLabel(oData);
1206      }
1207  
1208      // Menus usually allow only one branch to be open at a time.
1209      this.multiExpand = false;
1210  
1211  };
1212  
1213  YAHOO.widget.MenuNode.prototype = new YAHOO.widget.TextNode();
1214  
1215  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1216  
1217  /**
1218   * @class This implementation takes either a string or object for the
1219   * oData argument.  If is it a string, we will use it for the display
1220   * of this node (and it can contain any html code).  If the parameter
1221   * is an object, we look for a parameter called "html" that will be
1222   * used for this node's display.
1223   *
1224   * @extends YAHOO.widget.Node
1225   * @constructor
1226   * @param oData {object} a string or object containing the data that will
1227   * be used to render this node
1228   * @param oParent {YAHOO.widget.Node} this node's parent node
1229   * @param expanded {boolean} the initial expanded/collapsed state
1230   * @param hasIcon {boolean} specifies whether or not leaf nodes should
1231   * have an icon
1232   */
1233  YAHOO.widget.HTMLNode = function(oData, oParent, expanded, hasIcon) {
1234      if (oParent) {
1235          this.init(oData, oParent, expanded);
1236          this.initContent(oData, hasIcon);
1237      }
1238  };
1239  
1240  YAHOO.widget.HTMLNode.prototype = new YAHOO.widget.Node();
1241  
1242  /**
1243   * The CSS class for the label href.  Defaults to ygtvlabel, but can be
1244   * overridden to provide a custom presentation for a specific node.
1245   *
1246   * @type string
1247   */
1248  YAHOO.widget.HTMLNode.prototype.contentStyle = "ygtvhtml";
1249  
1250  /**
1251   * The generated id that will contain the data passed in by the implementer.
1252   *
1253   * @type string
1254   */
1255  YAHOO.widget.HTMLNode.prototype.contentElId = null;
1256  
1257  /**
1258   * The HTML content to use for this node's display
1259   *
1260   * @type string
1261   */
1262  YAHOO.widget.HTMLNode.prototype.content = null;
1263  
1264  /**
1265   * Sets up the node label
1266   *
1267   * @param {object} html string or object containing a html field
1268   * @param {boolean} hasIcon determines if the node will be rendered with an
1269   * icon or not
1270   */
1271  YAHOO.widget.HTMLNode.prototype.initContent = function(oData, hasIcon) {
1272      if (typeof oData == "string") {
1273          oData = { html: oData };
1274      }
1275  
1276      this.html = oData.html;
1277      this.contentElId = "ygtvcontentel" + this.index;
1278      this.hasIcon = hasIcon;
1279  };
1280  
1281  /**
1282   * Returns the outer html element for this node's content
1283   *
1284   * @return {Object} the element
1285   */
1286  YAHOO.widget.HTMLNode.prototype.getContentEl = function() {
1287      return document.getElementById(this.contentElId);
1288  };
1289  
1290  // overrides YAHOO.widget.Node
1291  YAHOO.widget.HTMLNode.prototype.getNodeHtml = function() {
1292      var sb = new Array();
1293  
1294      sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
1295      sb[sb.length] = '<tr>';
1296  
1297      for (i=0;i<this.depth;++i) {
1298          sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '">&nbsp;</td>';
1299      }
1300  
1301      if (this.hasIcon) {
1302          sb[sb.length] = '<td';
1303          sb[sb.length] = ' id="' + this.getToggleElId() + '"';
1304          sb[sb.length] = ' class="' + this.getStyle() + '"';
1305          sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">&nbsp;';
1306          if (this.hasChildren(true)) {
1307              sb[sb.length] = ' onmouseover="this.className=';
1308              sb[sb.length] = 'YAHOO.widget.TreeView.getNode(\'';
1309              sb[sb.length] = this.tree.id + '\',' + this.index +  ').getHoverStyle()"';
1310              sb[sb.length] = ' onmouseout="this.className=';
1311              sb[sb.length] = 'YAHOO.widget.TreeView.getNode(\'';
1312              sb[sb.length] = this.tree.id + '\',' + this.index +  ').getStyle()"';
1313          }
1314          sb[sb.length] = '</td>';
1315      }
1316  
1317      sb[sb.length] = '<td';
1318      sb[sb.length] = ' id="' + this.contentElId + '"';
1319      sb[sb.length] = ' class="' + this.contentStyle + '"';
1320      sb[sb.length] = ' >';
1321      sb[sb.length] = this.html;
1322      sb[sb.length] = '</td>';
1323      sb[sb.length] = '</tr>';
1324      sb[sb.length] = '</table>';
1325  
1326      return sb.join("");
1327  };
1328  
1329  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1330  
1331  /**
1332   * Static factory class for tree view expand/collapse animations
1333   */
1334  YAHOO.widget.TVAnim = new function() {
1335      /**
1336       * Constant for the fade in animation
1337       *
1338       * @type string
1339       */
1340      this.FADE_IN  = "YAHOO.widget.TVFadeIn";
1341  
1342      /**
1343       * Constant for the fade out animation
1344       *
1345       * @type string
1346       */
1347      this.FADE_OUT = "YAHOO.widget.TVFadeOut";
1348  
1349      /**
1350       * Returns a ygAnim instance of the given type
1351       *
1352       * @param type {string} the type of animation
1353       * @param el {HTMLElement} the element to element (probably the children div)
1354       * @param callback {function} function to invoke when the animation is done.
1355       * @return {ygAnim} the animation instance
1356       */
1357      this.getAnim = function(type, el, callback) {
1358          switch (type) {
1359              case this.FADE_IN:    return new YAHOO.widget.TVFadeIn(el, callback);
1360              case this.FADE_OUT:    return new YAHOO.widget.TVFadeOut(el, callback);
1361              default:            return null;
1362          }
1363      };
1364  
1365      /**
1366       * Returns true if the specified animation class is available
1367       *
1368       * @param type {string} the type of animation
1369       * @return {boolean} true if valid, false if not
1370       */
1371      this.isValid = function(type) {
1372          return ( "undefined" != eval("typeof " + type) );
1373      };
1374  };
1375  
1376  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1377  
1378  /**
1379   * 1/2 second fade-in
1380   *
1381   * @constructor
1382   * @param el {HTMLElement} the element to animate
1383   * @param callback {function} function to invoke when the animation is finished
1384   */
1385  YAHOO.widget.TVFadeIn = function(el, callback) {
1386      /**
1387       * The animation dom ref
1388       */
1389      this.el = el;
1390  
1391      /**
1392       * the callback to invoke when the animation is complete
1393       *
1394       * @type function
1395       */
1396      this.callback = callback;
1397  
1398      /**
1399       * @private
1400       */
1401  };
1402  
1403  /**
1404   * Performs the animation
1405   */
1406  YAHOO.widget.TVFadeIn.prototype = {
1407      animate: function() {
1408          var tvanim = this;
1409  
1410          var s = this.el.style;
1411          s.opacity = 0.1;
1412          s.filter = "alpha(opacity=10)";
1413          s.display = "";
1414  
1415          // var dur = ( navigator.userAgent.match(/msie/gi) ) ? 0.05 : 0.4;
1416          var dur = 0.4;
1417          // var a = new ygAnim_Fade(this.el, dur, 1);
1418          // a.setStart(0.1);
1419          // a.onComplete = function() { tvanim.onComplete(); };
1420  
1421          // var a = new YAHOO.util.Anim(this.el, 'opacity', 0.1, 1);
1422          var a = new YAHOO.util.Anim(this.el, {opacity: {from: 0.1, to: 1, unit:""}}, dur);
1423          a.onComplete.subscribe( function() { tvanim.onComplete(); } );
1424          a.animate();
1425      },
1426  
1427      /**
1428       * Clean up and invoke callback
1429       */
1430      onComplete: function() {
1431          this.callback();
1432      }
1433  };
1434  
1435  /* Copyright (c) 2006 Yahoo! Inc. All rights reserved. */
1436  
1437  /**
1438   * 1/2 second fade out
1439   *
1440   * @constructor
1441   * @param el {HTMLElement} the element to animate
1442   * @param callback {Function} function to invoke when the animation is finished
1443   */
1444  YAHOO.widget.TVFadeOut = function(el, callback) {
1445      /**
1446       * The animation dom ref
1447       */
1448      this.el = el;
1449  
1450      /**
1451       * the callback to invoke when the animation is complete
1452       *
1453       * @type function
1454       */
1455      this.callback = callback;
1456  
1457      /**
1458       * @private
1459       */
1460  };
1461  
1462  /**
1463   * Performs the animation
1464   */
1465  YAHOO.widget.TVFadeOut.prototype = {
1466      animate: function() {
1467          var tvanim = this;
1468          // var dur = ( navigator.userAgent.match(/msie/gi) ) ? 0.05 : 0.4;
1469          var dur = 0.4;
1470          // var a = new ygAnim_Fade(this.el, dur, 0.1);
1471          // a.onComplete = function() { tvanim.onComplete(); };
1472  
1473          // var a = new YAHOO.util.Anim(this.el, 'opacity', 1, 0.1);
1474          var a = new YAHOO.util.Anim(this.el, {opacity: {from: 1, to: 0.1, unit:""}}, dur);
1475          a.onComplete.subscribe( function() { tvanim.onComplete(); } );
1476          a.animate();
1477      },
1478  
1479      /**
1480       * Clean up and invoke callback
1481       */
1482      onComplete: function() {
1483          var s = this.el.style;
1484          s.display = "none";
1485          // s.opacity = 1;
1486          s.filter = "alpha(opacity=100)";
1487          this.callback();
1488      }
1489  };
1490  


Généré le : Sat Nov 24 09:00:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics