3 throw "Error jqTree is not loaded.";
6 $.fn.jqTreeContextMenu = function (menuElement, callbacks) {
9 // * Make sure the useContextMenu option is set in jqTree, either complain or set it automatically
10 // * Make menu fade in/out
15 // The jQuery object of the menu div.
16 var $menuEl = menuElement;
18 // This hash holds all menu items that should be disabled for a specific node.
19 var nodeToDisabledMenuItems = {};
24 // Disable system context menu from beeing displayed.
25 $el.bind("contextmenu", function (e) {
30 // Handle the contextmenu event sent from jqTree when user clicks right mouse button.
31 $el.bind('tree.contextmenu', function (event) {
32 var x = event.click_event.pageX;
33 var y = event.click_event.pageY;
36 var menuHeight = $menuEl.height();
37 var menuWidth = $menuEl.width();
38 var windowHeight = $(window).height();
39 var windowWidth = $(window).width();
41 if (menuHeight + y + yPadding > windowHeight) {
42 // Make sure the whole menu is rendered within the viewport.
45 if (menuWidth + x + xPadding > windowWidth) {
46 // Make sure the whole menu is rendered within the viewport.
50 // Handle disabling and enabling of menu items on specific nodes.
51 if (Object.keys(nodeToDisabledMenuItems).length > 0) {
52 if (event.node.name in nodeToDisabledMenuItems) {
53 var nodeName = event.node.name;
54 var items = nodeToDisabledMenuItems[nodeName];
55 if (items.length === 0) {
56 $menuEl.find('li').addClass('disabled');
57 $menuEl.find('li > a').unbind('click');
59 $menuEl.find('li > a').each(function () {
60 $(this).closest('li').removeClass('disabled');
61 var hrefValue = $(this).attr('href');
62 var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length)
63 if ($.inArray(value, items) > -1) {
64 $(this).closest('li').addClass('disabled');
65 $(this).unbind('click');
70 $menuEl.find('li.disabled').removeClass('disabled');
74 // Must call show before we set the offset (offset can not be set on display: none elements).
77 $menuEl.offset({ left: x, top: y });
79 var dismissContextMenu = function () {
80 $(document).unbind('click.jqtreecontextmenu');
81 $el.unbind('tree.click.jqtreecontextmenu');
84 // Make it possible to dismiss context menu by clicking somewhere in the document.
85 $(document).bind('click.jqtreecontextmenu', function () {
89 // Dismiss context menu if another node in the tree is clicked.
90 $el.bind('tree.click.jqtreecontextmenu', function (e) {
94 // Make selection follow the node that was right clicked on.
95 var selectedNode = $el.tree('getSelectedNode');
96 if (selectedNode !== event.node) {
97 $el.tree('selectNode', event.node);
100 // Handle click on menu items, if it's not disabled.
101 var menuItems = $menuEl.find('li:not(.disabled) a');
102 if (menuItems.length !== 0) {
103 menuItems.unbind('click');
104 menuItems.click(function (e) {
105 e.stopImmediatePropagation();
106 dismissContextMenu();
107 var hrefAnchor = e.currentTarget.attributes.href.nodeValue;
108 var funcKey = hrefAnchor.slice(hrefAnchor.indexOf("#") + 1, hrefAnchor.length)
109 var callbackFn = callbacks[funcKey];
111 callbackFn(event.node);
118 this.disable = function () {
119 if (arguments.length === 0) {
120 // Called as: api.disable()
121 $menuEl.find('li:not(.disabled)').addClass('disabled');
122 $menuEl.find('li a').unbind('click');
123 nodeToDisabledMenuItems = {};
124 } else if (arguments.length === 1) {
125 // Called as: api.disable(['edit','remove'])
126 var items = arguments[0];
127 if (typeof items !== 'object') {
130 $menuEl.find('li > a').each(function () {
131 var hrefValue = $(this).attr('href');
132 var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length)
133 if ($.inArray(value, items) > -1) {
134 $(this).closest('li').addClass('disabled');
135 $(this).unbind('click');
138 nodeToDisabledMenuItems = {};
139 } else if (arguments.length === 2) {
140 // Called as: api.disable(nodeName, ['edit','remove'])
141 var nodeName = arguments[0];
142 var items = arguments[1];
143 nodeToDisabledMenuItems[nodeName] = items;
147 this.enable = function () {
148 if (arguments.length === 0) {
149 // Called as: api.enable()
150 $menuEl.find('li.disabled').removeClass('disabled');
151 nodeToDisabledMenuItems = {};
152 } else if (arguments.length === 1) {
153 // Called as: api.enable(['edit','remove'])
154 var items = arguments[0];
155 if (typeof items !== 'object') {
159 $menuEl.find('li > a').each(function () {
160 var hrefValue = $(this).attr('href');
161 var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length)
162 if ($.inArray(value, items) > -1) {
163 $(this).closest('li').removeClass('disabled');
167 nodeToDisabledMenuItems = {};
168 } else if (arguments.length === 2) {
169 // Called as: api.enable(nodeName, ['edit','remove'])
170 var nodeName = arguments[0];
171 var items = arguments[1];
172 if (items.length === 0) {
173 delete nodeToDisabledMenuItems[nodeName];
175 var disabledItems = nodeToDisabledMenuItems[nodeName];
176 for (var i = 0; i < items.length; i++) {
177 var idx = disabledItems.indexOf(items[i]);
179 disabledItems.splice(idx, 1);
182 if (disabledItems.length === 0) {
183 delete nodeToDisabledMenuItems[nodeName];
185 nodeToDisabledMenuItems[nodeName] = disabledItems;
188 if (Object.keys(nodeToDisabledMenuItems).length === 0) {
189 $menuEl.find('li.disabled').removeClass('disabled');