OLD | NEW |
(Empty) | |
| 1 |
| 2 /** |
| 3 * Fired when the slider's value changes. |
| 4 * |
| 5 * @event value-change |
| 6 */ |
| 7 |
| 8 /** |
| 9 * Fired when the slider's immediateValue changes. |
| 10 * |
| 11 * @event immediate-value-change |
| 12 */ |
| 13 |
| 14 /** |
| 15 * Fired when the slider's value changes due to user interaction. |
| 16 * |
| 17 * Changes to the slider's value due to changes in an underlying |
| 18 * bound variable will not trigger this event. |
| 19 * |
| 20 * @event change |
| 21 */ |
| 22 |
| 23 Polymer({ |
| 24 is: 'paper-slider', |
| 25 |
| 26 behaviors: [ |
| 27 Polymer.IronRangeBehavior, |
| 28 Polymer.IronControlState |
| 29 ], |
| 30 |
| 31 properties: { |
| 32 |
| 33 /** |
| 34 * If true, the slider thumb snaps to tick marks evenly spaced based |
| 35 * on the `step` property value. |
| 36 */ |
| 37 snaps: { |
| 38 type: Boolean, |
| 39 value: false, |
| 40 notify: true |
| 41 }, |
| 42 |
| 43 /** |
| 44 * If true, a pin with numeric value label is shown when the slider thumb |
| 45 * is pressed. Use for settings for which users need to know the exact |
| 46 * value of the setting. |
| 47 */ |
| 48 pin: { |
| 49 type: Boolean, |
| 50 value: false, |
| 51 notify: true |
| 52 }, |
| 53 |
| 54 /** |
| 55 * The number that represents the current secondary progress. |
| 56 */ |
| 57 secondaryProgress: { |
| 58 type: Number, |
| 59 value: 0, |
| 60 notify: true, |
| 61 observer: '_secondaryProgressChanged' |
| 62 }, |
| 63 |
| 64 /** |
| 65 * If true, an input is shown and user can use it to set the slider value. |
| 66 */ |
| 67 editable: { |
| 68 type: Boolean, |
| 69 value: false |
| 70 }, |
| 71 |
| 72 /** |
| 73 * The immediate value of the slider. This value is updated while the use
r |
| 74 * is dragging the slider. |
| 75 */ |
| 76 immediateValue: { |
| 77 type: Number, |
| 78 value: 0, |
| 79 readOnly: true |
| 80 }, |
| 81 |
| 82 /** |
| 83 * The maximum number of markers |
| 84 */ |
| 85 maxMarkers: { |
| 86 type: Number, |
| 87 value: 0, |
| 88 notify: true, |
| 89 observer: '_maxMarkersChanged' |
| 90 }, |
| 91 |
| 92 /** |
| 93 * If true, the knob is expanded |
| 94 */ |
| 95 expand: { |
| 96 type: Boolean, |
| 97 value: false, |
| 98 readOnly: true |
| 99 }, |
| 100 |
| 101 /** |
| 102 * True when the user is dragging the slider. |
| 103 */ |
| 104 dragging: { |
| 105 type: Boolean, |
| 106 value: false, |
| 107 readOnly: true |
| 108 }, |
| 109 |
| 110 transiting: { |
| 111 type: Boolean, |
| 112 value: false, |
| 113 readOnly: true |
| 114 }, |
| 115 |
| 116 markers: { |
| 117 readOnly: true, |
| 118 value: [] |
| 119 }, |
| 120 }, |
| 121 |
| 122 observers: [ |
| 123 '_updateKnob(value, min, max, snaps, step)', |
| 124 '_minChanged(min)', |
| 125 '_maxChanged(max)', |
| 126 '_valueChanged(value)', |
| 127 '_immediateValueChanged(immediateValue)' |
| 128 ], |
| 129 |
| 130 ready: function() { |
| 131 // issue polymer/polymer#1305 |
| 132 this.async(function() { |
| 133 this._updateKnob(this.value); |
| 134 this._updateInputValue(); |
| 135 }, 1); |
| 136 }, |
| 137 |
| 138 /** |
| 139 * Increases value by `step` but not above `max`. |
| 140 * @method increment |
| 141 */ |
| 142 increment: function() { |
| 143 this.value = this._clampValue(this.value + this.step); |
| 144 }, |
| 145 |
| 146 /** |
| 147 * Decreases value by `step` but not below `min`. |
| 148 * @method decrement |
| 149 */ |
| 150 decrement: function() { |
| 151 this.value = this._clampValue(this.value - this.step); |
| 152 }, |
| 153 |
| 154 _updateKnob: function(value) { |
| 155 this._positionKnob(this._calcRatio(value)); |
| 156 }, |
| 157 |
| 158 _minChanged: function() { |
| 159 this.setAttribute('aria-valuemin', this.min); |
| 160 }, |
| 161 |
| 162 _maxChanged: function() { |
| 163 this.setAttribute('aria-valuemax', this.max); |
| 164 }, |
| 165 |
| 166 _valueChanged: function() { |
| 167 this.setAttribute('aria-valuenow', this.value); |
| 168 this.fire('value-change'); |
| 169 }, |
| 170 |
| 171 _immediateValueChanged: function() { |
| 172 if (!this.dragging) { |
| 173 this.value = this.immediateValue; |
| 174 } |
| 175 this._updateInputValue(); |
| 176 this.fire('immediate-value-change'); |
| 177 }, |
| 178 |
| 179 _secondaryProgressChanged: function() { |
| 180 this.secondaryProgress = this._clampValue(this.secondaryProgress); |
| 181 }, |
| 182 |
| 183 _updateInputValue: function() { |
| 184 if (this.editable) { |
| 185 this.$$('#input').value = this.immediateValue; |
| 186 } |
| 187 }, |
| 188 |
| 189 _expandKnob: function() { |
| 190 this._setExpand(true); |
| 191 }, |
| 192 |
| 193 _resetKnob: function() { |
| 194 this._expandJob && this._expandJob.stop(); |
| 195 this._setExpand(false); |
| 196 }, |
| 197 |
| 198 _positionKnob: function(ratio) { |
| 199 this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)) || 0
); |
| 200 this._setRatio(this.snaps ? this._calcRatio(this.immediateValue) : ratio); |
| 201 this.$.sliderKnob.style.left = this.ratio * 100 + '%'; |
| 202 }, |
| 203 |
| 204 _inputChange: function() { |
| 205 this.value = this.$$('#input').value; |
| 206 this.fire('change'); |
| 207 }, |
| 208 |
| 209 _calcKnobPosition: function(ratio) { |
| 210 return (this.max - this.min) * ratio + this.min; |
| 211 }, |
| 212 |
| 213 _onTrack: function(e) { |
| 214 switch (event.detail.state) { |
| 215 case 'end': |
| 216 this._trackEnd(event); |
| 217 break; |
| 218 case 'track': |
| 219 this._trackX(event); |
| 220 break; |
| 221 case 'start': |
| 222 this._trackStart(event); |
| 223 break; |
| 224 } |
| 225 }, |
| 226 |
| 227 _trackStart: function(e) { |
| 228 this._w = this.$.sliderBar.offsetWidth; |
| 229 this._x = this.ratio * this._w; |
| 230 this._startx = this._x || 0; |
| 231 this._minx = - this._startx; |
| 232 this._maxx = this._w - this._startx; |
| 233 this.$.sliderKnob.classList.add('dragging'); |
| 234 this._setDragging(true); |
| 235 e.preventDefault(); |
| 236 }, |
| 237 |
| 238 _trackX: function(e) { |
| 239 if (!this.dragging) { |
| 240 this._trackStart(e); |
| 241 } |
| 242 var x = Math.min(this._maxx, Math.max(this._minx, e.detail.dx)); |
| 243 this._x = this._startx + x; |
| 244 this._setImmediateValue(this._calcStep( |
| 245 this._calcKnobPosition(this._x / this._w)) || 0); |
| 246 var s = this.$.sliderKnob.style; |
| 247 s.transform = s.webkitTransform = 'translate3d(' + (this.snaps ? |
| 248 (this._calcRatio(this.immediateValue) * this._w) - this._startx : x) +
'px, 0, 0)'; |
| 249 }, |
| 250 |
| 251 _trackEnd: function() { |
| 252 var s = this.$.sliderKnob.style; |
| 253 s.transform = s.webkitTransform = ''; |
| 254 this.$.sliderKnob.classList.remove('dragging'); |
| 255 this._setDragging(false); |
| 256 this._resetKnob(); |
| 257 this.value = this.immediateValue; |
| 258 this.fire('change'); |
| 259 }, |
| 260 |
| 261 _knobdown: function(e) { |
| 262 e.preventDefault(); |
| 263 this._expandKnob(); |
| 264 }, |
| 265 |
| 266 _bardown: function(e) { |
| 267 e.preventDefault(); |
| 268 this._setTransiting(true); |
| 269 this._w = this.$.sliderBar.offsetWidth; |
| 270 var rect = this.$.sliderBar.getBoundingClientRect(); |
| 271 var ratio = (e.detail.x - rect.left) / this._w; |
| 272 this._positionKnob(ratio); |
| 273 this._expandJob = this.debounce(this._expandJob, this._expandKnob, 60); |
| 274 |
| 275 this.async(function() { |
| 276 this.fire('change'); |
| 277 }); |
| 278 }, |
| 279 |
| 280 _knobTransitionEnd: function(e) { |
| 281 if (e.target === this.$.sliderKnob) { |
| 282 this._setTransiting(false); |
| 283 } |
| 284 }, |
| 285 |
| 286 _maxMarkersChanged: function(maxMarkers) { |
| 287 var l = (this.max - this.min) / this.step; |
| 288 if (!this.snaps && l > maxMarkers) { |
| 289 this._setMarkers([]); |
| 290 } else { |
| 291 this._setMarkers(new Array(l)); |
| 292 } |
| 293 }, |
| 294 |
| 295 _getClassNames: function() { |
| 296 var classes = {}; |
| 297 |
| 298 classes['disabled'] = this.disabled; |
| 299 classes['pin'] = this.pin; |
| 300 classes['snaps'] = this.snaps; |
| 301 classes['ring'] = this.immediateValue <= this.min; |
| 302 classes['expand'] = this.expand; |
| 303 classes['dragging'] = this.dragging; |
| 304 classes['transiting'] = this.transiting; |
| 305 classes['editable'] = this.editable; |
| 306 |
| 307 return Object.keys(classes).filter( |
| 308 function(className) { |
| 309 return classes[className]; |
| 310 }).join(' '); |
| 311 }, |
| 312 |
| 313 _incrementKey: function(ev, keys) { |
| 314 if (keys.key === 'end') { |
| 315 this.value = this.max; |
| 316 } else { |
| 317 this.increment(); |
| 318 } |
| 319 this.fire('change'); |
| 320 }, |
| 321 |
| 322 _decrementKey: function(ev, keys) { |
| 323 if (keys.key === 'home') { |
| 324 this.value = this.min; |
| 325 } else { |
| 326 this.decrement(); |
| 327 } |
| 328 this.fire('change'); |
| 329 } |
| 330 }) |
OLD | NEW |