1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 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) 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @param {hash} params Constructor parameters. 26 * @param {DwtComposite} params.parent Parent control. 27 * @param {string} params.image Item image to display next to each color choice. 28 * @param {boolean} params.hideNone True to hide the "None" option. 29 * @param {boolean} params.hideNoFill True to hide the no-fill/use-default option. 30 */ 31 ZmColorMenu = function(params) { 32 if (arguments.length == 0) return; 33 params.className = params.className || "ZmColorMenu DwtMenu"; 34 DwtMenu.call(this, params); 35 this._hideNone = params.hideNone; 36 this._hideNoFill = params.hideNoFill; 37 this.setImage(params.image); 38 this._populateMenu(); 39 }; 40 ZmColorMenu.prototype = new DwtMenu; 41 ZmColorMenu.prototype.constructor = ZmColorMenu; 42 43 ZmColorMenu.prototype.toString = function() { 44 return "ZmColorMenu"; 45 }; 46 47 // 48 // Constants 49 // 50 51 ZmColorMenu.__KEY_COLOR = "color"; 52 53 // 54 // Public methods 55 // 56 57 ZmColorMenu.prototype.setImage = function(image) { 58 if (this._image != image) { 59 this._image = image; 60 var children = this.getChildren(); 61 for (var i = 0; i < children.length; i++) { 62 var child = children[i]; 63 var color = child.getData(ZmColorMenu.__KEY_COLOR); 64 var displayColor = color || ZmOrganizer.COLOR_VALUES[ZmOrganizer.ORG_DEFAULT_COLOR]; //default to gray 65 var icon = [image, displayColor].join(",color="); 66 child.setImage(icon); 67 } 68 } 69 }; 70 ZmColorMenu.prototype.getImage = function() { 71 return this._image; 72 }; 73 74 ZmColorMenu.prototype.getTextForColor = function(color) { 75 color = String(color).toLowerCase(); 76 if (!color.match(/^#/)) color = ZmOrganizer.COLOR_VALUES[color]; 77 var children = this.getChildren(); 78 for (var i = 0; i < children.length; i++) { 79 var mi = children[i]; 80 if (mi.getData(ZmColorMenu.__KEY_COLOR) == color) { 81 return mi.getText(); 82 } 83 } 84 return ZmMsg.custom; 85 }; 86 87 ZmColorMenu.prototype.showMoreColors = function() { 88 if (this.parent && this.parent.getMenu() == this) { 89 var menu = this.parent.getMenu(); 90 var moreMenu = this._getMoreColorMenu(); 91 this.parent.setMenu(moreMenu); 92 if (menu.isPoppedUp()) { 93 var loc = menu.getLocation(); 94 menu.popdown(); 95 moreMenu.popup(0, loc.x, loc.y); 96 } 97 else { 98 this.parent.popup(); 99 } 100 } 101 }; 102 103 ZmColorMenu.prototype.showLessColors = function() { 104 if (this.parent && this.parent.getMenu() != this) { 105 var menu = this.parent.getMenu(); 106 this.parent.setMenu(this); 107 if (menu.isPoppedUp()) { 108 var loc = menu.getLocation(); 109 menu.popdown(); 110 this.popup(0, loc.x, loc.y); 111 } 112 else { 113 this.parent.popup(); 114 } 115 } 116 }; 117 118 // 119 // DwtMenu methods 120 // 121 122 ZmColorMenu.prototype.addSelectionListener = function(listener) { 123 DwtMenu.prototype.addSelectionListener.apply(this, arguments); 124 this._getMoreColorMenu().addSelectionListener(listener); 125 }; 126 ZmColorMenu.prototype.removeSelectionListener = function(listener) { 127 DwtMenu.prototype.removeSelectionListener.apply(this, arguments); 128 this._getMoreColorMenu().removeSelectionListener(listener); 129 }; 130 131 // 132 // Protected methods 133 // 134 135 ZmColorMenu.prototype._populateMenu = function() { 136 var list = ZmOrganizer.COLOR_VALUES; 137 for (var id = 0; id < list.length; id++) { 138 var color = ZmOrganizer.COLOR_VALUES[id]; 139 if (!color && this._hideNone) continue; 140 var displayColor = color || ZmOrganizer.COLOR_VALUES[ZmOrganizer.ORG_DEFAULT_COLOR]; //default to gray 141 var image = this._image ? [this._image, displayColor].join(",color=") : null; 142 var text = ZmOrganizer.COLOR_TEXT[id]; 143 var menuItemId = "COLOR_" + id; 144 var menuItem = new DwtMenuItem({parent:this, id:menuItemId}); 145 menuItem.setImage(image); 146 menuItem.setText(text); 147 menuItem.setData(ZmOperation.MENUITEM_ID, id); 148 menuItem.setData(ZmColorMenu.__KEY_COLOR, color); 149 } 150 var callback = new AjxCallback(this, this.showMoreColors); 151 var showMoreItem = new ZmColorMenuItem({parent:this,callback:callback, id:"SHOW_MORE_ITEMS"}); 152 showMoreItem.setText(ZmMsg.colorsShowMore); 153 }; 154 155 ZmColorMenu.prototype._getMoreColorMenu = function() { 156 if (!this._moreMenu) { 157 var callback = new AjxCallback(this, this.showLessColors); 158 this._moreMenu = new ZmMoreColorMenu({parent:this.parent,callback:callback,hideNoFill:this._hideNoFill}); 159 } 160 return this._moreMenu; 161 }; 162 163 // 164 // Classes 165 // 166 167 ZmMoreColorMenu = function(params) { 168 params.style = DwtMenu.COLOR_PICKER_STYLE; 169 DwtMenu.call(this, params); 170 this._colorPicker = new DwtColorPicker({parent:this,hideNoFill:params.hideNoFill}); 171 this._colorPicker.getData = this.__DwtColorPicker_getData; // HACK 172 var showLessItem = new ZmColorMenuItem({parent:this,callback:params.callback}); 173 showLessItem.setText(ZmMsg.colorsShowLess); 174 }; 175 ZmMoreColorMenu.prototype = new DwtMenu; 176 ZmMoreColorMenu.prototype.constructor = ZmMoreColorMenu; 177 178 ZmMoreColorMenu.prototype.toString = function() { 179 return "ZmMoreColorMenu"; 180 }; 181 182 /** 183 * <strong>Note:</strong> 184 * This method is run in the context of the color picker! 185 * 186 * @private 187 */ 188 ZmMoreColorMenu.prototype.__DwtColorPicker_getData = function(key) { 189 // HACK: This is to fake the color picker as a menu item whose 190 // HACK: id is the selected color. 191 if (key == ZmOperation.MENUITEM_ID) { 192 return this.getInputColor(); 193 } 194 return DwtColorPicker.prototype.getData.apply(this, arguments); 195 }; 196 197 ZmMoreColorMenu.prototype.setDefaultColor = function(color) { 198 this._colorPicker.setDefaultColor(color); 199 } 200 201 /** 202 * A custom menu item class for the "More colors..." and 203 * "Fewer colors..." options which should not leave space for 204 * an image next to the text. A sub-class is also needed so 205 * that we can avoid the default handling of the item click. 206 * 207 * @param params 208 */ 209 ZmColorMenuItem = function(params) { 210 DwtMenuItem.call(this, params); 211 this.callback = params.callback; 212 // HACK: This is needed because we no-op the add/removeSelectionListener 213 // HACK: methods so that external people can't register listeners but we 214 // HACK: still want to handle a true selection to call the callback. 215 DwtMenuItem.prototype.addSelectionListener.call(this, new AjxListener(this, this.__handleItemSelect)); 216 }; 217 ZmColorMenuItem.prototype = new DwtMenuItem; 218 ZmColorMenuItem.prototype.constructor = ZmColorMenuItem; 219 220 ZmColorMenuItem.prototype.toString = function() { 221 return "ZmColorMenuItem"; 222 }; 223 224 ZmColorMenuItem.prototype.TEMPLATE = "zimbra.Widgets#ZmColorMenuItem"; 225 226 // DwtMenuItem methods 227 228 ZmColorMenuItem.prototype.addSelectionListener = function() {}; // no-op 229 ZmColorMenuItem.prototype.removeSelectionListener = function() {}; // no-op 230 231 ZmColorMenuItem.prototype.__handleItemSelect = function() { 232 if (this.callback) { 233 this.callback.run(); 234 } 235 }; 236