Yahoo! Developer Network Home - Help

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    /*
79         Get the TextNode instance that that triggered the 
80         display of the ContextMenu instance.
81    */ 
82 
83    var oTextNode = Dom.hasClass(oTarget, "ygtvlabel") ?  
84                        oTarget : Dom.getAncestorByClassName(oTarget, "ygtvlabel"); 
85 
86    if (oTextNode) { 
87 
88        oCurrentTextNode = oTextNodeMap[oTarget.id]; 
89 
90    } 
91    else { 
92     
93        // Cancel the display of the ContextMenu instance. 
94     
95        this.cancel(); 
96         
97    } 
98 
99
100 
101 
102/*
103     Instantiate a ContextMenu:  The first argument passed to 
104     the constructor is the id of the element to be created; the 
105     second is an object literal of configuration properties.
106*/ 
107 
108var oContextMenu = new YAHOO.widget.ContextMenu("mytreecontextmenu", { 
109                                                trigger: "mytreeview"
110                                                lazyload: true,  
111                                                itemdata: [ 
112                                                    { text: "Add Child Node", onclick: { fn: addNode } }, 
113                                                    { text: "Edit Node Label", onclick: { fn: editNodeLabel } }, 
114                                                    { text: "Delete Node", onclick: { fn: deleteNode } } 
115                                                ] }); 
116 
117 
118/*
119     Subscribe to the "contextmenu" event for the element(s)
120     specified as the "trigger" for the ContextMenu instance.
121*/ 
122 
123oContextMenu.subscribe("triggerContextMenu", onTriggerContextMenu); 
view plain | print | ?

Menu Family Examples:

More Menu Family Resources:

Copyright © 2008 Yahoo! Inc. All rights reserved.

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