Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('slider-value-range', function (Y, NAME) {
2
 
3
/**
4
 * Adds value support for Slider as a range of integers between a configured
5
 * minimum and maximum value.  For use with <code>Y.Base.build(..)</code> to
6
 * add the plumbing to <code>Y.SliderBase</code>.
7
 *
8
 * @module slider
9
 * @submodule slider-value-range
10
 */
11
 
12
// Constants for compression or performance
13
var MIN       = 'min',
14
    MAX       = 'max',
15
    VALUE     = 'value',
16
//     MINORSTEP = 'minorStep',
17
//     MAJORSTEP = 'majorStep',
18
 
19
    round = Math.round;
20
 
21
/**
22
 * One class of value algorithm that can be built onto SliderBase.  By default,
23
 * values range between 0 and 100, but you can configure these on the
24
 * built Slider class by setting the <code>min</code> and <code>max</code>
25
 * configurations.  Set the initial value (will cause the thumb to move to the
26
 * appropriate location on the rail) in configuration as well if appropriate.
27
 *
28
 * @class SliderValueRange
29
 */
30
function SliderValueRange() {
31
    this._initSliderValueRange();
32
}
33
 
34
Y.SliderValueRange = Y.mix( SliderValueRange, {
35
 
36
    // Prototype properties and methods that will be added onto host class
37
    prototype: {
38
 
39
        /**
40
         * Factor used to translate value -&gt; position -&gt; value.
41
         *
42
         * @property _factor
43
         * @type {Number}
44
         * @protected
45
         */
46
        _factor: 1,
47
 
48
        /**
49
         * Stub for construction logic.  Override if extending this class and
50
         * you need to set something up during the initializer phase.
51
         *
52
         * @method _initSliderValueRange
53
         * @protected
54
         */
55
        _initSliderValueRange: function () {},
56
 
57
        /**
58
         * Override of stub method in SliderBase that is called at the end of
59
         * its bindUI stage of render().  Subscribes to internal events to
60
         * trigger UI and related state updates.
61
         *
62
         * @method _bindValueLogic
63
         * @protected
64
         */
65
        _bindValueLogic: function () {
66
            this.after( {
67
                minChange  : this._afterMinChange,
68
                maxChange  : this._afterMaxChange,
69
                valueChange: this._afterValueChange
70
            } );
71
        },
72
 
73
        /**
74
         * Move the thumb to appropriate position if necessary.  Also resets
75
         * the cached offsets and recalculates the conversion factor to
76
         * translate position to value.
77
         *
78
         * @method _syncThumbPosition
79
         * @protected
80
         */
81
        _syncThumbPosition: function () {
82
            this._calculateFactor();
83
 
84
            this._setPosition( this.get( VALUE ) );
85
        },
86
 
87
        /**
88
         * Calculates and caches
89
         * (range between max and min) / (rail length)
90
         * for fast runtime calculation of position -&gt; value.
91
         *
92
         * @method _calculateFactor
93
         * @protected
94
         */
95
        _calculateFactor: function () {
96
            var length    = this.get( 'length' ),
97
                thumbSize = this.thumb.getStyle( this._key.dim ),
98
                min       = this.get( MIN ),
99
                max       = this.get( MAX );
100
 
101
            // The default thumb width is based on Sam skin's thumb dimension.
102
            // This attempts to allow for rendering off-DOM, then attaching
103
            // without the need to call syncUI().  It is still recommended
104
            // to call syncUI() in these cases though, just to be sure.
105
            length = parseFloat( length ) || 150;
106
            thumbSize = parseFloat( thumbSize ) || 15;
107
 
108
            this._factor = ( max - min ) / ( length - thumbSize );
109
 
110
            Y.log("Calculating factor(~" + this._factor.toFixed(3) + " = (max(" + max + ") - min(" + min + ")) / (length(" + length + ") - thumb size(" + thumbSize + "))","info","slider");
111
        },
112
 
113
        /**
114
         * Dispatch the new position of the thumb into the value setting
115
         * operations.
116
         *
117
         * @method _defThumbMoveFn
118
         * @param e { EventFacade } The host's thumbMove event
119
         * @protected
120
         */
121
        _defThumbMoveFn: function ( e ) {
122
            // To prevent set('value', x) from looping back around
123
            if (e.source !== 'set') {
124
                this.set(VALUE, this._offsetToValue(e.offset));
125
            }
126
        },
127
 
128
        /**
129
         * <p>Converts a pixel position into a value.  Calculates current
130
         * thumb offset from the leading edge of the rail multiplied by the
131
         * ratio of <code>(max - min) / (constraining dim)</code>.</p>
132
         *
133
         * <p>Override this if you want to use a different value mapping
134
         * algorithm.</p>
135
         *
136
         * @method _offsetToValue
137
         * @param offset { Number } X or Y pixel offset
138
         * @return { mixed } Value corresponding to the provided pixel offset
139
         * @protected
140
         */
141
        _offsetToValue: function ( offset ) {
142
 
143
            var value = round( offset * this._factor ) + this.get( MIN );
144
 
145
            Y.log("Offset: " + offset + " => Value: " + value, "info", "slider");
146
            return round( this._nearestValue( value ) );
147
        },
148
 
149
        /**
150
         * Converts a value into a pixel offset for use in positioning
151
         * the thumb according to the reverse of the
152
         * <code>_offsetToValue( xy )</code> operation.
153
         *
154
         * @method _valueToOffset
155
         * @param val { Number } The value to map to pixel X or Y position
156
         * @return { Number } The pixel offset
157
         * @protected
158
         */
159
        _valueToOffset: function ( value ) {
160
            var offset = round( ( value - this.get( MIN ) ) / this._factor );
161
 
162
            Y.log("Value: " + value + " => Offset: " + offset, "info", "slider");
163
            return offset;
164
        },
165
 
166
        /**
167
         * Returns the current value.  Override this if you want to introduce
168
         * output formatting. Otherwise equivalent to slider.get( "value" );
169
         *
170
         * @method getValue
171
         * @return {Number}
172
         */
173
        getValue: function () {
174
            return this.get( VALUE );
175
        },
176
 
177
        /**
178
         * Updates the current value.  Override this if you want to introduce
179
         * input value parsing or preprocessing.  Otherwise equivalent to
180
         * slider.set( "value", v );
181
         *
182
         * @method setValue
183
         * @param val {Number} The new value
184
         * @return {Slider}
185
         * @chainable
186
         */
187
        setValue: function ( val ) {
188
            return this.set( VALUE, val );
189
        },
190
 
191
        /**
192
         * Update position according to new min value.  If the new min results
193
         * in the current value being out of range, the value is set to the
194
         * closer of min or max.
195
         *
196
         * @method _afterMinChange
197
         * @param e { EventFacade } The <code>min</code> attribute change event.
198
         * @protected
199
         */
200
        _afterMinChange: function ( e ) {
201
            this._verifyValue();
202
 
203
            this._syncThumbPosition();
204
        },
205
 
206
        /**
207
         * Update position according to new max value.  If the new max results
208
         * in the current value being out of range, the value is set to the
209
         * closer of min or max.
210
         *
211
         * @method _afterMaxChange
212
         * @param e { EventFacade } The <code>max</code> attribute change event.
213
         * @protected
214
         */
215
        _afterMaxChange: function ( e ) {
216
            this._verifyValue();
217
 
218
            this._syncThumbPosition();
219
        },
220
 
221
        /**
222
         * Verifies that the current value is within the min - max range.  If
223
         * not, value is set to either min or max, depending on which is
224
         * closer.
225
         *
226
         * @method _verifyValue
227
         * @protected
228
         */
229
        _verifyValue: function () {
230
            var value   = this.get( VALUE ),
231
                nearest = this._nearestValue( value );
232
 
233
            if ( value !== nearest ) {
234
                // @TODO Can/should valueChange, minChange, etc be queued
235
                // events? To make dd.set( 'min', n ); execute after minChange
236
                // subscribers before on/after valueChange subscribers.
237
                this.set( VALUE, nearest );
238
            }
239
        },
240
 
241
        /**
242
         * Propagate change to the thumb position unless the change originated
243
         * from the thumbMove event.
244
         *
245
         * @method _afterValueChange
246
         * @param e { EventFacade } The <code>valueChange</code> event.
247
         * @protected
248
         */
249
        _afterValueChange: function ( e ) {
250
            var val = e.newVal;
251
            Y.log("Positioning thumb after set('value',x)","info","slider");
252
            this._setPosition( val, { source: 'set' } );
253
        },
254
 
255
        /**
256
         * Positions the thumb and its ARIA attributes in accordance with the
257
         * translated value.
258
         *
259
         * @method _setPosition
260
         * @param value {Number} Value to translate to a pixel position
261
         * @param [options] {Object} Details object to pass to `_uiMoveThumb`
262
         * @protected
263
         */
264
        _setPosition: function ( value, options ) {
265
            this._uiMoveThumb( this._valueToOffset( value ), options );
266
            this.thumb.set('aria-valuenow', value);
267
            this.thumb.set('aria-valuetext', value);
268
        },
269
 
270
        /**
271
         * Validates new values assigned to <code>min</code> attribute.  Numbers
272
         * are acceptable.  Override this to enforce different rules.
273
         *
274
         * @method _validateNewMin
275
         * @param value {Any} Value assigned to <code>min</code> attribute.
276
         * @return {Boolean} True for numbers.  False otherwise.
277
         * @protected
278
         */
279
        _validateNewMin: function ( value ) {
280
            return Y.Lang.isNumber( value );
281
        },
282
 
283
        /**
284
         * Validates new values assigned to <code>max</code> attribute.  Numbers
285
         * are acceptable.  Override this to enforce different rules.
286
         *
287
         * @method _validateNewMax
288
         * @param value { mixed } Value assigned to <code>max</code> attribute.
289
         * @return { Boolean } True for numbers.  False otherwise.
290
         * @protected
291
         */
292
        _validateNewMax: function ( value ) {
293
            return Y.Lang.isNumber( value );
294
        },
295
 
296
        /**
297
         * Restricts new values assigned to <code>value</code> attribute to be
298
         * between the configured <code>min</code> and <code>max</code>.
299
         * Rounds to nearest integer value.
300
         *
301
         * @method _setNewValue
302
         * @param value { Number } Value assigned to <code>value</code> attribute
303
         * @return { Number } Normalized and constrained value
304
         * @protected
305
         */
306
        _setNewValue: function ( value ) {
307
            if ( Y.Lang.isNumber( value ) ) {
308
                return round( this._nearestValue( value ) );
309
            }
310
            return Y.Attribute.INVALID_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
         * amount to increment/decrement the Slider value
382
         * when the arrow up/down/left/right keys are pressed
383
         *
384
         * @attribute minorStep
385
         * @type {Number}
386
         * @default 1
387
         */
388
        minorStep : {
389
            value: 1
390
        },
391
 
392
        /**
393
         * amount to increment/decrement the Slider value
394
         * when the page up/down keys are pressed
395
         *
396
         * @attribute majorStep
397
         * @type {Number}
398
         * @default 10
399
         */
400
        majorStep : {
401
            value: 10
402
        },
403
 
404
        /**
405
         * The value associated with the thumb's current position on the
406
         * rail. Defaults to the value inferred from the thumb's current
407
         * position. Specifying value in the constructor will move the
408
         * thumb to the position that corresponds to the supplied value.
409
         *
410
         * @attribute value
411
         * @type { Number }
412
         * @default (inferred from current thumb position)
413
         */
414
        value: {
415
            value : 0,
416
            setter: '_setNewValue'
417
        }
418
    }
419
}, true );
420
 
421
 
422
}, '3.18.1', {"requires": ["slider-base"]});