2
Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.com/yui/license.html
8
YUI.add('slider-value-range', function(Y) {
11
* Adds value support for Slider as a range of integers between a configured
12
* minimum and maximum value. For use with <code>Y.Base.build(..)</code> to
13
* add the plumbing to <code>Y.SliderBase</code>.
16
* @submodule slider-value-range
19
// Constants for compression or performance
27
* One class of value algorithm that can be built onto SliderBase. By default,
28
* values range between 0 and 100, but you can configure these on the
29
* built Slider class by setting the <code>min</code> and <code>max</code>
30
* configurations. Set the initial value (will cause the thumb to move to the
31
* appropriate location on the rail) in configuration as well if appropriate.
33
* @class SliderValueRange
35
function SliderValueRange() {
36
this._initSliderValueRange();
39
Y.SliderValueRange = Y.mix( SliderValueRange, {
41
// Prototype properties and methods that will be added onto host class
45
* Factor used to translate value -> position -> value.
54
* Stub for construction logic. Override if extending this class and
55
* you need to set something up during the initializer phase.
57
* @method _initSliderValueRange
60
_initSliderValueRange: function () {},
63
* Override of stub method in SliderBase that is called at the end of
64
* its bindUI stage of render(). Subscribes to internal events to
65
* trigger UI and related state updates.
67
* @method _bindValueLogic
70
_bindValueLogic: function () {
72
minChange : this._afterMinChange,
73
maxChange : this._afterMaxChange,
74
valueChange: this._afterValueChange
79
* Move the thumb to appropriate position if necessary. Also resets
80
* the cached offsets and recalculates the conversion factor to
81
* translate position to value.
83
* @method _syncThumbPosition
86
_syncThumbPosition: function () {
87
this._calculateFactor();
89
this._setPosition( this.get( VALUE ) );
93
* Calculates and caches
94
* (range between max and min) / (rail length)
95
* for fast runtime calculation of position -> value.
97
* @method _calculateFactor
100
_calculateFactor: function () {
101
var length = this.get( 'length' ),
102
thumbSize = this.thumb.getStyle( this._key.dim ),
103
min = this.get( MIN ),
104
max = this.get( MAX );
106
// The default thumb width is based on Sam skin's thumb dimension.
107
// This attempts to allow for rendering off-DOM, then attaching
108
// without the need to call syncUI(). It is still recommended
109
// to call syncUI() in these cases though, just to be sure.
110
length = parseFloat( length, 10 ) || 150;
111
thumbSize = parseFloat( thumbSize, 10 ) || 15;
113
this._factor = ( max - min ) / ( length - thumbSize );
118
* Dispatch the new position of the thumb into the value setting
121
* @method _defThumbMoveFn
122
* @param e { EventFacade } The host's thumbMove event
125
_defThumbMoveFn: function ( e ) {
126
var previous = this.get( VALUE ),
127
value = this._offsetToValue( e.offset );
129
// This test avoids duplication of this.set(..) if the origin
130
// of this thumbMove is from slider.set('value',x);
131
// slider.set() -> afterValueChange -> uiMoveThumb ->
132
// fire(thumbMove) -> _defThumbMoveFn -> this.set()
133
if ( previous !== value ) {
134
this.set( VALUE, value, { positioned: true } );
139
* <p>Converts a pixel position into a value. Calculates current
140
* thumb offset from the leading edge of the rail multiplied by the
141
* ratio of <code>(max - min) / (constraining dim)</code>.</p>
143
* <p>Override this if you want to use a different value mapping
146
* @method _offsetToValue
147
* @param offset { Number } X or Y pixel offset
148
* @return { mixed } Value corresponding to the provided pixel offset
151
_offsetToValue: function ( offset ) {
153
var value = round( offset * this._factor ) + this.get( MIN );
155
return round( this._nearestValue( value ) );
159
* Converts a value into a pixel offset for use in positioning
160
* the thumb according to the reverse of the
161
* <code>_offsetToValue( xy )</code> operation.
163
* @method _valueToOffset
164
* @param val { Number } The value to map to pixel X or Y position
165
* @return { Number } The pixel offset
168
_valueToOffset: function ( value ) {
169
var offset = round( ( value - this.get( MIN ) ) / this._factor );
175
* Returns the current value. Override this if you want to introduce
176
* output formatting. Otherwise equivalent to slider.get( "value" );
181
getValue: function () {
182
return this.get( VALUE );
186
* Updates the current value. Override this if you want to introduce
187
* input value parsing or preprocessing. Otherwise equivalent to
188
* slider.set( "value", v );
191
* @param val {Number} The new value
195
setValue: function ( val ) {
196
return this.set( VALUE, val );
200
* Update position according to new min value. If the new min results
201
* in the current value being out of range, the value is set to the
202
* closer of min or max.
204
* @method _afterMinChange
205
* @param e { EventFacade } The <code>min</code> attribute change event.
208
_afterMinChange: function ( e ) {
211
this._syncThumbPosition();
215
* Update position according to new max value. If the new max results
216
* in the current value being out of range, the value is set to the
217
* closer of min or max.
219
* @method _afterMaxChange
220
* @param e { EventFacade } The <code>max</code> attribute change event.
223
_afterMaxChange: function ( e ) {
226
this._syncThumbPosition();
230
* Verifies that the current value is within the min - max range. If
231
* not, value is set to either min or max, depending on which is
234
* @method _verifyValue
237
_verifyValue: function () {
238
var value = this.get( VALUE ),
239
nearest = this._nearestValue( value );
241
if ( value !== nearest ) {
242
// @TODO Can/should valueChange, minChange, etc be queued
243
// events? To make dd.set( 'min', n ); execute after minChange
244
// subscribers before on/after valueChange subscribers.
245
this.set( VALUE, nearest );
250
* Propagate change to the thumb position unless the change originated
251
* from the thumbMove event.
253
* @method _afterValueChange
254
* @param e { EventFacade } The <code>valueChange</code> event.
257
_afterValueChange: function ( e ) {
258
if ( !e.positioned ) {
259
this._setPosition( e.newVal );
264
* Positions the thumb in accordance with the translated value.
266
* @method _setPosition
269
_setPosition: function ( value ) {
270
this._uiMoveThumb( this._valueToOffset( value ) );
274
* Validates new values assigned to <code>min</code> attribute. Numbers
275
* are acceptable. Override this to enforce different rules.
277
* @method _validateNewMin
278
* @param value { mixed } Value assigned to <code>min</code> attribute.
279
* @return { Boolean } True for numbers. False otherwise.
282
_validateNewMin: function ( value ) {
283
return Y.Lang.isNumber( value );
287
* Validates new values assigned to <code>max</code> attribute. Numbers
288
* are acceptable. Override this to enforce different rules.
290
* @method _validateNewMax
291
* @param value { mixed } Value assigned to <code>max</code> attribute.
292
* @return { Boolean } True for numbers. False otherwise.
295
_validateNewMax: function ( value ) {
296
return Y.Lang.isNumber( value );
300
* Restricts new values assigned to <code>value</code> attribute to be
301
* between the configured <code>min</code> and <code>max</code>.
302
* Rounds to nearest integer value.
304
* @method _setNewValue
305
* @param value { Number } Value assigned to <code>value</code> attribute
306
* @return { Number } Normalized and constrained value
309
_setNewValue: function ( value ) {
310
return round( this._nearestValue( value ) );
314
* Returns the nearest valid value to the value input. If the provided
315
* value is outside the min - max range, accounting for min > max
316
* scenarios, the nearest of either min or max is returned. Otherwise,
317
* the provided value is returned.
319
* @method _nearestValue
320
* @param value { mixed } Value to test against current min - max range
321
* @return { Number } Current min, max, or value if within range
324
_nearestValue: function ( value ) {
325
var min = this.get( MIN ),
326
max = this.get( MAX ),
329
// Account for reverse value range (min > max)
330
tmp = ( max > min ) ? max : min;
331
min = ( max > min ) ? min : max;
334
return ( value < min ) ?
344
* Attributes that will be added onto host class.
353
* The value associated with the farthest top, left position of the
354
* rail. Can be greater than the configured <code>max</code> if you
355
* want values to increase from right-to-left or bottom-to-top.
363
validator: '_validateNewMin'
367
* The value associated with the farthest bottom, right position of
368
* the rail. Can be less than the configured <code>min</code> if
369
* you want values to increase from right-to-left or bottom-to-top.
377
validator: '_validateNewMax'
381
* The value associated with the thumb's current position on the
382
* rail. Defaults to the value inferred from the thumb's current
383
* position. Specifying value in the constructor will move the
384
* thumb to the position that corresponds to the supplied value.
388
* @default (inferred from current thumb position)
392
setter: '_setNewValue'
398
}, '3.2.0' ,{requires:['slider-base']});