Developer Network Home - Help

YUI 2: TreeView

YUI 2: TreeView

The YUI TreeView Control provides a rich, compact visual presentation of hierarchical node data. Support is provided for several common node types, for the association of custom metadata with each node, and for the dynamic loading of node data (via in-page data or via XMLHttpRequest using Connection Manager) to navigate large datasets with a small initial payload.

Upgrade Notes

Users new to TreeView can skip this section and proceed directly to the Getting Started section. Implementers who are upgrading from previous versions should not find any compatibility issues. All published public interfaces and general behavior were preserved. The following are the most significant changes:

  • All the individual in-line event listeners in each of the nodes were moved to the top of the tree and handled through event delegation.
  • A destroy() method has been added to delete the tree and detach all the event listeners.
  • TreeViews can now be built from existing markup or from an object literal provided as the second argument to the constructor.
  • The definition of a tree or any branch of it can now be saved and later used to rebuild the tree.
  • All public properties of a Node can now be set upon instancing by providing an object literal in the first argument with same-name properties. This replaces the optional third (expanded) and following arguments (hasIcon) which, though deprecated, have been preserved for backward compatibility.
  • Nodes can now receive the focus and the node will be highlighted accordingly.
  • New events were added: enterKeyPressed, clickEvent and dblClickEvent.
  • Event labelClick is deprecated, though kept for compatibility. Use clickEvent instead.
  • TreeView now responds to keys: arrow keys, home and end will move the focus, plus and minus will expand and collapse a branch and coupled with the Shift key they will expand or collapse the whole tree and Enter will toggle the node or navigate if the node with the focus has a value for href.
  • The Enter key will fire the event enterKeyPressed.
  • Method draw() is now deprecated (though preserved) in favor of render().
  • Method getNodeCount() now provides the actual number of nodes.
  • Nodes have a class ygtvdepth0 where the last digit(s) signal the depth.
  • TextNodes with the href property set will be built with the label enclosed in an anchor <a> element, others will simply be enclosed in span <span> elements, thus allowing different styles to be set on each.
  • TreeView now supports in-line editing:
    • Node method editNode opens up the label editor
    • TreeView method onEventEditNode has been provided to listen to either clickEvent, dblClickEvent or enterKeyPressed to pop up the label editor
    • Node property editable enables label editing for a specific node.
    • A single-line text editor has been added for TextNode (and its descendant, MenuNode).
    • A new node type, DateNode, is included which derives from TextNode and allows date editing via YUI's Calendar widget. If Calendar is not included, it will fall back to the plain single-line text editor.
    • No editor has been provided for HTMLNodes.
    • Editing for new node types can be provided (such as it was for DateNode) by overriding methods: fillEditorContainer and saveEditorValue. Visual customization of the editor box is provided by the ygtv-edit-XxxxNode class where XxxxNode is the name of the Node object (DateNode, TextNode, etc.)

new for 2.7.0

  • Fixed several bugs in the previous version, see the README file for more details
  • HTML markup may contain an attribute yuiConfig which can contain a JSON encoded object literal with values for Node properties that will override those implied in the markup
  • Method "focus" can now be called safely from code and will expand the branch where the focused item is
  • The TreeView now has a validator property that can take a function to validate and/or convert the new value just entered and reject it if wrong
  • Nodes can be highlighted and optionally have that state propagated both up to parent nodes and down along its branch

Getting Started

To use the TreeView control include the following source files in your web page:

  1. <!-- Required CSS -->
  2. <link type="text/css" rel="stylesheet" href="https://yui-s.yahooapis.com/2.9.0/build/treeview/assets/skins/sam/treeview.css">
  3. <!-- Optional CSS for for date editing with Calendar-->
  4. <link type="text/css" rel="stylesheet" href="https://yui-s.yahooapis.com/2.9.0/build/calendar/assets/skins/sam/calendar.css">
  5.  
  6. <!-- Dependency source file -->
  7. <script src="https://yui-s.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js" ></script>
  8. <!-- Optional dependency source file -->
  9. <script src="https://yui-s.yahooapis.com/2.9.0/build/animation/animation-min.js" type="text/javascript"></script>
  10. <!-- Optional dependency source file for date editing with Calendar-->
  11. <script src="https://yui-s.yahooapis.com/2.9.0/build/calendar/calendar-min.js" ></script>
  12. <!-- Optional dependency source file to decode contents of yuiConfig markup attribute-->
  13. <script src="https://yui-s.yahooapis.com/2.9.0/build/json/json-min.js" ></script>
  14.  
  15. <!-- TreeView source file -->
  16. <script src="https://yui-s.yahooapis.com/2.9.0/build/treeview/treeview-min.js" ></script>
  17.  
<!-- Required CSS -->
<link type="text/css" rel="stylesheet" href="https://yui-s.yahooapis.com/2.9.0/build/treeview/assets/skins/sam/treeview.css">
<!-- Optional CSS for for date editing with Calendar-->
<link type="text/css" rel="stylesheet" href="https://yui-s.yahooapis.com/2.9.0/build/calendar/assets/skins/sam/calendar.css">
 
<!-- Dependency source file --> 
<script src="https://yui-s.yahooapis.com/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js" ></script>
<!-- Optional dependency source file --> 
<script src="https://yui-s.yahooapis.com/2.9.0/build/animation/animation-min.js" type="text/javascript"></script>
<!-- Optional dependency source file for date editing with Calendar--> 
<script src="https://yui-s.yahooapis.com/2.9.0/build/calendar/calendar-min.js" ></script>
<!-- Optional dependency source file to decode contents of yuiConfig markup attribute--> 
<script src="https://yui-s.yahooapis.com/2.9.0/build/json/json-min.js" ></script>
 
<!-- TreeView source file --> 
<script src="https://yui-s.yahooapis.com/2.9.0/build/treeview/treeview-min.js" ></script>
 
Next, apply the yui-skin-sam class name to an element that is a parent of the element in which the TreeView Control lives. You can usually accomplish this simply by putting the class on the <body> tag:

  1. <body class="yui-skin-sam">
  2.  
<body class="yui-skin-sam">
 

For more information on skinning YUI components and making use of default skins, see our Understanding YUI Skins article here on the website.

YUI dependency configurator.

YUI Dependency Configurator:

Instead of copying and pasting the filepaths above, try letting the YUI dependency Configurator determine the optimal file list for your desired components; the Configurator uses YUI Loader to write out the full HTML for including the precise files you need for your implementation.

Note: If you wish to include this component via the YUI Loader, its module name is treeview. (Click here for the full list of module names for YUI Loader.)

Where these files come from: The files included using the text above will be served from Yahoo! servers; see "Serving YUI Files from Yahoo!" for important information about this service. JavaScript files are minified, meaning that comments and white space have been removed to make them more efficient to download. To use the full, commented versions or the -debug versions of YUI JavaScript files, please download the library distribution and host the files on your own server.

Order matters: As is the case generally with JavaScript and CSS, order matters; these files should be included in the order specified above. If you include files in the wrong order, errors may result.

The TreeView control is defined by YAHOO.widget.TreeView. The nodes of the tree are defined by the base class YAHOO.widget.Node and various subclasses.

Creating the Tree

Create a tree by instantiating TreeView with the ID of the element in which you want to draw the tree:

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. }
  5.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
}
 

You can use an element reference instead of an ID:

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView(document.getElementById("treeDiv1"));
  4. }
  5.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView(document.getElementById("treeDiv1"));
}
 

If the element that will contain the tree already has a series of nested ordered or unordered lists, the tree will be built using that information. The format for such existing markup should be:

  1. <div id="treeDiv1">
  2. <ul>
  3. <li class="expanded">List 0
  4. <ul>
  5. <li class="expanded">List 0-0
  6. <ul>
  7. <li>item 0-0-0</li>
  8. <li><a target="_new" href="www.elsewhere.com" title="go elsewhere">elsewhere</a></li>
  9. </ul>
  10. </li>
  11. </ul>
  12. </li>
  13. <li>List 1
  14. <ul>
  15. <li>List 1-0
  16. <ul>
  17. <li yuiConfig='{"type":"DateNode","editable":true}'>02/01/2009</li>
  18. <li><span>item <strong>1-1-0</strong></span></li>
  19. </ul>
  20. </li>
  21. </ul>
  22. </li>
  23. </ul>
  24. </div>
  25.  
<div id="treeDiv1">
    <ul>
        <li class="expanded">List 0
            <ul>
                <li class="expanded">List 0-0
                    <ul>
                        <li>item 0-0-0</li>
                        <li><a target="_new" href="www.elsewhere.com" title="go elsewhere">elsewhere</a></li>
                    </ul>
                </li>
            </ul>
        </li>
        <li>List 1
            <ul>
                <li>List 1-0
                    <ul>
                        <li yuiConfig='{"type":"DateNode","editable":true}'>02/01/2009</li>
                        <li><span>item <strong>1-1-0</strong></span></li>
                    </ul>
                </li>
            </ul>
        </li>
    </ul>
</div>
 

TreeView will create TextNodes from text contained in list-item <li> elements and from <a> anchor elements. It will create child nodes from <ul> or <ol> elements and HTMLNodes from any other markup found. The first branch of the tree will be expanded. The first item of List 1-0 would nornally be a plain TextNode, but by using the yuiConfig attribute, it can be changed to a DateNode and made editable. Decoding the yuiConfig attribute requires the JSON utility to be loaded.

Though the user will see item 1-1-0 as a single text, in the DOM it will be represented as three elements, two text elements, the second enclosed in a <strong> element. Since the markup parser can take only the first element of each list-item, the item has to be enclosed in a single <span> container. The item will be turned into an HTMLNode.

The constructor also accepts a second argument, an array containing the tree definition. If such a tree definition is provided, no markup will be parsed. The array can contain any number of string or object literals, each a definition for a node. TextNodes will be created from string literals. Each object node definition should contain a type property that can be any of the short-names (case-insensitive) "text", "html" or "menu", it can be the full name of an object definition in the YAHOO.widget object that inherits from YAHOO.widget.Node, such as "TextNode" or "HTMLNode" of a full reference to an object that inherits from YAHOO.widget.Node.

The definition can have an optional children property containing an array of further node definitions with the same format.

All other properties of each definition, if its name matches that of an existing public property, will have its value assigned to it. It is to be expected that node definitions of type "text" would have a label property and those of type "html" an html property. All other extra custom properties will be assigned to the data property of the node.

This tree definition object is of the same format as would be obtained from calling method getTreeDefinition(), thus, by calling this method, the structure of the tree can be preserved and regenerated later. Any branch of the tree can be preserved by calling method getNodeDefinition() on any Node. In fact, getTreeDefinition() simply calls getNodeDefinition() on the root node.

Methods buildTreeFromMarkup and buildTreeFromObject which are the ones providing this functionality, can actually be called at any time after the TreeView instance has been created

The following code would produce the same tree as the markup in the above example

  1. var tree = new YAHOO.widget.TreeView("treeDiv1", [
  2. {
  3. type: "text",
  4. label: "List 0",
  5. expanded: true,
  6. children: [
  7. {
  8. type: "text",
  9. label: "List 0-0",
  10. expanded: true,
  11. children: [
  12. "item 0-0-0",
  13. {
  14. type: "text",
  15. target: "_new",
  16. href: "www.elsewhere.com",
  17. title: "go elsewhere",
  18. label: "elsewhere"
  19. }
  20. }
  21. ]
  22. },
  23. {
  24. type: "text",
  25. label: "List 1",
  26. children: [
  27. {
  28. type: "text",
  29. label: "List 1-0",
  30. children: [
  31. {
  32. type: "DateNode",
  33. label: "02/01/2009",
  34. "editable": true
  35. },
  36. {
  37. type: "text",
  38. label: "item <strong>1-1-0</strong>"
  39. }
  40. ]
  41. }
  42. ]}
  43. ]}
  44. ]);
  45. tree.render();
  46.  
var tree = new YAHOO.widget.TreeView("treeDiv1", [ 
    {
        type: "text",
        label: "List 0",
        expanded: true,
            children: [
                    {
                        type: "text",
                        label: "List 0-0",
                        expanded: true,
                        children: [
                            "item 0-0-0",
                            {
                                type: "text",
                                target: "_new",
                                href: "www.elsewhere.com",
                                title: "go elsewhere",
                                label: "elsewhere"
                            }
                    }
            ]
    },
    {
        type: "text",
        label: "List 1",
        children: [
            {
                type: "text", 
                label: "List 1-0", 
                children: [
                    {
                        type: "DateNode",
                        label: "02/01/2009",
                        "editable": true
                    },
                    {
                        type: "text",
                        label: "item <strong>1-1-0</strong>"
                    }
                ]
            }
        ]}
    ]}
]);
tree.render();
 

The last item 1-1-0, which the HTML parser would have created as an HTMLNode node, unable as it is to tell appart text with simple formatting from more complex HTML, is created as a TextNode in this example, and the <span> was omitted since it was there for the sake of the parser.

Once the tree object has been created you can begin to add its nodes, if not already done via existing markup or object literal. The HTML code for the tree is not inserted into the host element until you call the render method, so any nodes you add prior to calling the render method will be present when it is rendered. (the draw method, now deprecated, has been kept for backward compatibility)

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. // if required, add nodes here
  5. tree.render();
  6. }
  7.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
    // if required, add nodes here
    tree.render();
}
 

Adding Nodes

When the tree is created, a root node is generated automatically. The constructor for a new node takes the parent node as an argument. You can get a reference to the tree's root node to build the first level of the tree with the getRoot() method:

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. var root = tree.getRoot();
  5. var tmpNode = new YAHOO.widget.TextNode("mylabel", root, false);
  6.  
  7. tree.render();
  8. }
  9.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
    var root = tree.getRoot();
    var tmpNode = new YAHOO.widget.TextNode("mylabel", root, false);
 
    tree.render();
}
 

The above example appends a text node to the root of the tree with "mylabel" as the label. The last, now deprecated, parameter is a boolean that indicates whether or not the new node should be expanded when the HTML for the tree is generated. The same node can be created with the following instruction:

  1. var tmpNode = new YAHOO.widget.TextNode({
  2. label: "mylabel",
  3. expanded: false
  4. }, root);
  5.  
var tmpNode = new YAHOO.widget.TextNode({
    label: "mylabel",
    expanded: false
}, root);
 

Any public property of the node can be set in the same way which is the preferred way instead of using the optional constructor arguments. (see also: Custom Properties in nodes below)

The new node you created (tmpNode) can now be used as the parent for other nodes.

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. var root = tree.getRoot();
  5. var tmpNode = new YAHOO.widget.TextNode({
  6. label: "mylabel1",
  7. expanded: false
  8. }, root);
  9. var tmpNode2 = new YAHOO.widget.TextNode({
  10. label: "mylabel1-1",
  11. expanded: false
  12. }, tmpNode);
  13.  
  14. tree.render();
  15. }
  16.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
    var root = tree.getRoot();
    var tmpNode = new YAHOO.widget.TextNode({
        label: "mylabel1",
        expanded: false
    }, root);
    var tmpNode2 = new YAHOO.widget.TextNode({
        label: "mylabel1-1", 
        expanded: false
    }, tmpNode);
 
   tree.render();
}
 

Removing Nodes

Nodes can be removed with the removeNode method. The removed node's descendants are also deleted.

  1. tree.removeNode(nodeToRemove);
  2.  
tree.removeNode(nodeToRemove);
 

The TreeView instance's popNode method can be used to remove a node from a tree while preserving the node's child collection. You can also use the Node object's appendTo, insertBefore, and insertAfter methods to move the popped node to a new location within the Tree.

  1. // remove the node and insert it before another node
  2. tree.popNode(nodeToPop);
  3. nodeToPop.insertBefore(anotherNode);
  4. anotherNode.parent.refresh();
  5.  
  6. // remove the node and append it to another node
  7. tree.popNode(nodeToPop);
  8. nodeToPop.appendTo(anotherNode);
  9. anotherNode.refresh();
  10.  
// remove the node and insert it before another node
tree.popNode(nodeToPop);
nodeToPop.insertBefore(anotherNode);
anotherNode.parent.refresh();
 
// remove the node and append it to another node
tree.popNode(nodeToPop);
nodeToPop.appendTo(anotherNode);
anotherNode.refresh();
 

See the examples below in Using TreeView or the API Documentation for more details.

Using TreeView

This section describes several common uses and customizations of TreeView and contains these sections:

Setting Up your Style Definitions

The TreeView component makes use of several CSS classes to style the tree. You can either use the CSS provided in the download source, or you can create your own. If you create your own, you'll need to follow TreeView's naming conventions for its CSS classes.

Icon styles:

  • ygtvtn: First or middle sibling, no children
  • ygtvtm: First or middle sibling, collapsible
  • ygtvtmh: First or middle sibling, collapsible, hover state
  • ygtvtp: First or middle sibling, expandable
  • ygtvtph: First or middle sibling, expandable, hover state
  • ygtvln: Last sibling, no children
  • ygtvlm: Last sibling, collapsible
  • ygtvlmh: Last sibling, collapsible, hover state
  • ygtvlp: Last sibling, expandable
  • ygtvlph: Last sibling, expandable, hover state
  • ygtloading: Loading dynamic data indicator

Depth spacer styles:

  • ygtvdepthN: to all nodes, where N is the depth of the node
  • ygtvdepthcell: Node's ancestor at the current depth has a next sibling
  • ygtvblankdepthcell: Node's ancestor at the current depth does not have a next sibling

Container styles:

  • ygtvitem: The node's container element
  • ygtvchildren: The container around each node's collection of children
  • ygtvcontent: The container around each node's content (label, anchor, HTML)

Text styles:

  • ygtvlabel[link,visited,hover]: The style of the text label/href when using TextNode
  • Due to a bug in the font smoothing algorithm in Internet Explorer, these styles define a white background for the labels thus, TreeViews have to be drawn over a white background or the background-color definition of these styles adjusted to match your background.

Focused/highlighted elements

  • ygtvfocus: The style added to any of the above to highlight the node having the focus
  • ygtv-highlight0: The style of a node with no highlight
  • ygtv-highlight1: The style of a highlighted node
  • ygtv-highlight2: The style of a node that have some but not all children hightlighted

Label editor

  • ygtvok: The style of the Ok button
  • ygtvcancel: The style of the Cancel button
  • ygtv-label-editor: The generic style of the popup window
  • ygtv-edit-XxxxNode: The style of the popup window for each specific node type (i.e.: ygtv-edit-TextNode).

You can review the current CSS definitions for TreeView by looking at the CSS file that accompanies TreeView in the YUI download or by reviewing the current production CSS:

Multiple trees with different styles

You can configure multiple different presentation styles for multiple trees on the same page by defining the additional styles using id selectors on the element containing the tree. An example of this technique is provided.

The built-in CSS definitions for TreeView do not support skinning (except for highlighting as noted below). The styles will be applied regardless of whether there is a skin definition (yui-skin-sam) or not. If two or more style sheets are loaded, the last one will override the rest. Providing for skinning at this point would break existing implementations with no skin selector defined. Should skinning be required, implementors might take the non-minified treeview-skin.css and prefix all selectors with the chosen skin name (i.e.: .ygtvtm would turn into .yui-skin-sam .ygtvtm).

Keeping Custom Properties in Node References

The TreeView control accepts objects as the first argument of the node constructor. This provides an opportunity for setting additional properties and for storing metadata about the node in its object. TreeView will store all Node properties it doesn't know about in the data member of the node object. For each property, it will first check if there is an existing property by that name and if so it will assign it its value, if not, it will go into the object in the data property. This feature can be useful when handling events passed to you by the TreeView Control (See Responding to Events, below, for an example of this use).

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. var root = tree.getRoot();
  5. var myobj = {
  6. label: "mylabel1",
  7. myNodeId: "myid1"
  8. };
  9. var tmpNode = new YAHOO.widget.TextNode(myobj, root);
  10.  
  11. tree.render();
  12. }
  13.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
    var root = tree.getRoot();
    var myobj = {
        label: "mylabel1", 
        myNodeId: "myid1"
    };
    var tmpNode = new YAHOO.widget.TextNode(myobj, root);
 
   tree.render();
}
 

Changing the Behavior for the Label of a Text Node

By default, clicking the text label of a node expands or collapses it. You can change this behavior to a URL by using a custom object to instantiate your node and providing an href property:

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. var root = tree.getRoot();
  5. var myobj = {
  6. label: "mylabel1",
  7. href:"http://www.yahoo.com"
  8. };
  9. var tmpNode = new YAHOO.widget.TextNode(myobj, root);
  10.  
  11. tree.render();
  12. }
  13.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
    var root = tree.getRoot();
    var myobj = {
        label: "mylabel1", 
        href:"http://www.yahoo.com"
    };
    var tmpNode = new YAHOO.widget.TextNode(myobj, root);
 
    tree.render();
}
 

The HTML for such a TextNode includes a link (<a href="...">) with the contents of the href property and target and title properties, if present.

Responding to Events

The TreeView component supports event callbacks for when a node is expanded or collapsed. The callback function gets a reference to the node that was expanded/collapsed, and that callback can be used to dynamically alter the presentation of the node.

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4.  
  5. var root = tree.getRoot();
  6.  
  7. var myobj = {
  8. label: "mylabel1",
  9. myNodeId:"myid1"
  10. };
  11. var tmpNode = new YAHOO.widget.TextNode(myobj, root);
  12.  
  13. myobj = {
  14. label: "mylabel2",
  15. myNodeId: "myid2"
  16. };
  17. var tmpNode2 = new YAHOO.widget.TextNode(myobj, tmpNode);
  18.  
  19. myobj = {
  20. label: "mylabel3",
  21. myNodeId: "myid3"
  22. };
  23. var tmpNode3 = new YAHOO.widget.TextNode(myobj, tmpNode);
  24.  
  25. // Expand and collapse happen prior to the actual expand/collapse,
  26. // and can be used to cancel the operation
  27. tree.subscribe("expand", function(node) {
  28. alert(node.data.myNodeId + " was expanded");
  29. // return false; // return false to cancel the expand
  30. });
  31.  
  32. tree.subscribe("collapse", function(node) {
  33. alert(node.data.myNodeId + " was collapsed");
  34. });
  35.  
  36. // By default, trees with TextNodes will fire an event for when the label is clicked:
  37. tree.subscribe("labelClick", function(node) {
  38. alert(node.data.myNodeId + " label was clicked");
  39. });
  40.  
  41. tree.render();
  42. }
  43.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
 
    var root = tree.getRoot();
 
    var myobj = {
        label: "mylabel1", 
        myNodeId:"myid1"
    };
    var tmpNode = new YAHOO.widget.TextNode(myobj, root);
 
    myobj = {
        label: "mylabel2", 
        myNodeId: "myid2" 
    };
    var tmpNode2 = new YAHOO.widget.TextNode(myobj, tmpNode);
 
    myobj = {
        label: "mylabel3", 
        myNodeId: "myid3"
    };
    var tmpNode3 = new YAHOO.widget.TextNode(myobj, tmpNode);
 
    // Expand and collapse happen prior to the actual expand/collapse,
    // and can be used to cancel the operation
    tree.subscribe("expand", function(node) {
        alert(node.data.myNodeId + " was expanded");
        // return false; // return false to cancel the expand
    });
 
    tree.subscribe("collapse", function(node) {
        alert(node.data.myNodeId + " was collapsed");
    });
 
    // By default, trees with TextNodes will fire an event for when the label is clicked:
    tree.subscribe("labelClick", function(node) {
        alert(node.data.myNodeId + " label was clicked");
    });
 
    tree.render();
}
 

The following events have been added in this version of TreeView:

  • enterKeyPressed: Fired when the Enter key is pressed when focus is on a node.
  • clickEvent: Fired on clicking on a node, except for the toggle icon which expands or collapses the node and triggers the corresponding events.
  • dblClickEvent: As the previous, for double clicks.

Editing the contents of a Node

The contents of a node can be edited in-line. The programmer can pop-up the content editor by calling method editNode. Nodes must have an editor defined and property editable has to be true.

The editor can also be shown by listening to events clickEvent, dblClickEvent or enterKeyPressed. Method onEventEditNode has been provided so that it can be associated with any of them.

  1. tree.subscribe("dblClickEvent",tree.onEventEditNode);
  2.  
tree.subscribe("dblClickEvent",tree.onEventEditNode);
 

Node types TextNode, MenuNode and DateNode have editors defined. DateNode uses the YUI Calendar Control. A DateNode inherits from TextNode and has only the methods associated with providing the editing functionality changed so it can be used as an example for other node types requiring specific editors.

Loading your data dynamically

The TreeView component supports dynamic data loading. To enable this feature, you must provide a callback function that populates the child nodes for a given node when that node is expanded for the first time. Dynamic loading can be defined for the entire tree or for individual nodes. The callback function receives a reference to the node that is being expanded and a callback function that must be executed once you are finished creating the child nodes.

  1. var tree;
  2. function treeInit() {
  3. tree = new YAHOO.widget.TreeView("treeDiv1");
  4. tree.setDynamicLoad(loadDataForNode);
  5.  
  6. var root = tree.getRoot();
  7.  
  8. var myobj = {
  9. label: "mylabel1",
  10. id: "myid1"
  11. };
  12. var tmpNode = new YAHOO.widget.TextNode(myobj, root, false);
  13.  
  14. myobj = {
  15. label: "mylabel2",
  16. id: "myid2"
  17. };
  18. var tmpNode2 = new YAHOO.widget.TextNode(myobj, tmpNode, false);
  19.  
  20. myobj = {
  21. label: "mylabel3",
  22. id: "myid3"
  23. };
  24. var tmpNode3 = new YAHOO.widget.TextNode(myobj, tmpNode, false);
  25.  
  26. tree.render();
  27. }
  28.  
  29. function loadDataForNode(node, onCompleteCallback) {
  30. var id= node.data.id;
  31. // -- code to get your data, possibly using Connect --
  32. var tmpNode = new YAHOO.widget.TextNode(id + "label1", node, false);
  33. tmpNode = new YAHOO.widget.TextNode(id + "label2", node, false);
  34.  
  35. // Be sure to notify the TreeView component when the data load is complete
  36. onCompleteCallback();
  37. }
  38.  
var tree;
function treeInit() {
    tree = new YAHOO.widget.TreeView("treeDiv1");
    tree.setDynamicLoad(loadDataForNode);
 
    var root = tree.getRoot();
 
    var myobj = {
        label: "mylabel1", 
        id: "myid1"
    };
    var tmpNode = new YAHOO.widget.TextNode(myobj, root, false);
 
    myobj = {
        label: "mylabel2", 
        id: "myid2"
    };
    var tmpNode2 = new YAHOO.widget.TextNode(myobj, tmpNode, false);
 
    myobj = {
        label: "mylabel3", 
        id: "myid3"
    };
    var tmpNode3 = new YAHOO.widget.TextNode(myobj, tmpNode, false);
 
    tree.render();
}
 
function loadDataForNode(node, onCompleteCallback) {
    var id= node.data.id;
    // -- code to get your data, possibly using Connect --
    var tmpNode = new YAHOO.widget.TextNode(id + "label1", node, false);
    tmpNode = new YAHOO.widget.TextNode(id + "label2", node, false);
 
    // Be sure to notify the TreeView component when the data load is complete
    onCompleteCallback();
}
 

Reloading Dynamic Nodes

Dynamically loaded nodes only invoke the data loader the first time they node are expanded. The widget has a utility method that will clear out the node's collection of children and reset the node so that the next time it is expanded it will call the data loader again.

  1. tree.removeChildren(nodeToReset);
  2.  
tree.removeChildren(nodeToReset);
 

Creating Custom Node Types

The TreeView widget provides a number of node types that differ in behavior and presentation:

  • YAHOO.widget.TextNode: Provides the default tree presentation. The node label is a plain text that will expand/collapse the node by default. If the href property is set, the text will be rendered as an anchor element. It is possible to override this so the a click on the label does something else.
  • YAHOO.widget.MenuNode: Similar to TextNode, except two sibling nodes cannot be expanded at once. This lets you create navigation menus that only show the sub-destinations for the current selection.
  • YAHOO.widget.HTMLNode: Does not create the node with default behavior like TextNode does. Instead, it allows you to pass in arbritrary HTML that will be inserted into the node verbatim.
  • YAHOO.widget.DateNode: It is a plain TextNode that uses YUI's Calendar widget for label editing.

It is also possible to subclass one of these nodes to provide custom features. Check out the task list example to learn how to do this.

Highlighting Nodes

Clicking on a node will highlight it to show it has the focus, but that highlighting is not persistent as it will blur as soon as another element gets the focus. TreeView provides a persistent highlighting. The implementor has to define which UI event will produce the higlighting, by attaching the highlighting listener to the chosen event:

  1. myTreeView.subscribe("clickEvent",myTreeView.onEventToggleHighlight);
  2.  
myTreeView.subscribe("clickEvent",myTreeView.onEventToggleHighlight);
 

By default, TreeView is set for simple highlighting. Highlighting can be set off for any node by setting its enableHighlight property to false.

Any node can be set to propagate the highlighting up to its parents or down to its children. When propagating down, all child nodes will copy the highlighted state of their parent. When propagating up, each parent will check the highlight state of its children and will be fully highlighted if all its children are highlighted, not highlighted if none are and partially highlighted otherwise. Propagation will cease on nodes with enableHighlight set to false.

  1. myTreeView.setNodesProperty("propagateHighlightUp",true);
  2. myTreeView.setNodesProperty("propagateHighlightDown",true);
  3.  
myTreeView.setNodesProperty("propagateHighlightUp",true);
myTreeView.setNodesProperty("propagateHighlightDown",true);
 

The built-in CSS style sheet provides two styles of highlighting or 'skins'. To select either one, the container for the TreeView needs to add the corresponding 'skin' name, either ygtv-highlight which will highlight nodes in whilte text over blue background, suitable for simple highlighting or ygtv-checkbox, suitable for both simple and propagating highlighting. If no 'skin' is selected, the highlighting will operate but it will not be visible to the user. To set the tree to use the 'checkbox' highlighting, define the container to hold the tree thus:

  1. <div id="treeDiv1" class="ygtv-checkbox"></div>
  2.  
<div id="treeDiv1" class="ygtv-checkbox"></div>
 

Known Issues

Internet Explorer sometimes has trouble rendering deeply nested nodes (It has been reported that this problem surfaces at about 38 levels deep). A future release will have a different markup pattern that may fix this issue.

YUI on Mobile: Using TreeView Control with "A-Grade" Mobile Browsers

About this Section: YUI generally works well with mobile browsers that are based on A-Grade browser foundations. For example, Nokia's N-series phones, including the N95, use a browser based on Webkit — the same foundation shared by Apple's Safari browser, which is found on the iPhone. The fundamental challenges in developing for this emerging class of full, A-Grade-derived browsers on handheld devices are:

  • Screen size: You have a much smaller canvas;
  • Input devices: Mobile devices generally do not have mouse input, and therefore are missing some or all mouse events (like mouseover);
  • Processor power: Mobile devices have slower processors that can more easily be saturated by JavaScript and DOM interactions — and processor usage affects things like battery life in ways that don't have analogues in desktop browsers;
  • Latency: Most mobile devices have a much higher latency on the network than do terrestrially networked PCs; this can make pages with many script, css or other types of external files load much more slowly.

There are other considerations, many of them device/browser specific (for example, current versions of the iPhone's Safari browser do not support Flash). The goal of these sections on YUI User's Guides is to provide you some preliminary insights about how specific components perform on this emerging class of mobile devices. Although we have not done exhaustive testing, and although these browsers are revving quickly and present a moving target, our goal is to provide some early, provisional advice to help you get started as you contemplate how your YUI-based application will render in the mobile world.

More Information:

TreeView is functional in the target mobile browsers. However, deeply nested nodes may cause horizontal scrolling and may be a sub-optimal user experience.

Support & Community

The YUI Library and related topics are discussed on the on the YUILibrary.com forums.

Also be sure to check out YUIBlog for updates and articles about the YUI Library written by the library's developers.

Filing Bugs & Feature Requests

The YUI Library's public bug tracking and feature request repositories are located on the YUILibrary.com site. Before filing new feature requests or bug reports, please review our reporting guidelines.

Copyright © 2016 Yahoo! Inc. All rights reserved.

Privacy Policy - Copyright Policy - Job Openings