dba442c86d763488bb7060d586b775c2b46e4beb
[portal.git] / ecomp-portal-FE-os / client / src / views / functionalMenu / jqTreeContextMenu.js
1 /*-
2  * ================================================================================
3  * ECOMP Portal
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ================================================================================
19  */
20 (function ($) {
21         if (!$.fn.tree) {
22                 throw "Error jqTree is not loaded.";
23         }
24
25         $.fn.jqTreeContextMenu = function (menuElement, callbacks) {
26                 //
27                 // TODO:
28                 // * Make sure the useContextMenu option is set in jqTree, either complain or set it automatically
29                 // * Make menu fade in/out
30                 //
31                 var self = this;
32                 var $el = this;
33
34                 // The jQuery object of the menu div.
35                 var $menuEl = menuElement;
36                 
37                 // This hash holds all menu items that should be disabled for a specific node.
38                 var nodeToDisabledMenuItems = {};
39                 
40                 // Hide the menu div.
41                 $menuEl.hide();
42
43                 // Disable system context menu from beeing displayed.
44                 $el.bind("contextmenu", function (e) { 
45                         e.preventDefault();
46                         return false; 
47                 });
48
49                 // Handle the contextmenu event sent from jqTree when user clicks right mouse button.
50                 $el.bind('tree.contextmenu', function (event) {
51                         var x = event.click_event.pageX;
52                         var y = event.click_event.pageY;
53                         var yPadding = 5;
54                         var xPadding = 5;
55                         var menuHeight = $menuEl.height();
56                         var menuWidth = $menuEl.width();
57                         var windowHeight = $(window).height();
58                         var windowWidth = $(window).width();
59                         
60                         if (menuHeight + y + yPadding > windowHeight) {
61                                 // Make sure the whole menu is rendered within the viewport. 
62                                 y = y - menuHeight;
63                         }
64                         if (menuWidth + x + xPadding > windowWidth) {
65                                 // Make sure the whole menu is rendered within the viewport. 
66                                 x = x - menuWidth;
67                         }
68
69                         // Handle disabling and enabling of menu items on specific nodes.
70                         if (Object.keys(nodeToDisabledMenuItems).length > 0) {
71                                 if (event.node.name in nodeToDisabledMenuItems) {
72                                         var nodeName = event.node.name;
73                                         var items = nodeToDisabledMenuItems[nodeName];
74                                         if (items.length === 0) {
75                                                 $menuEl.find('li').addClass('disabled');
76                                                 $menuEl.find('li > a').unbind('click');
77                                         } else {
78                                                 $menuEl.find('li > a').each(function () {
79                                                         $(this).closest('li').removeClass('disabled');
80                                                         var hrefValue = $(this).attr('href');
81                                                         var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length)
82                                                         if ($.inArray(value, items) > -1) {
83                                                                 $(this).closest('li').addClass('disabled');
84                                                                 $(this).unbind('click');
85                                                         }
86                                                 });     
87                                         }
88                                 } else {
89                                         $menuEl.find('li.disabled').removeClass('disabled');
90                                 }
91                         }
92
93                         // Must call show before we set the offset (offset can not be set on display: none elements).
94                         $menuEl.show();
95
96                         $menuEl.offset({ left: x, top: y });
97
98                         var dismissContextMenu = function () {
99                                 $(document).unbind('click.jqtreecontextmenu');
100                                 $el.unbind('tree.click.jqtreecontextmenu');
101                                 $menuEl.hide();
102                         }
103                         // Make it possible to dismiss context menu by clicking somewhere in the document.
104                         $(document).bind('click.jqtreecontextmenu', function () {
105                                 dismissContextMenu();
106                         });
107
108                         // Dismiss context menu if another node in the tree is clicked.
109                         $el.bind('tree.click.jqtreecontextmenu', function (e) {
110                                 dismissContextMenu();
111                         });
112
113                         // Make selection follow the node that was right clicked on.
114                         var selectedNode = $el.tree('getSelectedNode');
115                         if (selectedNode !== event.node) {
116                                 $el.tree('selectNode', event.node);
117                         }
118
119                         // Handle click on menu items, if it's not disabled.
120                         var menuItems = $menuEl.find('li:not(.disabled) a');
121                         if (menuItems.length !== 0) {
122                                 menuItems.unbind('click');
123                                 menuItems.click(function (e) {
124                                         e.stopImmediatePropagation();
125                                         dismissContextMenu();
126                                         var hrefAnchor = e.currentTarget.attributes.href.nodeValue;
127                                         var funcKey = hrefAnchor.slice(hrefAnchor.indexOf("#") + 1, hrefAnchor.length)
128                                         var callbackFn = callbacks[funcKey];
129                                         if (callbackFn) {
130                                                 callbackFn(event.node);
131                                         }
132                                         return false;
133                                 });
134                         }
135                 });
136                 
137                 this.disable = function () {
138                         if (arguments.length === 0) {
139                                 // Called as: api.disable()
140                                 $menuEl.find('li:not(.disabled)').addClass('disabled');
141                                 $menuEl.find('li a').unbind('click');
142                                 nodeToDisabledMenuItems = {};
143                         } else if (arguments.length === 1) {
144                                 // Called as: api.disable(['edit','remove'])
145                                 var items = arguments[0];
146                                 if (typeof items !== 'object') {
147                                         return;
148                                 }
149                                 $menuEl.find('li > a').each(function () {
150                                         var hrefValue = $(this).attr('href');
151                                         var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length)
152                                         if ($.inArray(value, items) > -1) {
153                                                 $(this).closest('li').addClass('disabled');
154                                                 $(this).unbind('click');
155                                         }
156                                 });
157                                 nodeToDisabledMenuItems = {};
158                         } else if (arguments.length === 2) {
159                                 // Called as: api.disable(nodeName, ['edit','remove'])
160                                 var nodeName = arguments[0];
161                                 var items = arguments[1];
162                                 nodeToDisabledMenuItems[nodeName] = items;
163                         }
164                 };
165
166                 this.enable = function () {
167                         if (arguments.length === 0) {
168                                 // Called as: api.enable()
169                                 $menuEl.find('li.disabled').removeClass('disabled');
170                                 nodeToDisabledMenuItems = {};
171                         } else if (arguments.length === 1) {
172                                 // Called as: api.enable(['edit','remove'])
173                                 var items = arguments[0];
174                                 if (typeof items !== 'object') {
175                                         return;
176                                 }
177                                 
178                                 $menuEl.find('li > a').each(function () {
179                                         var hrefValue = $(this).attr('href');
180                                         var value = hrefValue.slice(hrefValue.indexOf("#") + 1, hrefValue.length)
181                                         if ($.inArray(value, items) > -1) {
182                                                 $(this).closest('li').removeClass('disabled');
183                                         }
184                                 });
185
186                                 nodeToDisabledMenuItems = {};
187                         } else if (arguments.length === 2) {
188                                 // Called as: api.enable(nodeName, ['edit','remove'])
189                                 var nodeName = arguments[0];
190                                 var items = arguments[1];
191                                 if (items.length === 0) {
192                                         delete nodeToDisabledMenuItems[nodeName];
193                                 } else {
194                                         var disabledItems = nodeToDisabledMenuItems[nodeName];
195                                         for (var i = 0; i < items.length; i++) {
196                                                 var idx = disabledItems.indexOf(items[i]);
197                                                 if (idx > -1) {
198                                                         disabledItems.splice(idx, 1);
199                                                 }
200                                         }
201                                         if (disabledItems.length === 0) {
202                                                 delete nodeToDisabledMenuItems[nodeName];
203                                         } else {
204                                                 nodeToDisabledMenuItems[nodeName] = disabledItems;      
205                                         }
206                                 }
207                                 if (Object.keys(nodeToDisabledMenuItems).length === 0) {
208                                         $menuEl.find('li.disabled').removeClass('disabled');
209                                 }
210                         }
211                 };
212                 return this;
213         };
214 } (jQuery));