| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * @fileoverview |
| 7 * cr-slider wraps a paper-slider. It maps the slider's values from a linear UI |
| 8 * range to a range of real values. When |value| does not map exactly to a |
| 9 * tick mark, it interpolates to the nearest tick. |
| 10 * |
| 11 * Unlike paper-slider, there is no distinction between value and |
| 12 * immediateValue; when either changes, the |value| property is updated. |
| 13 */ |
| 14 Polymer({ |
| 15 is: 'cr-slider', |
| 16 |
| 17 properties: { |
| 18 /** The value the slider represents and controls. */ |
| 19 value: { |
| 20 type: Number, |
| 21 notify: true, |
| 22 }, |
| 23 |
| 24 /** @type {!Array<number>} Values corresponding to each tick. */ |
| 25 tickValues: Array, |
| 26 |
| 27 disabled: { |
| 28 type: Boolean, |
| 29 value: false, |
| 30 reflectToAttribute: true, |
| 31 }, |
| 32 |
| 33 snaps: { |
| 34 type: Boolean, |
| 35 value: false, |
| 36 }, |
| 37 |
| 38 maxMarkers: Number, |
| 39 }, |
| 40 |
| 41 observers: [ |
| 42 'valueChanged_(value, tickValues.*)', |
| 43 ], |
| 44 |
| 45 /** |
| 46 * Sets the |value| property to the value corresponding to the knob position |
| 47 * after a user action. |
| 48 * @private |
| 49 */ |
| 50 onSliderChange_: function() { |
| 51 this.value = this.tickValues[this.$.slider.immediateValue]; |
| 52 }, |
| 53 |
| 54 /** |
| 55 * Updates the knob position when |value| changes. If the knob is still being |
| 56 * dragged, this instead forces |value| back to the current position. |
| 57 * @private |
| 58 */ |
| 59 valueChanged_: function() { |
| 60 // First update the slider settings if |tickValues| was set. |
| 61 this.$.slider.max = this.tickValues.length - 1; |
| 62 |
| 63 if (this.$.slider.dragging && |
| 64 this.value != this.tickValues[this.$.slider.immediateValue]) { |
| 65 // The value changed outside cr-slider but we're still holding the knob, |
| 66 // so set the value back to where the knob was. |
| 67 // Async so we don't confuse Polymer's data binding. |
| 68 this.async(function() { |
| 69 this.value = this.tickValues[this.$.slider.immediateValue]; |
| 70 }); |
| 71 return; |
| 72 } |
| 73 |
| 74 // Convert from the public |value| to the slider index (where the knob |
| 75 // should be positioned on the slider). |
| 76 var sliderIndex = this.tickValues.indexOf(this.value); |
| 77 if (sliderIndex == -1) { |
| 78 // No exact match. |
| 79 sliderIndex = this.findNearestIndex_(this.tickValues, this.value); |
| 80 } |
| 81 this.$.slider.value = sliderIndex; |
| 82 }, |
| 83 |
| 84 /** |
| 85 * Returns the index of the item in |arr| closest to |value|. |
| 86 * @param {!Array<number>} arr |
| 87 * @param {number} value |
| 88 * @return {number} |
| 89 * @private |
| 90 */ |
| 91 findNearestIndex_: function(arr, value) { |
| 92 var closestIndex; |
| 93 var minDifference = Number.MAX_VALUE; |
| 94 for (var i = 0; i < arr.length; i++) { |
| 95 var difference = Math.abs(arr[i] - value); |
| 96 if (difference < minDifference) { |
| 97 closestIndex = i; |
| 98 minDifference = difference; |
| 99 } |
| 100 } |
| 101 |
| 102 assert(typeof closestIndex != 'undefined'); |
| 103 return closestIndex; |
| 104 }, |
| 105 }); |
| OLD | NEW |