]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/slider/slider-value-range.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / slider / slider-value-range.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('slider-value-range', function(Y) {
9
10 /**
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>.
14  *
15  * @module slider
16  * @submodule slider-value-range
17  */
18
19 // Constants for compression or performance
20 var MIN       = 'min',
21     MAX       = 'max',
22     VALUE     = 'value',
23
24     round = Math.round;
25
26 /**
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.
32  *
33  * @class SliderValueRange
34  */
35 function SliderValueRange() {
36     this._initSliderValueRange();
37 }
38
39 Y.SliderValueRange = Y.mix( SliderValueRange, {
40
41     // Prototype properties and methods that will be added onto host class
42     prototype: {
43
44         /**
45          * Factor used to translate value -&gt; position -&gt; value.
46          *
47          * @property _factor
48          * @type {Number}
49          * @protected
50          */
51         _factor: 1,
52
53         /**
54          * Stub for construction logic.  Override if extending this class and
55          * you need to set something up during the initializer phase.
56          *
57          * @method _initSliderValueRange
58          * @protected
59          */
60         _initSliderValueRange: function () {},
61
62         /**
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.
66          *
67          * @method _bindValueLogic
68          * @protected
69          */
70         _bindValueLogic: function () {
71             this.after( {
72                 minChange  : this._afterMinChange,
73                 maxChange  : this._afterMaxChange,
74                 valueChange: this._afterValueChange
75             } );
76         },
77
78         /**
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.
82          *
83          * @method _syncThumbPosition
84          * @protected
85          */
86         _syncThumbPosition: function () {
87             this._calculateFactor();
88
89             this._setPosition( this.get( VALUE ) );
90         },
91
92         /**
93          * Calculates and caches
94          * (range between max and min) / (rail length)
95          * for fast runtime calculation of position -&gt; value.
96          *
97          * @method _calculateFactor
98          * @protected
99          */
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 );
105
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;
112
113             this._factor = ( max - min ) / ( length - thumbSize );
114
115         },
116
117         /**
118          * Dispatch the new position of the thumb into the value setting
119          * operations.
120          *
121          * @method _defThumbMoveFn
122          * @param e { EventFacade } The host's thumbMove event
123          * @protected
124          */
125         _defThumbMoveFn: function ( e ) {
126             var previous = this.get( VALUE ),
127                 value    = this._offsetToValue( e.offset );
128
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 } );
135             }
136         },
137
138         /**
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>
142          *
143          * <p>Override this if you want to use a different value mapping
144          * algorithm.</p>
145          *
146          * @method _offsetToValue
147          * @param offset { Number } X or Y pixel offset
148          * @return { mixed } Value corresponding to the provided pixel offset
149          * @protected
150          */
151         _offsetToValue: function ( offset ) {
152
153             var value = round( offset * this._factor ) + this.get( MIN );
154
155             return round( this._nearestValue( value ) );
156         },
157
158         /**
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.
162          *
163          * @method _valueToOffset
164          * @param val { Number } The value to map to pixel X or Y position
165          * @return { Number } The pixel offset 
166          * @protected
167          */
168         _valueToOffset: function ( value ) {
169             var offset = round( ( value - this.get( MIN ) ) / this._factor );
170
171             return offset;
172         },
173
174         /**
175          * Returns the current value.  Override this if you want to introduce
176          * output formatting. Otherwise equivalent to slider.get( "value" );
177          *
178          * @method getValue
179          * @return {Number}
180          */
181         getValue: function () {
182             return this.get( VALUE );
183         },
184
185         /**
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 );
189          *
190          * @method setValue
191          * @param val {Number} The new value
192          * @return {Slider}
193          * @chainable
194          */
195         setValue: function ( val ) {
196             return this.set( VALUE, val );
197         },
198
199         /**
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.
203          *
204          * @method _afterMinChange
205          * @param e { EventFacade } The <code>min</code> attribute change event.
206          * @protected
207          */
208         _afterMinChange: function ( e ) {
209             this._verifyValue();
210
211             this._syncThumbPosition();
212         },
213
214         /**
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.
218          *
219          * @method _afterMaxChange
220          * @param e { EventFacade } The <code>max</code> attribute change event.
221          * @protected
222          */
223         _afterMaxChange: function ( e ) {
224             this._verifyValue();
225
226             this._syncThumbPosition();
227         },
228
229         /**
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
232          * closer.
233          *
234          * @method _verifyValue
235          * @protected
236          */
237         _verifyValue: function () {
238             var value   = this.get( VALUE ),
239                 nearest = this._nearestValue( value );
240
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 );
246             }
247         },
248
249         /**
250          * Propagate change to the thumb position unless the change originated
251          * from the thumbMove event.
252          *
253          * @method _afterValueChange
254          * @param e { EventFacade } The <code>valueChange</code> event.
255          * @protected
256          */
257         _afterValueChange: function ( e ) {
258             if ( !e.positioned ) {
259                 this._setPosition( e.newVal );
260             }
261         },
262
263         /**
264          * Positions the thumb in accordance with the translated value.
265          *
266          * @method _setPosition
267          * @protected
268          */
269         _setPosition: function ( value ) {
270             this._uiMoveThumb( this._valueToOffset( value ) );
271         },
272
273         /**
274          * Validates new values assigned to <code>min</code> attribute.  Numbers
275          * are acceptable.  Override this to enforce different rules.
276          *
277          * @method _validateNewMin
278          * @param value { mixed } Value assigned to <code>min</code> attribute.
279          * @return { Boolean } True for numbers.  False otherwise.
280          * @protected
281          */
282         _validateNewMin: function ( value ) {
283             return Y.Lang.isNumber( value );
284         },
285
286         /**
287          * Validates new values assigned to <code>max</code> attribute.  Numbers
288          * are acceptable.  Override this to enforce different rules.
289          *
290          * @method _validateNewMax
291          * @param value { mixed } Value assigned to <code>max</code> attribute.
292          * @return { Boolean } True for numbers.  False otherwise.
293          * @protected
294          */
295         _validateNewMax: function ( value ) {
296             return Y.Lang.isNumber( value );
297         },
298
299         /**
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.
303          *
304          * @method _setNewValue
305          * @param value { Number } Value assigned to <code>value</code> attribute
306          * @return { Number } Normalized and constrained value
307          * @protected
308          */
309         _setNewValue: function ( value ) {
310             return round( this._nearestValue( value ) );
311         },
312
313         /**
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.
318          *
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
322          * @protected
323          */
324         _nearestValue: function ( value ) {
325             var min = this.get( MIN ),
326                 max = this.get( MAX ),
327                 tmp;
328
329             // Account for reverse value range (min > max)
330             tmp = ( max > min ) ? max : min;
331             min = ( max > min ) ? min : max;
332             max = tmp;
333
334             return ( value < min ) ?
335                     min :
336                     ( value > max ) ?
337                         max :
338                         value;
339         }
340
341     },
342
343     /**
344      * Attributes that will be added onto host class.
345      *
346      * @property ATTRS
347      * @type {Object}
348      * @static
349      * @protected
350      */
351     ATTRS: {
352         /**
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.
356          *
357          * @attribute min
358          * @type { Number }
359          * @default 0
360          */
361         min: {
362             value    : 0,
363             validator: '_validateNewMin'
364         },
365
366         /**
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.
370          *
371          * @attribute max
372          * @type { Number }
373          * @default 100
374          */
375         max: {
376             value    : 100,
377             validator: '_validateNewMax'
378         },
379
380         /**
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.
385          *
386          * @attribute value
387          * @type { Number }
388          * @default (inferred from current thumb position)
389          */
390         value: {
391             value : 0,
392             setter: '_setNewValue'
393         }
394     }
395 }, true );
396
397
398 }, '3.3.0' ,{requires:['slider-base']});