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 * This file defines a toolbar. 27 */ 28 29 /** 30 * Creates a toolbar. 31 * @class 32 * This class represents a basic toolbar which can add buttons, manage listeners, and 33 * enable/disabled its buttons. 34 * 35 * @author Conrad Damon 36 * 37 * @param {Hash} params a hash of parameters 38 * @param {DwtComposite} params.parent the containing widget 39 * @param {String} params.className the CSS class 40 * @param {constant} params.posStyle the positioning style 41 * @param {String} params.id an explicit ID to use for the control's HTML element 42 * @param {ZmController} params.controller the owning controller 43 * @param {String} params.refElementId the id of element that contains toolbar 44 * 45 * @extends DwtToolBar 46 */ 47 ZmToolBar = function(params) { 48 if (arguments.length == 0) return; 49 50 params.posStyle = params.posStyle || DwtControl.ABSOLUTE_STYLE; 51 DwtToolBar.call(this, params); 52 53 var controller = params.controller || appCtxt.getCurrentController(); 54 if (controller) { 55 this._controller = controller; 56 this._keyMap = this._controller.getKeyMapName(); 57 } 58 59 this._refElementId = params.refElementId; 60 this._buttons = {}; 61 }; 62 63 ZmToolBar.prototype = new DwtToolBar; 64 ZmToolBar.prototype.constructor = ZmToolBar; 65 66 ZmToolBar.prototype.isZmToolBar = true; 67 ZmToolBar.prototype.toString = function() { return "ZmToolBar"; }; 68 69 /** 70 * Adds a selection listener. 71 * 72 * @param {String} buttonId the button id 73 * @param {AjxListener} listener the listener 74 */ 75 ZmToolBar.prototype.addSelectionListener = 76 function(buttonId, listener) { 77 var button = this._buttons[buttonId]; 78 if (button) { 79 button.addSelectionListener(listener); 80 } 81 }; 82 83 /** 84 * Removes a selection listener. 85 * 86 * @param {String} buttonId the button id 87 * @param {AjxListener} listener the listener 88 */ 89 ZmToolBar.prototype.removeSelectionListener = 90 function(buttonId, listener) { 91 var button = this._buttons[buttonId]; 92 if (button) { 93 button.removeSelectionListener(listener); 94 } 95 }; 96 97 /** 98 * Gets the button. 99 * 100 * @param {String} buttonId the button id 101 * @return {ZmAppButton} the button 102 */ 103 ZmToolBar.prototype.getButton = 104 function(buttonId) { 105 return this._buttons[buttonId]; 106 }; 107 108 /** 109 * sets an item visibility. finds the button by id. 110 * 111 * @param {String} buttonId the button id 112 * @param {Boolean} visible 113 */ 114 ZmToolBar.prototype.setItemVisible = 115 function(buttonId, visible) { 116 var button = this.getButton(buttonId); 117 if (!button) { 118 return; 119 } 120 button.setVisible(visible); 121 }; 122 123 124 /** 125 * Sets the data. 126 * 127 * @param {String} buttonId the button id 128 * @param {String} key the data key 129 * @param {Object} data the data 130 */ 131 ZmToolBar.prototype.setData = 132 function(buttonId, key, data) { 133 this._buttons[buttonId].setData(key, data); 134 }; 135 136 /** 137 * Enables or disables the specified buttons. 138 * 139 * @param {Array} ids a list of button ids 140 * @param {Boolean} enabled if <code>true</code>, enable the buttons 141 */ 142 ZmToolBar.prototype.enable = 143 function(ids, enabled) { 144 ids = (ids instanceof Array) ? ids : [ids]; 145 for (var i = 0; i < ids.length; i++) { 146 if (this._buttons[ids[i]]) { 147 this._buttons[ids[i]].setEnabled(enabled); 148 } 149 } 150 }; 151 152 ZmToolBar.prototype.setSelected = 153 function(id) { 154 var oldButton = this._selectedId ? this._buttons[this._selectedId] : null; 155 var newButton = id ? this._buttons[id] : null; 156 if (oldButton) { 157 oldButton.setSelected(false); 158 } 159 if (newButton) { 160 newButton.setSelected(true); 161 this._selectedId = id; 162 } 163 }; 164 165 /** 166 * Enables or disables all buttons. 167 * 168 * @param {Boolean} enabled if <code>true</code>, enable the buttons 169 */ 170 ZmToolBar.prototype.enableAll = 171 function(enabled) { 172 for (var i in this._buttons) { 173 this._buttons[i].setEnabled(enabled); 174 } 175 }; 176 177 /** 178 * Creates a button and adds the button to this toolbar. 179 * 180 * @param {String} id the button id 181 * @param {Hash} params a hash of parameters: 182 * @param {function} params.constructor the constructor for button object (default is {@link DwtToolBarButton}) 183 * @param {String} params.template the button template 184 * @param {String} params.text the button text 185 * @param {String} params.tooltip the button tooltip text 186 * @param {String} params.image the icon class for the button 187 * @param {String} params.disImage the disabled version of icon 188 * @param {Boolean} params.enabled if <code>true</code>, button is enabled 189 * @param {String} params.className the CSS class name 190 * @param {String} params.style the button style 191 * @param {int} params.index the position at which to add the button 192 * @param {constant} params.shortcut the shortcut id (from {@link ZmKeyMap}) for showing hint 193 * @param {AjxCallback|DwtMenu} params.menu the menu creation callback (recommended) or menu 194 * @param {Boolean} params.menuAbove if <code>true</code>, popup menu above the button. 195 * 196 * @param {Object} params.whatToShow if exists, determines what to show as follows: (for usage, see ZmToolBar.prototype._createButton and DwtButton.prototype.setImage and DwtButton.prototype.setText 197 * @param {Boolean} params.whatToShow.showImage if <code>true</code>, display image 198 * @param {Boolean} params.whatToShow.showText if <code>true</code>, display text 199 * 200 */ 201 ZmToolBar.prototype.createButton = 202 function(id, params) { 203 var b = this._buttons[id] = this._createButton(params); 204 if (params.image) { 205 b.setImage(params.image); 206 } 207 if (params.text) { 208 b.setText(params.text); 209 } 210 if (params.tooltip) { 211 b.setToolTipContent(ZmOperation.getToolTip(id, this._keyMap) || params.tooltip, true); 212 } 213 b.setEnabled(params.enabled !== false); 214 b.setData("_buttonId", id); 215 if (params.menu) { 216 b.setMenu(params.menu, false, null, params.menuAbove); 217 } 218 219 return b; 220 }; 221 222 // 223 // Data 224 // 225 226 ZmToolBar.prototype.SEPARATOR_TEMPLATE = "share.Widgets#ZmToolBarSeparator"; 227 228 // 229 // Protected methods 230 // 231 232 /** 233 * @private 234 */ 235 ZmToolBar.prototype._createButton = 236 function(params, className) { 237 var ctor = params.ctor || DwtToolBarButton; 238 var button = new ctor({ 239 parent:this, 240 style:params.style, 241 className:className, 242 index:params.index, 243 id:params.id, 244 template: params.template 245 }); 246 button.textPrecedence = params.textPrecedence; 247 button.imagePrecedence = params.imagePrecedence; 248 button.whatToShow = params.whatToShow; 249 250 return button; 251 }; 252 253 /** 254 * @private 255 */ 256 ZmToolBar.prototype._buttonId = 257 function(button) { 258 return button.getData("_buttonId"); 259 }; 260 261 /** 262 * Creates an ordered list of which bits of text or images get removed when we need space. 263 * 264 * @private 265 */ 266 ZmToolBar.prototype._createPrecedenceList = 267 function() { 268 this._precedenceList = []; 269 for (var id in this._buttons) { 270 if (ZmOperation.isSep(id)) { continue; } 271 var b = this._buttons[id]; 272 var tp = b.textPrecedence; 273 if (tp) { 274 this._precedenceList.push({id:id, type:"text", precedence:tp}); 275 } 276 var ip = b.imagePrecedence; 277 if (ip) { 278 this._precedenceList.push({id:id, type:"image", precedence:ip}); 279 } 280 } 281 this._precedenceList.sort(function(a, b) { 282 return (a.precedence > b.precedence) ? 1 : (a.precedence < b.precedence) ? -1 : 0; 283 }); 284 }; 285 286 // The following overrides are so that we check our width after a call to a function that 287 // may affect our size. 288 289 /** 290 * Sets the size. This method is called by the application view manager <code>fitToContainer()</code>, 291 * which happens during initial layout as well as in response to the user changing the browser size. 292 * 293 * @param {int} width the width (in pixels) 294 * @param {int} height the height (in pixels) 295 */ 296 ZmToolBar.prototype.setSize = 297 function(width, height) { 298 DBG.println("tb", "------ setSize " + width + " x " + height); 299 var sz = this.getSize(); 300 if (sz && (width != sz.x || height != sz.y)) { 301 DwtToolBar.prototype.setSize.apply(this, arguments); 302 } 303 }; 304 305 ZmToolBar.prototype.adjustSize = 306 function() { 307 if (!this._refElementId || !this._inited) { return; } 308 if (!this._refElement) { 309 this._refElement = document.getElementById(this._refElementId); 310 } 311 var container = this._refElement && this._refElement.parentNode; 312 var offsetWidth; 313 if (container && ((offsetWidth = container.offsetWidth) >= 30)) { 314 var style = this._refElement.style; 315 style.maxWidth = style.width = (offsetWidth - 30) + "px"; 316 style.overflow = "hidden"; 317 } 318 } 319 320 /** 321 * Adds a button to the element with the given ID. Designed to handle non-ZmToolBar toolbars. 322 * 323 * @param params [hash] hash of params: 324 * parent [DwtControl] parent control 325 * setting [const] setting that must be true for this button to be added 326 * tdId [string] ID of TD that is to contain this button 327 * buttonId [string]* ID of the button 328 * style [const]* button style 329 * type [string]* used to differentiate between regular and toolbar buttons 330 * lbl [string]* button text 331 * icon [string]* button icon 332 * tooltip [string]* button tooltip 333 */ 334 ZmToolBar.addButton = 335 function(params) { 336 337 if (params.setting && !appCtxt.get(params.setting)) { return; } 338 339 var button; 340 var tdId = params.parent._htmlElId + (params.tdId || params.buttonId); 341 var buttonEl = document.getElementById(tdId); 342 if (buttonEl) { 343 var btnParams = {parent:params.parent, index: params.index, style:params.style, id:params.buttonId, template: params.template, className: params.className}; 344 button = (params.type && params.type == "toolbar") ? (new DwtToolBarButton(btnParams)) : (new DwtButton(btnParams)); 345 var hint = Dwt.getAttr(buttonEl, "hint"); 346 ZmToolBar._setButtonStyle(button, hint, params.lbl, params.icon); 347 if (params.tooltip) { 348 button.setToolTipContent(params.tooltip, true); 349 } 350 button.reparentHtmlElement(tdId); 351 } 352 353 return button; 354 }; 355 356 ZmToolBar._setButtonStyle = 357 function(button, hint, text, image) { 358 if (hint == "text") { 359 button.whatToShow = { showText: true }; 360 } else if (hint == "icon") { 361 button.whatToShow = { showImage: true }; 362 } else { // add icon and text if no hint (or unsupported hint) provided 363 button.whatToShow = { showImage: true, showText: true }; 364 } 365 366 button.setText(text); 367 button.setImage(image); 368 }; 369