1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * @overview
 26  */
 27 
 28 /**
 29  * Creates a popup menu.
 30  * @class
 31  * This class represents a basic popup menu which can add menu items, manage listeners, and
 32  * enable/disabled its menu items.
 33  *
 34  * @author Conrad Damon
 35  *
 36  * @param {DwtComposite}	parent		the containing widget
 37  * @param {string}	className		the CSS class
 38  * @param {string}	id			an explicit ID to use for the control's HTML element
 39  * @param {ZmController}	controller	the owning controller
 40  * 
 41  * @extends		DwtMenu
 42  */
 43 ZmPopupMenu = function(parent, className, id, controller) {
 44 
 45 	if (arguments.length == 0) return;
 46 	var params = Dwt.getParams(arguments, ZmPopupMenu.PARAMS);
 47 	params.className = params.className ? params.className : "ActionMenu";
 48 	params.style = params.style || DwtMenu.POPUP_STYLE;
 49     params.id = params.id || "POPUP_" + Dwt.getNextId();
 50 	DwtMenu.call(this, params);
 51 
 52 	controller = controller || appCtxt.getCurrentController();
 53 	if (controller) {
 54 		this._controller = controller;
 55 		this._keyMap = this._controller.getKeyMapName();
 56 	}
 57 
 58 	this._menuItems = {};
 59 };
 60 
 61 ZmPopupMenu.PARAMS = ["parent", "className", "id", "controller"];
 62 
 63 ZmPopupMenu.prototype = new DwtMenu;
 64 ZmPopupMenu.prototype.constructor = ZmPopupMenu;
 65 
 66 ZmPopupMenu.prototype.isZmPopupMenu = true;
 67 ZmPopupMenu.prototype.toString = function() { return "ZmPopupMenu"; };
 68 
 69 /**
 70  * Adds a section listener.
 71  * 
 72  * @param	{string}		menuItemId		the menu item id
 73  * @param	{AjxListener}	listener		the selection listener
 74  * @param	{number}		index				the index where to insert the listener
 75  */
 76 ZmPopupMenu.prototype.addSelectionListener =
 77 function(menuItemId, listener, index) {
 78 	var menuItem = this._menuItems[menuItemId];
 79 	if (menuItem) {
 80 		menuItem.addSelectionListener(listener, index);
 81 	}
 82 };
 83 
 84 /**
 85  * Removes a section listener.
 86  * 
 87  * @param	{string}		menuItemId		the menu item id
 88  * @param	{AjxListener}	listener		the selection listener
 89  */
 90 ZmPopupMenu.prototype.removeSelectionListener =
 91 function(menuItemId, listener) {
 92 	var menuItem = this._menuItems[menuItemId];
 93 	if (menuItem) {
 94 		menuItem.removeSelectionListener(listener);
 95 	}
 96 };
 97 
 98 ZmPopupMenu.prototype.popup =
 99 function(delay, x, y, kbGenerated) {
100 	delay = delay ? delay : 0;
101 	x = (x != null) ? x : Dwt.DEFAULT;
102 	y = (y != null) ? y : Dwt.DEFAULT;
103 	DwtMenu.prototype.popup.call(this, delay, x, y, kbGenerated);
104 };
105 
106 /**
107  * Enables/disables menu items.
108  *
109  * @param {array}	ids		a list of menu item IDs
110  * @param {boolean}		enabled	if <code>true</code>, enable the menu items
111  */
112 ZmPopupMenu.prototype.enable =
113 function(ids, enabled) {
114 	ids = (ids instanceof Array) ? ids : [ids];
115 	for (var i = 0; i < ids.length; i++) {
116 		if (this._menuItems[ids[i]]) {
117 			this._menuItems[ids[i]].setEnabled(enabled);
118 		}
119 	}
120 };
121 
122 /**
123  * Enables/disables all menu items.
124  *
125  * @param {boolean}		enabled	if <code>true</code>, enable the menu items
126  */
127 ZmPopupMenu.prototype.enableAll =
128 function(enabled) {
129 	for (var i in this._menuItems) {
130 		this._menuItems[i].setEnabled(enabled);
131 	}
132 };
133 
134 /**
135  * Creates a menu item and adds the item to this menu.
136  *
137  * @param {string}	id			the menu item ID
138  * @param {hash}	params		a hash of parameters
139  * @param {string}	params.text		the menu item text
140  * @param {string}	params.image		the icon class for the or menu item
141  * @param {string}	params.disImage	disabled version of icon
142  * @param {boolean}	params.enabled		if <code>true</code>, menu item is enabled
143  * @param {constant}	params.style			the menu item style
144  * @param {string}	params.radioGroupId	the ID of radio group for this menu item
145  * @param {constant}	params.shortcut		the shortcut ID (from {@link ZmKeyMap}) for showing hint
146  * 
147  * @see		DwtMenuItem
148  */
149 ZmPopupMenu.prototype.createMenuItem =
150 function(id, params, htmlElId) {
151 	var mi = this._menuItems[id] = new DwtMenuItem({parent:this, style:params.style, radioGroupId:params.radioGroupId,
152 													id: (htmlElId || params.id || id), index: params.index});
153 	if (params.image) {
154 		mi.setImage(params.image);
155 	}
156 	if (params.text) {
157 		mi.setText(params.text);
158 	}
159 	if (params.shortcut) {
160 		mi.setShortcut(appCtxt.getShortcutHint(this._keyMap, params.shortcut));
161 	}
162 
163 	mi.setEnabled(params.enabled !== false);
164 	mi.setData(ZmOperation.MENUITEM_ID, id);
165 
166     //set context menu tr id
167     var row = mi.getRowElement();
168 	if (row) {
169 		row.setAttribute("id", "POPUP" + "_" + mi.getHTMLElId().toString().replace(/\s/g, ""));
170     }
171 
172 	return mi;
173 };
174 
175 /**
176  * Gets the menu item with the given ID.
177  *
178  * @param {string}	id		an operation ID
179  * @return	{DwtMenuItem}		the menu item
180  */
181 ZmPopupMenu.prototype.getMenuItem =
182 function(id) {
183 	return this._menuItems[id];
184 };
185 
186 /**
187  * sets an item visibility. finds the menu item by id. 
188  *
189  * @param	{String}	id  the operation id
190  * @param	{Boolean}	visible
191  */
192 ZmPopupMenu.prototype.setItemVisible =
193 function(id, visible) {
194 	var item = this.getMenuItem(id);
195 	if (!item) {
196 		return;
197 	}
198 	item.setVisible(visible);
199 };
200 
201 /**
202  * Gets the menu items.
203  *
204  * @return	{array}		an array of {@link DwtMenuItem} objects
205  */
206 ZmPopupMenu.prototype.getMenuItems =
207 function() {
208 	return this._menuItems;
209 };
210 
211 /**
212  * Gets the menu search sub-menu (if any).
213  *
214  * @return {DwtMenu}        the menu
215  */
216 ZmPopupMenu.prototype.getSearchMenu =
217 function() {
218     var menuItem = this.getMenuItem(ZmOperation.SEARCH_MENU);
219     if (menuItem) {
220         return menuItem.getMenu();
221     }
222 };
223 
224 ZmPopupMenu.prototype.getContactGroupMenu =
225 function() {
226 	var menuItem = this.getMenuItem(ZmOperation.CONTACTGROUP_MENU);
227 	if (menuItem) {
228 		return menuItem.getMenu();
229 	}
230 };
231 
232 
233 /**
234  * Creates a menu item separator.
235  * 
236  * @return	{DwtMenuItem}	the separator menu item
237  */
238 ZmPopupMenu.prototype.createSeparator =
239 function() {
240 	new DwtMenuItem({parent:this, style:DwtMenuItem.SEPARATOR_STYLE});
241 };
242