YUI Library Home

YUI Library Examples: Menu Family: Adding A Context Menu To A TreeView

Menu Family: Adding A Context Menu To A TreeView

This example demonstates how to use the ContextMenu widget to add a context menu to a YUI TreeView control. The context menu allows the user to add, edit and remove items from a TreeView instance.

Please Note: Opera users will need to do the following to use this example:

  • Opera for Windows: Hold down the control key and click with the left mouse button.
  • Opera for OS X: Hold down the command key (⌘) and click with the left mouse button.

When adding context menus to large data structures like a <table> or large list (<ol> or <ul>), it is recommended to bind a single YAHOO.widget.ContextMenu instance to the structure's root element, than to a set of its child nodes (<tr>s or <li>s). Doing so significantly improves the performance of a web page or application by reducing the number of "contextmenu" event handlers as well as the number of YAHOO.widget.ContextMenu instances in memory.

Begin by creating a TreeView instance. Next, create an object that maps HTML ids to their corresponding TextNode instances. As each TextNode instance is added to the TreeView, store a reference to it in the map.

1/*
2     Initialize the TreeView instance when the "mytreeview" <div>
3     is ready to be scripted.
4*/ 
5 
6YAHOO.util.Event.onAvailable("mytreeview"function () { 
7 
8    /*
9         Map of YAHOO.widget.TextNode instances in the 
10         TreeView instance.
11    */ 
12 
13    var oTextNodeMap = {}; 
14 
15 
16    // Creates a TextNode instance and appends it to the TreeView  
17 
18    function buildRandomTextBranch(p_oNode) { 
19 
20        var oTextNode, 
21            i; 
22 
23        if (p_oNode.depth < 6) { 
24 
25            for (i = 0; i < Math.floor(Math.random() * 4); i++) { 
26 
27                oTextNode = new YAHOO.widget.TextNode(p_oNode.label + "-" + i, p_oNode, false); 
28 
29                oTextNodeMap[oTextNode.labelElId] = oTextNode; 
30                 
31                buildRandomTextBranch(oTextNode); 
32 
33            } 
34 
35        } 
36 
37    } 
38 
39 
40    // Create a TreeView instance 
41 
42    var oTreeView = new YAHOO.widget.TreeView("mytreeview"); 
43 
44    var n, oTextNode; 
45 
46    for (n = 0; n < Math.floor((Math.random()*4) + 3); n++) { 
47 
48        oTextNode = new YAHOO.widget.TextNode("label-" + n, oTreeView.getRoot(), false); 
49         
50        /*
51             Add the TextNode instance to the map, using its
52             HTML id as the key.
53        */ 
54         
55        oTextNodeMap[oTextNode.labelElId] = oTextNode; 
56         
57        buildRandomTextBranch(oTextNode); 
58 
59    } 
60 
61    oTreeView.draw(); 
62 
63}); 
view plain | print | ?

Once the TreeView is created, instantiate a ContextMenu specifying the TreeView instance's root element as its trigger. Lastly, add a "triggerContextMenu" event handler for the ContextMenu instance that uses the "contextEventTarget" property to retrieve the TextNode instance that triggered its display. A reference to the TextNode is stored in a variable (oCurrentTextNode), so that it can be manipulated by the addNode, editNodeLabel, and deleteNode functions.

1/*
2     The YAHOO.widget.TextNode instance whose "contextmenu" 
3     DOM event triggered the display of the 
4     ContextMenu instance.
5*/ 
6 
7var oCurrentTextNode = null
8 
9 
10/*
11     Adds a new TextNode as a child of the TextNode instance 
12     that was the target of the "contextmenu" event that 
13     triggered the display of the ContextMenu instance.
14*/ 
15 
16function addNode() { 
17 
18    var sLabel = window.prompt("Enter a label for the new node: """), 
19        oChildNode; 
20 
21    if (sLabel && sLabel.length > 0) { 
22         
23        oChildNode = new YAHOO.widget.TextNode(sLabel, oCurrentTextNode, false); 
24 
25        oCurrentTextNode.refresh(); 
26        oCurrentTextNode.expand(); 
27 
28        oTextNodeMap[oChildNode.labelElId] = oChildNode; 
29 
30    } 
31 
32
33 
34 
35/*
36     Edits the label of the TextNode that was the target of the
37     "contextmenu" event that triggered the display of the 
38     ContextMenu instance.
39*/ 
40 
41function editNodeLabel() { 
42 
43    var sLabel = window.prompt("Enter a new label for this node: ", oCurrentTextNode.getLabelEl().innerHTML); 
44 
45    if (sLabel && sLabel.length > 0) { 
46         
47        oCurrentTextNode.getLabelEl().innerHTML = sLabel; 
48 
49    } 
50 
51
52 
53 
54/*
55    Deletes the TextNode that was the target of the "contextmenu"
56    event that triggered the display of the ContextMenu instance.
57*/ 
58 
59function deleteNode() { 
60 
61    delete oTextNodeMap[oCurrentTextNode.labelElId]; 
62 
63    oTreeView.removeNode(oCurrentTextNode); 
64    oTreeView.draw(); 
65 
66
67 
68 
69/*
70    "contextmenu" event handler for the element(s) that 
71    triggered the display of the ContextMenu instance - used
72    to set a reference to the TextNode instance that triggered
73    the display of the ContextMenu instance.
74*/ 
75 
76function onTriggerContextMenu(p_oEvent) { 
77 
78    var oTarget = this.contextEventTarget, 
79        Dom = YAHOO.util.Dom; 
80 
81    /*
82         Get the TextNode instance that that triggered the 
83         display of the ContextMenu instance.
84    */ 
85 
86    var oTextNode = Dom.hasClass(oTarget, "ygtvlabel") ?  
87                        oTarget : Dom.getAncestorByClassName(oTarget, "ygtvlabel"); 
88 
89    if (oTextNode) { 
90 
91        oCurrentTextNode = oTextNodeMap[oTarget.id]; 
92 
93    } 
94    else { 
95     
96        // Cancel the display of the ContextMenu instance. 
97     
98        this.cancel(); 
99         
100    } 
101 
102
103 
104 
105/*
106     Instantiate a ContextMenu:  The first argument passed to 
107     the constructor is the id of the element to be created; the 
108     second is an object literal of configuration properties.
109*/ 
110 
111var oContextMenu = new YAHOO.widget.ContextMenu("mytreecontextmenu", { 
112                                                trigger: "mytreeview"
113                                                lazyload: true,  
114                                                itemdata: [ 
115                                                    { text: "Add Child Node", onclick: { fn: addNode } }, 
116                                                    { text: "Edit Node Label", onclick: { fn: editNodeLabel } }, 
117                                                    { text: "Delete Node", onclick: { fn: deleteNode } } 
118                                                ] }); 
119 
120 
121/*
122     Subscribe to the "contextmenu" event for the element(s)
123     specified as the "trigger" for the ContextMenu instance.
124*/ 
125 
126oContextMenu.subscribe("triggerContextMenu", onTriggerContextMenu); 
view plain | print | ?

Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

Menu Family Examples:

More Menu Family Resources:

Copyright © 2009 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings