Chromium Code Reviews| 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 * SliderHostBehavior handles data binding for paper-sliders that need to map | |
| 8 * the slider's values from a linear UI range to a range of real values. When | |
| 9 * the real value does not map exactly to a tick mark, it interpolates to the | |
| 10 * nearest tick. | |
| 11 * | |
| 12 * Sliders should be data bound as follows: | |
| 13 * | |
| 14 * <paper-slider | |
| 15 * value="[[getSliderIndexFromValue( | |
| 16 * path.to.property.value, listOfValidValues)]]" | |
| 17 * on-change="onSliderChange" on-value-change="onSliderValueChange" | |
| 18 * data-value-path="path.to.property.value" | |
| 19 * slider-tick-values="[[listOfValidValues]]"> | |
| 20 * </paper-slider> | |
| 21 * | |
| 22 * In addition to the computed value binding and two events, this includes two | |
| 23 * new attributes: | |
| 24 * data-value-path: the path to the number value the slider should control | |
| 25 * slider-tick-values: an {!Array<number>} of the values the ticks represent | |
| 26 */ | |
| 27 | |
| 28 /** | |
| 29 * paper-slider with the required annotations. | |
| 30 * @constructor | |
| 31 * @extends {PaperSliderElement} | |
| 32 */ | |
| 33 var SliderHostBehaviorSlider = function() {}; | |
| 34 /** @type {!{valuePath: string}} */ | |
| 35 SliderHostBehaviorSlider.prototype.dataset; | |
| 36 /** @type {!Array<number>} */ | |
| 37 SliderHostBehaviorSlider.prototype.sliderTickValues; | |
| 38 | |
| 39 /** @polymerBehavior */ | |
| 40 var SliderHostBehavior = { | |
| 41 /** | |
| 42 * value-change is fired when the slider is first data-bound, so we can use | |
| 43 * this as a proxy for initialization. | |
| 44 * @param {!Event} e | |
| 45 */ | |
| 46 onSliderValueChange: function(e) { | |
| 47 var slider = /** @type {!SliderHostBehaviorSlider} */(e.target); | |
| 48 | |
| 49 // If the slider is already initialized, do nothing. | |
| 50 if (typeof slider.min != 'undefined' && typeof slider.max != 'undefined') | |
| 51 return; | |
| 52 | |
| 53 // Asynchronously update so we can ensure all properties are bound. | |
| 54 this.async(this.initializeSlider_.bind(this, slider)); | |
| 55 }, | |
| 56 | |
| 57 /** | |
| 58 * Sets the path to the value corresponding to the slider position in | |
| 59 * response to user action. | |
| 60 * @param {!Event} e Slider change event. | |
| 61 */ | |
| 62 onSliderChange: function(e) { | |
| 63 var slider = /** @type {!SliderHostBehaviorSlider} */(e.target); | |
| 64 var index = slider.value; | |
| 65 var ticks = slider.sliderTickValues; | |
| 66 assert(index >= 0 && index < ticks.length); | |
| 67 this.set(slider.dataset.valuePath, ticks[index]); | |
| 68 }, | |
| 69 | |
| 70 /** | |
| 71 * Converts from raw values (what the ticks represent) to the slider index | |
| 72 * (where the pip should be positioned on the slider). | |
| 73 * @param {number} value Value to convert. | |
| 74 * @param {!Array<number>} ticks Array of values corresponding to ticks. | |
| 75 * @return {number} | |
| 76 */ | |
| 77 getSliderIndexFromValue: function(value, ticks) { | |
| 78 // TODO | |
|
stevenjb
2016/05/11 16:37:41
TODO?
| |
| 79 assert(!(typeof value != 'number' || Number.isNaN(value))) | |
| 80 //return undefined; | |
| 81 return this.findNearestIndex_(ticks, value); | |
| 82 }, | |
| 83 | |
| 84 /** | |
| 85 * Sets the min, max and value based on the availale ticks. | |
| 86 * @param {!PaperSliderElement} slider The slider, after data binding. | |
| 87 * @private | |
| 88 */ | |
| 89 initializeSlider_: function(slider) { | |
| 90 var ticks = slider.sliderTickValues; | |
| 91 slider.min = 0; | |
| 92 slider.max = ticks.length - 1; | |
| 93 | |
| 94 // Set the value in case it was originally out-of-bounds. | |
| 95 var value = /** @type {number|undefined} */( | |
| 96 this.get(slider.dataset.valuePath)); | |
| 97 if (typeof value != 'undefined') | |
| 98 slider.value = this.getSliderIndexFromValue(value, ticks); | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * Returns the index of the item in |arr| closest to |value|. Same cost as | |
| 103 * Array.prototype.indexOf if an exact match exists. | |
| 104 * @param {!Array<number>} arr | |
| 105 * @param {number} value | |
| 106 * @return {number} | |
| 107 * @private | |
| 108 */ | |
| 109 findNearestIndex_: function(arr, value) { | |
| 110 assert(arr.length); | |
| 111 | |
| 112 // The common case has an exact match. | |
| 113 var closestIndex = arr.indexOf(value); | |
| 114 if (closestIndex != -1) | |
| 115 return closestIndex; | |
| 116 | |
| 117 // No exact match. Find the element closest to |value|. | |
| 118 var minDifference = Number.MAX_VALUE; | |
| 119 for (var i = 0; i < arr.length; i++) { | |
| 120 var difference = Math.abs(arr[i] - value); | |
| 121 if (difference < minDifference) { | |
| 122 closestIndex = i; | |
| 123 minDifference = difference; | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 return closestIndex; | |
| 128 }, | |
| 129 }; | |
| OLD | NEW |