7 Polymer
.IronA11yKeysBehavior
,
8 Polymer
.PaperInkyFocusBehavior
,
9 Polymer
.IronFormElementBehavior
,
10 Polymer
.IronRangeBehavior
16 * If true, the slider thumb snaps to tick marks evenly spaced based
17 * on the `step` property value.
26 * If true, a pin with numeric value label is shown when the slider thumb
27 * is pressed. Use for settings for which users need to know the exact
28 * value of the setting.
37 * The number that represents the current secondary progress.
43 observer
: '_secondaryProgressChanged'
47 * If true, an input is shown and user can use it to set the slider value.
55 * The immediate value of the slider. This value is updated while the user
56 * is dragging the slider.
65 * The maximum number of markers
71 observer
: '_maxMarkersChanged'
75 * If true, the knob is expanded
84 * True when the user is dragging the slider.
106 '_updateKnob(value, min, max, snaps, step)',
109 '_valueChanged(value)',
110 '_immediateValueChanged(immediateValue)'
119 'left down pagedown home': '_decrementKey',
120 'right up pageup end': '_incrementKey'
124 // issue polymer/polymer#1305
125 this.async(function() {
126 this._updateKnob(this.value
);
127 this._updateInputValue();
132 * Increases value by `step` but not above `max`.
135 increment: function() {
136 this.value
= this._clampValue(this.value
+ this.step
);
140 * Decreases value by `step` but not below `min`.
143 decrement: function() {
144 this.value
= this._clampValue(this.value
- this.step
);
147 _updateKnob: function(value
) {
148 this._positionKnob(this._calcRatio(value
));
151 _minChanged: function() {
152 this.setAttribute('aria-valuemin', this.min
);
155 _maxChanged: function() {
156 this.setAttribute('aria-valuemax', this.max
);
159 _valueChanged: function() {
160 this.setAttribute('aria-valuenow', this.value
);
161 this.fire('value-change');
164 _immediateValueChanged: function() {
166 this.fire('immediate-value-change');
168 this.value
= this.immediateValue
;
170 this._updateInputValue();
173 _secondaryProgressChanged: function() {
174 this.secondaryProgress
= this._clampValue(this.secondaryProgress
);
177 _updateInputValue: function() {
179 this.$$('#input').value
= this.immediateValue
.toString();
183 _expandKnob: function() {
184 this._setExpand(true);
187 _resetKnob: function() {
188 this.cancelDebouncer('expandKnob');
189 this._setExpand(false);
192 _positionKnob: function(ratio
) {
193 this._setImmediateValue(this._calcStep(this._calcKnobPosition(ratio
)));
194 this._setRatio(this._calcRatio(this.immediateValue
));
196 this.$.sliderKnob
.style
.left
= (this.ratio
* 100) + '%';
199 _inputChange: function() {
200 this.value
= this.$$('#input').value
;
204 _calcKnobPosition: function(ratio
) {
205 return (this.max
- this.min
) * ratio
+ this.min
;
208 _onTrack: function(event
) {
209 switch (event
.detail
.state
) {
211 this._trackStart(event
);
222 _trackStart: function(event
) {
223 this._w
= this.$.sliderBar
.offsetWidth
;
224 this._x
= this.ratio
* this._w
;
225 this._startx
= this._x
|| 0;
226 this._minx
= - this._startx
;
227 this._maxx
= this._w
- this._startx
;
228 this.$.sliderKnob
.classList
.add('dragging');
230 this._setDragging(true);
233 _trackX: function(e
) {
234 if (!this.dragging
) {
238 var dx
= Math
.min(this._maxx
, Math
.max(this._minx
, e
.detail
.dx
));
239 this._x
= this._startx
+ dx
;
241 var immediateValue
= this._calcStep(this._calcKnobPosition(this._x
/ this._w
));
242 this._setImmediateValue(immediateValue
);
244 // update knob's position
245 var translateX
= ((this._calcRatio(immediateValue
) * this._w
) - this._startx
);
246 this.translate3d(translateX
+ 'px', 0, 0, this.$.sliderKnob
);
249 _trackEnd: function() {
250 var s
= this.$.sliderKnob
.style
;
252 this.$.sliderKnob
.classList
.remove('dragging');
253 this._setDragging(false);
255 this.value
= this.immediateValue
;
257 s
.transform
= s
.webkitTransform
= '';
262 _knobdown: function(event
) {
266 event
.detail
.sourceEvent
.preventDefault();
268 // set the focus manually because we will called prevent default
272 _bardown: function(event
) {
273 this._w
= this.$.sliderBar
.offsetWidth
;
274 var rect
= this.$.sliderBar
.getBoundingClientRect();
275 var ratio
= (event
.detail
.x
- rect
.left
) / this._w
;
276 var prevRatio
= this.ratio
;
278 this._setTransiting(true);
280 this._positionKnob(ratio
);
282 this.debounce('expandKnob', this._expandKnob
, 60);
284 // if the ratio doesn't change, sliderKnob's animation won't start
285 // and `_knobTransitionEnd` won't be called
286 // Therefore, we need to manually update the `transiting` state
288 if (prevRatio
=== this.ratio
) {
289 this._setTransiting(false);
292 this.async(function() {
297 event
.detail
.sourceEvent
.preventDefault();
300 _knobTransitionEnd: function(event
) {
301 if (event
.target
=== this.$.sliderKnob
) {
302 this._setTransiting(false);
306 _maxMarkersChanged: function(maxMarkers
) {
307 var l
= (this.max
- this.min
) / this.step
;
308 if (!this.snaps
&& l
> maxMarkers
) {
309 this._setMarkers([]);
311 this._setMarkers(new Array(l
));
315 _getClassNames: function() {
318 classes
.disabled
= this.disabled
;
319 classes
.pin
= this.pin
;
320 classes
.snaps
= this.snaps
;
321 classes
.ring
= this.immediateValue
<= this.min
;
322 classes
.expand
= this.expand
;
323 classes
.dragging
= this.dragging
;
324 classes
.transiting
= this.transiting
;
325 classes
.editable
= this.editable
;
327 return Object
.keys(classes
).filter(
328 function(className
) {
329 return classes
[className
];
333 _incrementKey: function(event
) {
334 if (event
.detail
.key
=== 'end') {
335 this.value
= this.max
;
342 _decrementKey: function(event
) {
343 if (event
.detail
.key
=== 'home') {
344 this.value
= this.min
;
353 * Fired when the slider's value changes.
355 * @event value-change
359 * Fired when the slider's immediateValue changes.
361 * @event immediate-value-change
365 * Fired when the slider's value changes due to user interaction.
367 * Changes to the slider's value due to changes in an underlying
368 * bound variable will not trigger this event.