1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2007, 2008, 2009, 2010, 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) 2007, 2008, 2009, 2010, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * Creates a slider. 26 * @constructor 27 * @class 28 * This class represents a slider. 29 * 30 * @param {DwtControl} parent the parent widget 31 * @param {DwtSlider.HORIZONTAL|DwtSlider.VERTICAL} orientation the orientation of the slider 32 * @param {string} [className] the CSS class. If not provided defaults to "DwtHorizontalSlider" or "DwtVerticalSlider" 33 * @param {constant} [posStyle=DwtControl.STATIC_STYLE] the positioning style (see {@link DwtControl}) 34 * 35 * @extends DwtControl 36 */ 37 DwtSlider = function(parent, orientation, className, posStyle) { 38 if (arguments.length == 0) return; 39 this._orientation = orientation || DwtSlider.HORIZONTAL; 40 className = className || (this._orientation == DwtSlider.HORIZONTAL ? "DwtHorizontalSlider" : "DwtVerticalSlider"); 41 DwtControl.call(this, {parent:parent, className:className, posStyle:posStyle}); 42 43 this._size = 0; 44 this._buttonSize = 0; 45 46 this._value = 0; 47 this._minimum = 0; 48 this._maximum = 100; 49 50 this._isDragging = false; 51 52 DwtDragTracker.init(this, null, 0, 0, this._dragListener, this); 53 54 this._createHtml(); 55 }; 56 57 DwtSlider.prototype = new DwtControl; 58 DwtSlider.prototype.constructor = DwtSlider; 59 60 /** 61 * Defines the "horizontal" orientation. 62 */ 63 DwtSlider.HORIZONTAL = 1; 64 /** 65 * Defines the "vertical" orientation. 66 */ 67 DwtSlider.VERTICAL = 2; 68 69 DwtSlider.prototype.toString = 70 function() { 71 return "DwtSlider"; 72 }; 73 74 /** 75 * Sets the value of the slider, moving the position button accordingly. 76 * 77 * @param {number} value the value 78 * @param {boolean} notify if <code>true</code>, to notify change listeners of the new value 79 */ 80 DwtSlider.prototype.setValue = 81 function(value, notify) { 82 // Adjust the value into the valid range. 83 value = Math.max(this._minimum, value); 84 value = Math.min(this._maximum, value); 85 this._value = value; 86 87 // Move the button. 88 var location = this._valueToLocation(value); 89 var property = this._orientation == DwtSlider.HORIZONTAL ? "left" : "top"; 90 var element = this._getButtonElement(); 91 element.style[property] = location; 92 93 // Send notification. 94 if (notify) { 95 if (!this._changeEvent) { 96 this._changeEvent = new DwtEvent(true); 97 this._changeEvent.dwtObj = this; 98 } 99 this.notifyListeners(DwtEvent.ONCHANGE, this._changeEvent); 100 } 101 }; 102 103 /** 104 * Gets the slider value. 105 * 106 * @return {number} the value 107 */ 108 DwtSlider.prototype.getValue = 109 function() { 110 return this._value; 111 }; 112 113 /** 114 * Sets the range and value of the slider. 115 * 116 * @param {number} minimum the minimum allowed value 117 * @param {number} maximum the maximum allowed value 118 * @param {number} value the value 119 * @param {boolean} notify if <code>true</code>, notify change listeners of the new value 120 */ 121 DwtSlider.prototype.setRange = 122 function(minimum, maximum, newValue, notify) { 123 if (minimum >= maximum) { 124 throw new DwtException("Invalid slider range: [" + minimum + ", " + maximum + "]"); 125 }; 126 127 this._minimum = minimum; 128 this._maximum = maximum; 129 if (typeof newValue == "undefined") { 130 newValue = minimum; 131 } 132 this.setValue(newValue, notify); 133 }; 134 135 /** 136 * Gets the minimum allowed value. 137 * 138 * @return {number} the minimum value 139 */ 140 DwtSlider.prototype.getMinimum = 141 function() { 142 return this._minimum; 143 }; 144 145 /** 146 * Gets the maximum allowed value 147 * 148 * @return {number} the maximum value 149 */ 150 DwtSlider.prototype.getMaximum = 151 function() { 152 return this._maximum; 153 }; 154 155 /** 156 * Checks if the slider is currently dragging. 157 * 158 * @return {Boolean} <code>true</code> if the slider is dragging 159 */ 160 DwtSlider.prototype.isDragging = 161 function() { 162 return this._isDragging; 163 }; 164 165 /** 166 * Adds a change listener. 167 * 168 * @param {AjxListener} listener the listener 169 */ 170 DwtSlider.prototype.addChangeListener = 171 function(listener) { 172 this.addListener(DwtEvent.ONCHANGE, listener); 173 }; 174 175 DwtSlider.prototype._setLocation = 176 function(location, notify) { 177 var value = this._locationToValue(location); 178 this.setValue(value, notify); 179 }; 180 181 DwtSlider.prototype._getLocation = 182 function() { 183 return this._valueToLocation(this._value); 184 }; 185 186 DwtSlider.prototype._valueToLocation = 187 function(value) { 188 if (this._orientation == DwtSlider.HORIZONTAL) { 189 return (value - this._minimum) / (this._maximum - this._minimum) * (this._size - this._buttonSize); 190 } else { 191 return this._size - this._buttonSize - (value - this._minimum) / (this._maximum - this._minimum) * (this._size - this._buttonSize); 192 } 193 }; 194 195 DwtSlider.prototype._locationToValue = 196 function(location) { 197 if (this._orientation == DwtSlider.HORIZONTAL) { 198 return location / (this._size - this._buttonSize) * (this._maximum - this._minimum) + this._minimum; 199 } else { 200 return (this._size - this._buttonSize - location) / (this._size - this._buttonSize) * (this._maximum - this._minimum) + this._minimum; 201 } 202 }; 203 204 DwtSlider.prototype._calculateSizes = 205 function() { 206 var property = this._orientation == DwtSlider.HORIZONTAL ? "x" : "y"; 207 this._buttonSize = Dwt.getSize(this._getButtonElement())[property]; 208 this._size = Dwt.getSize(this.getHtmlElement())[property]; 209 if (this._buttonSize >= this._size) { 210 throw new DwtException("Invalid slider sizes"); 211 } 212 }; 213 214 DwtSlider.prototype._getButtonElement = 215 function() { 216 return document.getElementById(this._htmlElId + "_button"); 217 }; 218 219 DwtSlider.prototype._createHtml = 220 function() { 221 var element = this.getHtmlElement(); 222 var args = { id:this._htmlElId }; 223 var template = this._orientation == DwtSlider.HORIZONTAL ? 224 "dwt.Widgets#DwtHorizontalSlider" : 225 "dwt.Widgets#DwtVerticalSlider"; 226 element.innerHTML = AjxTemplate.expand(template, args); 227 this._calculateSizes(); 228 }; 229 230 DwtSlider.prototype._dragListener = 231 function(obj, a, b) { 232 var elementProperty = this._orientation == DwtSlider.HORIZONTAL ? "x" : "y"; 233 var eventProperty = this._orientation == DwtSlider.HORIZONTAL ? "docX" : "docY"; 234 if (obj.state == DwtDragTracker.STATE_START) { 235 // If clicked outside of button, move button immediately. 236 var windowLocation = Dwt.toWindow(this.getHtmlElement(), 0, 0); 237 var clickLocation = obj.mouseEv[eventProperty] - windowLocation[elementProperty]; 238 var buttonLocation = this._getLocation(); 239 if (clickLocation < buttonLocation || clickLocation > (buttonLocation + this._buttonSize)) { 240 this._setLocation(clickLocation - this._buttonSize / 2, true); 241 } 242 243 // Save the original position in the tracker's user data. 244 obj.userData = { location: this._getLocation(), value: this._value }; 245 this._isDragging = true; 246 this._moved = false; 247 } else { 248 if (obj.state == DwtDragTracker.STATE_END) { 249 this._isDragging = false; 250 } else if (obj.state == DwtDragTracker.STATE_DRAGGING) { 251 this._moved = true; 252 } 253 if (this._moved) { 254 var location = obj.userData.location + obj.delta[elementProperty]; 255 this._setLocation(location, true); 256 } 257 } 258 }; 259