Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Unified Diff: ui/webui/resources/cr_elements/slider/slider_host_behavior.js

Issue 1967913002: Material WebUI: cr-slider element for intelligent range mapping (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@KeyboardFinish
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/webui/resources/cr_elements/slider/slider_host_behavior.js
diff --git a/ui/webui/resources/cr_elements/slider/slider_host_behavior.js b/ui/webui/resources/cr_elements/slider/slider_host_behavior.js
new file mode 100644
index 0000000000000000000000000000000000000000..87279acde804d4f91e23c747d41e6dabb7492770
--- /dev/null
+++ b/ui/webui/resources/cr_elements/slider/slider_host_behavior.js
@@ -0,0 +1,129 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * SliderHostBehavior handles data binding for paper-sliders that need to map
+ * the slider's values from a linear UI range to a range of real values. When
+ * the real value does not map exactly to a tick mark, it interpolates to the
+ * nearest tick.
+ *
+ * Sliders should be data bound as follows:
+ *
+ * <paper-slider
+ * value="[[getSliderIndexFromValue(
+ * path.to.property.value, listOfValidValues)]]"
+ * on-change="onSliderChange" on-value-change="onSliderValueChange"
+ * data-value-path="path.to.property.value"
+ * slider-tick-values="[[listOfValidValues]]">
+ * </paper-slider>
+ *
+ * In addition to the computed value binding and two events, this includes two
+ * new attributes:
+ * data-value-path: the path to the number value the slider should control
+ * slider-tick-values: an {!Array<number>} of the values the ticks represent
+ */
+
+/**
+ * paper-slider with the required annotations.
+ * @constructor
+ * @extends {PaperSliderElement}
+ */
+var SliderHostBehaviorSlider = function() {};
+/** @type {!{valuePath: string}} */
+SliderHostBehaviorSlider.prototype.dataset;
+/** @type {!Array<number>} */
+SliderHostBehaviorSlider.prototype.sliderTickValues;
+
+/** @polymerBehavior */
+var SliderHostBehavior = {
+ /**
+ * value-change is fired when the slider is first data-bound, so we can use
+ * this as a proxy for initialization.
+ * @param {!Event} e
+ */
+ onSliderValueChange: function(e) {
+ var slider = /** @type {!SliderHostBehaviorSlider} */(e.target);
+
+ // If the slider is already initialized, do nothing.
+ if (typeof slider.min != 'undefined' && typeof slider.max != 'undefined')
+ return;
+
+ // Asynchronously update so we can ensure all properties are bound.
+ this.async(this.initializeSlider_.bind(this, slider));
+ },
+
+ /**
+ * Sets the path to the value corresponding to the slider position in
+ * response to user action.
+ * @param {!Event} e Slider change event.
+ */
+ onSliderChange: function(e) {
+ var slider = /** @type {!SliderHostBehaviorSlider} */(e.target);
+ var index = slider.value;
+ var ticks = slider.sliderTickValues;
+ assert(index >= 0 && index < ticks.length);
+ this.set(slider.dataset.valuePath, ticks[index]);
+ },
+
+ /**
+ * Converts from raw values (what the ticks represent) to the slider index
+ * (where the pip should be positioned on the slider).
+ * @param {number} value Value to convert.
+ * @param {!Array<number>} ticks Array of values corresponding to ticks.
+ * @return {number}
+ */
+ getSliderIndexFromValue: function(value, ticks) {
+ // TODO
stevenjb 2016/05/11 16:37:41 TODO?
+ assert(!(typeof value != 'number' || Number.isNaN(value)))
+ //return undefined;
+ return this.findNearestIndex_(ticks, value);
+ },
+
+ /**
+ * Sets the min, max and value based on the availale ticks.
+ * @param {!PaperSliderElement} slider The slider, after data binding.
+ * @private
+ */
+ initializeSlider_: function(slider) {
+ var ticks = slider.sliderTickValues;
+ slider.min = 0;
+ slider.max = ticks.length - 1;
+
+ // Set the value in case it was originally out-of-bounds.
+ var value = /** @type {number|undefined} */(
+ this.get(slider.dataset.valuePath));
+ if (typeof value != 'undefined')
+ slider.value = this.getSliderIndexFromValue(value, ticks);
+ },
+
+ /**
+ * Returns the index of the item in |arr| closest to |value|. Same cost as
+ * Array.prototype.indexOf if an exact match exists.
+ * @param {!Array<number>} arr
+ * @param {number} value
+ * @return {number}
+ * @private
+ */
+ findNearestIndex_: function(arr, value) {
+ assert(arr.length);
+
+ // The common case has an exact match.
+ var closestIndex = arr.indexOf(value);
+ if (closestIndex != -1)
+ return closestIndex;
+
+ // No exact match. Find the element closest to |value|.
+ var minDifference = Number.MAX_VALUE;
+ for (var i = 0; i < arr.length; i++) {
+ var difference = Math.abs(arr[i] - value);
+ if (difference < minDifference) {
+ closestIndex = i;
+ minDifference = difference;
+ }
+ }
+
+ return closestIndex;
+ },
+};

Powered by Google App Engine
This is Rietveld 408576698