1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 */ 27 28 /** 29 * Creates an empty contact menu. 30 * @class 31 * This class represents a menu structure of contact groups that to which 32 * contacts can be added. It also provides ability for user to create a new 33 * contact group. 34 * 35 * @param {DwtControl} parent the parent widget 36 * @param {ZmController} controller the owning controller 37 * 38 * @extends ZmPopupMenu 39 */ 40 ZmContactGroupMenu = function(parent, controller) { 41 42 // create a menu (though we don't put anything in it yet) so that parent widget shows it has one 43 ZmPopupMenu.call(this, parent, null, parent.getHTMLElId() + "|GROUP_MENU", controller); 44 45 parent.setMenu(this); 46 this._addHash = {}; 47 this._removeHash = {}; 48 this._evtMgr = new AjxEventMgr(); 49 this._desiredState = true; 50 this._items = null; 51 this._dirty = true; 52 53 // Use a delay to make sure our slow popup operation isn't called when someone 54 // is just rolling over a menu item to get somewhere else. 55 if (parent instanceof DwtMenuItem) { 56 parent.setHoverDelay(ZmContactGroupMenu._HOVER_TIME); 57 } 58 }; 59 60 ZmContactGroupMenu.prototype = new ZmPopupMenu; 61 ZmContactGroupMenu.prototype.constructor = ZmContactGroupMenu; 62 63 ZmContactGroupMenu.KEY_GROUP_EVENT = "_contactGroupEvent_"; 64 ZmContactGroupMenu.KEY_GROUP_ADDED = "_contactGroupAdded_"; 65 ZmContactGroupMenu.MENU_ITEM_ADD_ID = "group_add"; 66 67 ZmContactGroupMenu._HOVER_TIME = 200; 68 69 ZmContactGroupMenu.prototype.toString = 70 function() { 71 return "ZmContactGroupMenu"; 72 }; 73 74 ZmContactGroupMenu.prototype.addSelectionListener = 75 function(listener) { 76 this._evtMgr.addListener(DwtEvent.SELECTION, listener); 77 }; 78 79 ZmContactGroupMenu.prototype.removeSelectionListener = 80 function(listener) { 81 this._evtMgr.removeListener(DwtEvent.SELECTION, listener); 82 }; 83 84 ZmContactGroupMenu.prototype.setEnabled = 85 function(enabled) { 86 this._desiredState = enabled; 87 if (enabled && !this._contactGroupList) { return; } 88 89 this.parent.setEnabled(enabled); 90 }; 91 92 // Dynamically set the list of contact groups that can be added/removed based on the given list of items. 93 ZmContactGroupMenu.prototype.set = 94 function(items, contactGroupList, newDisabled) { 95 DBG.println(AjxDebug.DBG3, "set contact group menu"); 96 this._contactGroupList = contactGroupList; 97 this._items = items; 98 this._dirty = true; 99 this._newDisabled = newDisabled; 100 101 this.parent.setEnabled(true); 102 103 // Turn on the hover delay. 104 if (this.parent instanceof DwtMenuItem) { 105 this.parent.setHoverDelay(ZmContactGroupMenu._HOVER_TIME); 106 } 107 }; 108 109 ZmContactGroupMenu.prototype._doPopup = 110 function(x, y, kbGenerated) { 111 if (this._dirty) { 112 // reset the menu 113 this.removeChildren(); 114 115 if (this._contactGroupList) { 116 var groupNames = []; 117 for (var i=0; i<this._contactGroupList.length; i++) { 118 var contact = ZmContact.getContactFromCache(this._contactGroupList[i].id); 119 if (contact && !ZmContact.isInTrash(contact)) { 120 groupNames.push(ZmContact.getAttr(this._contactGroupList[i], "nickname")); 121 } 122 else { 123 this._contactGroupList[i] = {id: false}; 124 } 125 } 126 this._render(groupNames); 127 } 128 this._dirty = false; 129 130 // Remove the hover delay to prevent flicker when mousing around. 131 if (this.parent instanceof DwtMenuItem) { 132 this.parent.setHoverDelay(0); 133 } 134 } 135 ZmPopupMenu.prototype._doPopup.call(this, x, y, kbGenerated); 136 }; 137 138 ZmContactGroupMenu.prototype._render = 139 function(groupNames, addRemove) { 140 141 for (var i = 0; i < this._contactGroupList.length; i++) { 142 this._addNewGroup(this, this._contactGroupList[i], true, null, this._addHash); 143 } 144 145 if (this._contactGroupList.length) { 146 new DwtMenuItem({parent:this, style:DwtMenuItem.SEPARATOR_STYLE}); 147 } 148 149 // add static "New Contact Group" menu item 150 var miNew = this._menuItems[ZmContactGroupMenu.MENU_ITEM_ADD_ID] = new DwtMenuItem({parent:this, id: this._htmlElId + "|NEWGROUP"}); 151 miNew.setText(AjxStringUtil.htmlEncode(ZmMsg.newGroup)); 152 miNew.setImage("NewGroup"); 153 if (this._newDisabled) { 154 miNew.setEnabled(false); 155 } 156 else { 157 miNew.setData(ZmContactGroupMenu.KEY_GROUP_EVENT, ZmEvent.E_CREATE); 158 miNew.addSelectionListener(this._menuItemSelectionListener.bind(this), 0); 159 } 160 }; 161 162 ZmContactGroupMenu.groupNameLength = 20; 163 ZmContactGroupMenu.prototype._addNewGroup = 164 function(menu, group, add, index, groupHash) { 165 var nickName = ZmContact.getAttr(group, "nickname") || group.fileAsStr; 166 if (nickName) { 167 var mi = new DwtMenuItem({parent:menu, index:index}); 168 var groupName = AjxStringUtil.clipByLength(nickName, ZmContactGroupMenu.groupNameLength); 169 mi.setText(groupName); 170 mi.setImage("Group"); 171 mi.addSelectionListener(this._menuItemSelectionListener.bind(this), 0); 172 mi.setData(ZmContactGroupMenu.KEY_GROUP_EVENT, ZmEvent.E_MODIFY); 173 mi.setData(ZmContactGroupMenu.KEY_GROUP_ADDED, add); 174 mi.setData(Dwt.KEY_OBJECT, group); 175 } 176 }; 177 178 ZmContactGroupMenu.prototype._menuItemSelectionListener = 179 function(ev) { 180 // Only notify if the node is one of our nodes 181 if (ev.item.getData(ZmContactGroupMenu.KEY_GROUP_EVENT)) { 182 this._evtMgr.notifyListeners(DwtEvent.SELECTION, ev.item); 183 } 184 }; 185 186 /** 187 * Sets "New Contact Group" to be enabled/disabled 188 * @param {Boolean} disabled true to set disabled 189 */ 190 ZmContactGroupMenu.prototype.setNewDisabled = 191 function(disabled) { 192 this._newDisabled = disabled; 193 };