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, 2015, 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, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 */ 27 28 /** 29 * Creates a toolbar with the given buttons. 30 * @class 31 * This class represents a toolbar that contains buttons. 32 * It can be easily created using a set of standard operations, and/or custom buttons 33 * can be provided. This class is designed for use with items ({@link ZmItem}), so it can for 34 * example contain a button with a tab submenu. See also {@link ZmActionMenu}. 35 * 36 * @author Conrad Damon 37 * 38 * @param {Hash} params a hash of parameters 39 * @param {DwtComposite} params.parent the containing widget 40 * @param {Array} params.buttons a list of operation IDs 41 * @param {constant} params.posStyle the positioning style 42 * @param {String} params.className the CSS class name 43 * @param {Stirng} params.buttonClassName the CSS class name for buttons 44 * @param {Hash} params.overrides a hash of overrides by op ID 45 * @param {Array} params.secondaryButtons a list of operation IDs 46 * @param {Array} params.rightSideButtons a list of operation IDs 47 * @param {constant} params.context the vcontextID (used to generate button IDs) 48 * @param {constant} params.toolbarType the toolbar type (used to generate button IDs) 49 * @param {Boolean} params.addTextElement if true, add a text "button" (element) at the end (but before the view button, if any). This can be used for message counts etc 50 * @param {ZmController} params.controller the owning controller 51 * 52 * @extends ZmToolBar 53 */ 54 ZmButtonToolBar = function(params) { 55 if (arguments.length == 0) return; 56 57 if (!params.className && (params.controller && params.controller._elementsToHide == ZmAppViewMgr.LEFT_NAV)) { 58 params.className = "ZToolbar itemToolbar"; 59 } 60 params.className = params.className || "ZToolbar"; 61 params.id = params.context ? ZmId.getToolbarId(params.context, params.toolbarType) : null; 62 ZmToolBar.call(this, params); 63 64 this._context = params.context; 65 this._toolbarType = params.toolbarType; 66 this._buttonStyle = params.buttonClassName; 67 68 // standard buttons default to New/Tag/Print/Delete 69 var buttonOps = params.buttons; 70 if (!buttonOps) { 71 buttonOps = [ZmOperation.NEW_MENU, ZmOperation.TAG_MENU, ZmOperation.PRINT, ZmOperation.DELETE]; 72 } else if (buttonOps == ZmOperation.NONE) { 73 buttonOps = null; 74 } 75 // weed out disabled ops, save list of ones that make it 76 /** 77 * The operation list property. 78 * @type Array 79 */ 80 this.opList = ZmOperation.filterOperations(buttonOps); 81 82 this._zimletButtonLocation = this.opList.length; 83 84 var secondaryOpList = ZmOperation.filterOperations(params.secondaryButtons); 85 86 if (secondaryOpList && secondaryOpList.length) { 87 this.opList.push(ZmOperation.SEP, ZmOperation.ACTIONS_MENU); 88 } 89 90 var rightSideOpList = ZmOperation.filterOperations(params.rightSideButtons); 91 92 if (rightSideOpList.length > 0 || params.addTextElement) { 93 this.opList.push(ZmOperation.FILLER); 94 } 95 96 if (params.addTextElement) { 97 this.opList.push(ZmOperation.TEXT); 98 } 99 100 if (rightSideOpList.length > 0) { 101 this.opList = this.opList.concat(rightSideOpList); 102 } 103 104 this._buttons = ZmOperation.createOperations(this, this.opList, params.overrides); 105 106 if (secondaryOpList && secondaryOpList.length) { 107 var actionsButton = this._secondaryButton = this.getButton(ZmOperation.ACTIONS_MENU); 108 109 actionsButton.noMenuBar = true; 110 111 var secondaryMenu = this._secondaryButtonMenu = new ZmActionMenu({parent: actionsButton, menuItems: ZmOperation.NONE, context: this._context, controller: params.controller}); 112 var secondaryButtons = ZmOperation.createOperations(secondaryMenu, secondaryOpList, params.overrides); 113 actionsButton.setMenu(secondaryMenu); 114 115 //add secondary buttons to buttons list as I believe from now on it shouldn't matter if they are primary or under the secondary "actions" menu. 116 //that way we don't need to operate on 2 different collections when enabling/disabling, adding listeners, etc. 117 //var secondaryButtons = secondaryMenu._menuItems; 118 for (var id in secondaryButtons) { 119 this._buttons[id] = secondaryButtons[id]; 120 } 121 //same as buttons, with opList. 122 this.opList = this.opList.concat(secondaryOpList); 123 124 } 125 126 //todo - I guess in the new UI a button (primary) will have either text or image. not both. Think of whether this precedence is still required then. 127 this._createPrecedenceList(); //this is only done to the primary, not the secondary buttons (since the secondary are in a drop-down so removing one's image or text won't make sense.) 128 129 this._inited = true; 130 }; 131 132 ZmButtonToolBar.prototype = new ZmToolBar; 133 ZmButtonToolBar.prototype.constructor = ZmButtonToolBar; 134 135 ZmButtonToolBar.prototype.isZmButtonToolBar = true; 136 ZmButtonToolBar.prototype.toString = function() { return "ZmButtonToolBar"; }; 137 138 139 // Public methods 140 141 142 /** 143 * Creates a button and adds its operation ID as data. 144 * 145 * @param {String} id the name of the operation 146 * @param {Hash} params a hash of parameters 147 * @param {String} params.text a button text 148 * @param {String} params.tooltip a button tooltip text 149 * @param {String} params.image a icon class for the button 150 * @param {String} params.disImage a disabled version of icon 151 * @param {Boolean} params.enabled if <code>true</code>, button is enabled 152 * @param {String} params.className the CSS class name 153 * @param {String} params.style thebutton style 154 * @param {int} params.index the position at which to add the button 155 * @param {Boolean} params.showImageInToolbar if <code>true</code>, the button should show image (default is false) 156 * @param {Boolean} params.showTextInToolbar if <code>true</code>, the button should show text (default is !params.showImageInToolbar) 157 */ 158 ZmButtonToolBar.prototype.createOp = 159 function(id, params) { 160 params.className = this._buttonStyle; 161 var b; 162 if (id == ZmOperation.TEXT) { 163 var id; 164 if (this._context) { 165 var context = this._toolbarType ? [this._context, this._toolbarType].join("_") : this._context; 166 id = [ZmId.WIDGET, AjxStringUtil.toMixed(context, "_", true), AjxStringUtil.toMixed(id, "_")].join(""); 167 } 168 params.textClassName = params.textClassName || "DwtText ZWidgetTitle"; 169 b = new DwtText({parent:this, className:params.textClassName, id:id}); 170 } else { 171 params.id = params.domId || (this._context ? ZmId.getButtonId(this._context, id, this._toolbarType) : null); 172 params.textPrecedence = ZmOperation.getProp(id, "textPrecedence"); 173 params.iconPrecedence = ZmOperation.getProp(id, "iconPrecedence"); 174 var showImage = params.showImageInToolbar || false; //default to false; 175 var showText = !showImage || params.showTextInToolbar; 176 showImage = showImage || !params.text; //no text? gotta show image 177 showText = showText || !params.image; //no image? gotta show text 178 params.image = showImage && params.image; 179 params.whatToShow = {showImage: showImage, showText: showText} 180 b = this.createButton(id, params); 181 } 182 b.setData(ZmOperation.KEY_ID, id); 183 184 return b; 185 }; 186 187 /** 188 * Creates a zimlet button and adds its operation ID as data. This method selects the best location for the zimlet, so zimlets don't have to do it and it's consistent. 189 * 190 * for parameters see createOp 191 */ 192 ZmButtonToolBar.prototype.createZimletOp = 193 function(id, params) { 194 params.index = this._zimletButtonLocation; 195 return this.createOp(id, params); 196 }; 197 198 199 /** 200 * Adds the operation. 201 * 202 * @param {String} id the id 203 * @param {int} index the index 204 */ 205 ZmButtonToolBar.prototype.addOp = 206 function(id, index) { 207 if(this.getOp(id)) { 208 return; 209 } 210 ZmOperation.addOperation(this, id, this._buttons, index); 211 AjxUtil.arrayAdd(this.opList, id, index); 212 }; 213 214 /** 215 * Removes the operation. 216 * 217 * @param {String} id the id 218 * 219 * @see ZmOperation 220 */ 221 ZmButtonToolBar.prototype.removeOp = 222 function(id) { 223 ZmOperation.removeOperation(this, id, this._buttons); 224 AjxUtil.arrayRemove(this.opList, id); 225 }; 226 227 /** 228 * Gets the button. 229 * 230 * @param {constant} id the button 231 * @return {DwtButton} the button 232 * 233 * @see ZmOperation 234 */ 235 ZmButtonToolBar.prototype.getOp = 236 function(id) { 237 return this.getButton(id); 238 }; 239 240 /** 241 * Gets the menu tag sub-menu (if any). 242 * 243 * @return {ZmTagMenu} the menu 244 */ 245 ZmButtonToolBar.prototype.getTagMenu = 246 function() { 247 var button = this.getButton(ZmOperation.TAG_MENU); 248 if (button) { 249 return button.getMenu(); 250 } 251 }; 252 253 /** 254 * gets the secondary menu (the "Actions" menu in the toolbar) 255 */ 256 ZmButtonToolBar.prototype.getActionsMenu = 257 function() { 258 return this._secondaryButtonMenu; 259 }; 260 261 /** 262 * gets the secondary button (the "Actions" button in the toolbar) 263 */ 264 ZmButtonToolBar.prototype.getActionsButton = 265 function() { 266 return this._secondaryButton; 267 }; 268 269 270 // 271 // Private methods 272 // 273 274 // Returns the ID for the given button. 275 ZmButtonToolBar.prototype._buttonId = 276 function(button) { 277 return button.getData(ZmOperation.KEY_ID); 278 }; 279