| OLD | NEW |
| (Empty) |
| 1 <!-- | |
| 2 @license | |
| 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. | |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE | |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS | |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS | |
| 7 Code distributed by Google as part of the polymer project is also | |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS | |
| 9 --> | |
| 10 | |
| 11 <link rel="import" href="../paper-styles/paper-styles.html"> | |
| 12 <link rel="import" href="../iron-flex-layout/iron-flex-layout.html"> | |
| 13 <link rel="import" href="../iron-behaviors/iron-control-state.html"> | |
| 14 <link rel="import" href="../paper-progress/paper-progress.html"> | |
| 15 <link rel="import" href="../paper-input/paper-input.html"> | |
| 16 | |
| 17 <!-- | |
| 18 `paper-slider` allows user to select a value from a range of values by | |
| 19 moving the slider thumb. The interactive nature of the slider makes it a | |
| 20 great choice for settings that reflect intensity levels, such as volume, | |
| 21 brightness, or color saturation. | |
| 22 | |
| 23 Example: | |
| 24 | |
| 25 <paper-slider></paper-slider> | |
| 26 | |
| 27 Use `min` and `max` to specify the slider range. Default is 0 to 100. | |
| 28 | |
| 29 Example: | |
| 30 | |
| 31 <paper-slider min="10" max="200" value="110"></paper-slider> | |
| 32 | |
| 33 Styling slider: | |
| 34 | |
| 35 To change the slider progress bar color: | |
| 36 | |
| 37 paper-slider { | |
| 38 --paper-slider-active-color: #0f9d58; | |
| 39 } | |
| 40 | |
| 41 To change the slider knob color: | |
| 42 | |
| 43 paper-slider { | |
| 44 --paper-slider-knob-color: #0f9d58; | |
| 45 } | |
| 46 | |
| 47 To change the slider pin color: | |
| 48 | |
| 49 paper-slider { | |
| 50 --paper-slider-pin-color: #0f9d58; | |
| 51 } | |
| 52 | |
| 53 To change the slider pin's font color: | |
| 54 | |
| 55 paper-slider { | |
| 56 --paper-slider-pin-font-color: #0f9d58; | |
| 57 } | |
| 58 | |
| 59 To change the slider secondary progress bar color: | |
| 60 | |
| 61 paper-slider { | |
| 62 --paper-slider-secondary-color: #0f9d58; | |
| 63 } | |
| 64 | |
| 65 To change the slider disabled active color: | |
| 66 | |
| 67 paper-slider { | |
| 68 --paper-slider-disabled-active-color: #ccc; | |
| 69 } | |
| 70 | |
| 71 To change the slider disabled secondary progress bar color: | |
| 72 | |
| 73 paper-slider { | |
| 74 --paper-slider-disabled-secondary-color: #ccc; | |
| 75 } | |
| 76 | |
| 77 @group Paper Elements | |
| 78 @element paper-slider | |
| 79 @demo demo/index.html | |
| 80 @hero hero.svg | |
| 81 --> | |
| 82 | |
| 83 <dom-module id="paper-slider"> | |
| 84 <link rel="import" type="css" href="paper-slider.css"> | |
| 85 <template> | |
| 86 <template is="dom-if" if="{{!disabled}}"> | |
| 87 </template> | |
| 88 | |
| 89 <div id="sliderContainer" class$="[[_getClassNames(disabled, pin, snaps, imm
ediateValue, min, expand, dragging, transiting, editable)]]"> | |
| 90 <div class="bar-container"> | |
| 91 <paper-progress id="sliderBar" aria-hidden="true" min="[[min]]" max="[[m
ax]]" value="[[immediateValue]]" secondary-progress="[[secondaryProgress]]" | |
| 92 on-down="_bardown" on-up="_resetKnob" on-track="_onTrack"></paper-prog
ress> | |
| 93 </div> | |
| 94 | |
| 95 <template is="dom-if" if="[[snaps]]"> | |
| 96 <div class="slider-markers horizontal layout"> | |
| 97 <template is="dom-repeat" items="[[markers]]"> | |
| 98 <div class="slider-marker flex"></div> | |
| 99 </template> | |
| 100 </div> | |
| 101 </template> | |
| 102 | |
| 103 <div id="sliderKnob" on-down="_knobdown" on-up="_resetKnob" | |
| 104 on-track="_onTrack" | |
| 105 on-transitionend="_knobTransitionEnd" | |
| 106 center-justified center horizontal layout> | |
| 107 | |
| 108 <div id="sliderKnobInner" value$="[[immediateValue]]"></div> | |
| 109 </div> | |
| 110 </div> | |
| 111 | |
| 112 <template is="dom-if" if="[[editable]]"> | |
| 113 <paper-input id="input" class="slider-input" disabled$="[[disabled]]" on-c
hange="_inputChange"></paper-input> | |
| 114 </template> | |
| 115 | |
| 116 </template> | |
| 117 </dom-module> | |
| 118 | |
| 119 <script> | |
| 120 /** | |
| 121 * Fired when the slider's value changes. | |
| 122 * | |
| 123 * @event value-change | |
| 124 */ | |
| 125 | |
| 126 /** | |
| 127 * Fired when the slider's immediateValue changes. | |
| 128 * | |
| 129 * @event immediate-value-change | |
| 130 */ | |
| 131 | |
| 132 /** | |
| 133 * Fired when the slider's value changes due to user interaction. | |
| 134 * | |
| 135 * Changes to the slider's value due to changes in an underlying | |
| 136 * bound variable will not trigger this event. | |
| 137 * | |
| 138 * @event change | |
| 139 */ | |
| 140 | |
| 141 Polymer({ | |
| 142 is: 'paper-slider', | |
| 143 | |
| 144 behaviors: [ | |
| 145 Polymer.IronRangeBehavior, | |
| 146 Polymer.IronControlState | |
| 147 ], | |
| 148 | |
| 149 properties: { | |
| 150 | |
| 151 /** | |
| 152 * If true, the slider thumb snaps to tick marks evenly spaced based | |
| 153 * on the `step` property value. | |
| 154 */ | |
| 155 snaps: { | |
| 156 type: Boolean, | |
| 157 value: false, | |
| 158 notify: true | |
| 159 }, | |
| 160 | |
| 161 /** | |
| 162 * If true, a pin with numeric value label is shown when the slider thumb | |
| 163 * is pressed. Use for settings for which users need to know the exact | |
| 164 * value of the setting. | |
| 165 */ | |
| 166 pin: { | |
| 167 type: Boolean, | |
| 168 value: false, | |
| 169 notify: true | |
| 170 }, | |
| 171 | |
| 172 /** | |
| 173 * The number that represents the current secondary progress. | |
| 174 */ | |
| 175 secondaryProgress: { | |
| 176 type: Number, | |
| 177 value: 0, | |
| 178 notify: true, | |
| 179 observer: '_secondaryProgressChanged' | |
| 180 }, | |
| 181 | |
| 182 /** | |
| 183 * If true, an input is shown and user can use it to set the slider value. | |
| 184 */ | |
| 185 editable: { | |
| 186 type: Boolean, | |
| 187 value: false | |
| 188 }, | |
| 189 | |
| 190 /** | |
| 191 * The immediate value of the slider. This value is updated while the use
r | |
| 192 * is dragging the slider. | |
| 193 */ | |
| 194 immediateValue: { | |
| 195 type: Number, | |
| 196 value: 0, | |
| 197 readOnly: true | |
| 198 }, | |
| 199 | |
| 200 /** | |
| 201 * The maximum number of markers | |
| 202 */ | |
| 203 maxMarkers: { | |
| 204 type: Number, | |
| 205 value: 0, | |
| 206 notify: true, | |
| 207 observer: '_maxMarkersChanged' | |
| 208 }, | |
| 209 | |
| 210 /** | |
| 211 * If true, the knob is expanded | |
| 212 */ | |
| 213 expand: { | |
| 214 type: Boolean, | |
| 215 value: false, | |
| 216 readOnly: true | |
| 217 }, | |
| 218 | |
| 219 /** | |
| 220 * True when the user is dragging the slider. | |
| 221 */ | |
| 222 dragging: { | |
| 223 type: Boolean, | |
| 224 value: false, | |
| 225 readOnly: true | |
| 226 }, | |
| 227 | |
| 228 transiting: { | |
| 229 type: Boolean, | |
| 230 value: false, | |
| 231 readOnly: true | |
| 232 }, | |
| 233 | |
| 234 markers: { | |
| 235 readOnly: true, | |
| 236 value: [] | |
| 237 }, | |
| 238 }, | |
| 239 | |
| 240 observers: [ | |
| 241 '_updateKnob(value, min, max, snaps, step)', | |
| 242 '_minChanged(min)', | |
| 243 '_maxChanged(max)', | |
| 244 '_valueChanged(value)', | |
| 245 '_immediateValueChanged(immediateValue)' | |
| 246 ], | |
| 247 | |
| 248 ready: function() { | |
| 249 // issue polymer/polymer#1305 | |
| 250 this.async(function() { | |
| 251 this._updateKnob(this.value); | |
| 252 this._updateInputValue(); | |
| 253 }, 1); | |
| 254 }, | |
| 255 | |
| 256 /** | |
| 257 * Increases value by `step` but not above `max`. | |
| 258 * @method increment | |
| 259 */ | |
| 260 increment: function() { | |
| 261 this.value = this._clampValue(this.value + this.step); | |
| 262 }, | |
| 263 | |
| 264 /** | |
| 265 * Decreases value by `step` but not below `min`. | |
| 266 * @method decrement | |
| 267 */ | |
| 268 decrement: function() { | |
| 269 this.value = this._clampValue(this.value - this.step); | |
| 270 }, | |
| 271 | |
| 272 _updateKnob: function(value) { | |
| 273 this._positionKnob(this._calcRatio(value)); | |
| 274 }, | |
| 275 | |
| 276 _minChanged: function() { | |
| 277 this.setAttribute('aria-valuemin', this.min); | |
| 278 }, | |
| 279 | |
| 280 _maxChanged: function() { | |
| 281 this.setAttribute('aria-valuemax', this.max); | |
| 282 }, | |
| 283 | |
| 284 _valueChanged: function() { | |
| 285 this.setAttribute('aria-valuenow', this.value); | |
| 286 this.fire('value-change'); | |
| 287 }, | |
| 288 | |
| 289 _immediateValueChanged: function() { | |
| 290 if (!this.dragging) { | |
| 291 this.value = this.immediateValue; | |
| 292 } | |
| 293 this._updateInputValue(); | |
| 294 this.fire('immediate-value-change'); | |
| 295 }, | |
| 296 | |
| 297 _secondaryProgressChanged: function() { | |
| 298 this.secondaryProgress = this._clampValue(this.secondaryProgress); | |
| 299 }, | |
| 300 | |
| 301 _updateInputValue: function() { | |
| 302 if (this.editable) { | |
| 303 this.$$('#input').value = this.immediateValue; | |
| 304 } | |
| 305 }, | |
| 306 | |
| 307 _expandKnob: function() { | |
| 308 this._setExpand(true); | |
| 309 }, | |
| 310 | |
| 311 _resetKnob: function() { | |
| 312 this._expandJob && this._expandJob.stop(); | |
| 313 this._setExpand(false); | |
| 314 }, | |
| 315 | |
| 316 _positionKnob: function(ratio) { | |
| 317 this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio)) || 0
); | |
| 318 this._setRatio(this.snaps ? this._calcRatio(this.immediateValue) : ratio); | |
| 319 this.$.sliderKnob.style.left = this.ratio * 100 + '%'; | |
| 320 }, | |
| 321 | |
| 322 _inputChange: function() { | |
| 323 this.value = this.$$('#input').value; | |
| 324 this.fire('change'); | |
| 325 }, | |
| 326 | |
| 327 _calcKnobPosition: function(ratio) { | |
| 328 return (this.max - this.min) * ratio + this.min; | |
| 329 }, | |
| 330 | |
| 331 _onTrack: function(e) { | |
| 332 switch (event.detail.state) { | |
| 333 case 'end': | |
| 334 this._trackEnd(event); | |
| 335 break; | |
| 336 case 'track': | |
| 337 this._trackX(event); | |
| 338 break; | |
| 339 case 'start': | |
| 340 this._trackStart(event); | |
| 341 break; | |
| 342 } | |
| 343 }, | |
| 344 | |
| 345 _trackStart: function(e) { | |
| 346 this._w = this.$.sliderBar.offsetWidth; | |
| 347 this._x = this.ratio * this._w; | |
| 348 this._startx = this._x || 0; | |
| 349 this._minx = - this._startx; | |
| 350 this._maxx = this._w - this._startx; | |
| 351 this.$.sliderKnob.classList.add('dragging'); | |
| 352 this._setDragging(true); | |
| 353 e.preventDefault(); | |
| 354 }, | |
| 355 | |
| 356 _trackX: function(e) { | |
| 357 if (!this.dragging) { | |
| 358 this._trackStart(e); | |
| 359 } | |
| 360 var x = Math.min(this._maxx, Math.max(this._minx, e.detail.dx)); | |
| 361 this._x = this._startx + x; | |
| 362 this._setImmediateValue(this._calcStep( | |
| 363 this._calcKnobPosition(this._x / this._w)) || 0); | |
| 364 var s = this.$.sliderKnob.style; | |
| 365 s.transform = s.webkitTransform = 'translate3d(' + (this.snaps ? | |
| 366 (this._calcRatio(this.immediateValue) * this._w) - this._startx : x) +
'px, 0, 0)'; | |
| 367 }, | |
| 368 | |
| 369 _trackEnd: function() { | |
| 370 var s = this.$.sliderKnob.style; | |
| 371 s.transform = s.webkitTransform = ''; | |
| 372 this.$.sliderKnob.classList.remove('dragging'); | |
| 373 this._setDragging(false); | |
| 374 this._resetKnob(); | |
| 375 this.value = this.immediateValue; | |
| 376 this.fire('change'); | |
| 377 }, | |
| 378 | |
| 379 _knobdown: function(e) { | |
| 380 e.preventDefault(); | |
| 381 this._expandKnob(); | |
| 382 }, | |
| 383 | |
| 384 _bardown: function(e) { | |
| 385 e.preventDefault(); | |
| 386 this._setTransiting(true); | |
| 387 this._w = this.$.sliderBar.offsetWidth; | |
| 388 var rect = this.$.sliderBar.getBoundingClientRect(); | |
| 389 var ratio = (e.detail.x - rect.left) / this._w; | |
| 390 this._positionKnob(ratio); | |
| 391 this._expandJob = this.debounce(this._expandJob, this._expandKnob, 60); | |
| 392 | |
| 393 this.async(function() { | |
| 394 this.fire('change'); | |
| 395 }); | |
| 396 }, | |
| 397 | |
| 398 _knobTransitionEnd: function(e) { | |
| 399 if (e.target === this.$.sliderKnob) { | |
| 400 this._setTransiting(false); | |
| 401 } | |
| 402 }, | |
| 403 | |
| 404 _maxMarkersChanged: function(maxMarkers) { | |
| 405 var l = (this.max - this.min) / this.step; | |
| 406 if (!this.snaps && l > maxMarkers) { | |
| 407 this._setMarkers([]); | |
| 408 } else { | |
| 409 this._setMarkers(new Array(l)); | |
| 410 } | |
| 411 }, | |
| 412 | |
| 413 _getClassNames: function() { | |
| 414 var classes = {}; | |
| 415 | |
| 416 classes['disabled'] = this.disabled; | |
| 417 classes['pin'] = this.pin; | |
| 418 classes['snaps'] = this.snaps; | |
| 419 classes['ring'] = this.immediateValue <= this.min; | |
| 420 classes['expand'] = this.expand; | |
| 421 classes['dragging'] = this.dragging; | |
| 422 classes['transiting'] = this.transiting; | |
| 423 classes['editable'] = this.editable; | |
| 424 | |
| 425 return Object.keys(classes).filter( | |
| 426 function(className) { | |
| 427 return classes[className]; | |
| 428 }).join(' '); | |
| 429 }, | |
| 430 | |
| 431 _incrementKey: function(ev, keys) { | |
| 432 if (keys.key === 'end') { | |
| 433 this.value = this.max; | |
| 434 } else { | |
| 435 this.increment(); | |
| 436 } | |
| 437 this.fire('change'); | |
| 438 }, | |
| 439 | |
| 440 _decrementKey: function(ev, keys) { | |
| 441 if (keys.key === 'home') { | |
| 442 this.value = this.min; | |
| 443 } else { | |
| 444 this.decrement(); | |
| 445 } | |
| 446 this.fire('change'); | |
| 447 } | |
| 448 }) | |
| 449 </script> | |
| OLD | NEW |