value-range.js revision fce1829c55377876814443046b7025c68b762f7c
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * Adds value support for Slider as a range of integers between a configured
a02a0a8a7eb461619931f4a0e896afa247b52c54Mark Andrews * minimum and maximum value. For use with <code>Y.Base.build(..)</code> to
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * add the plumbing to <code>Y.SliderBase</code>.
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @module slider
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @submodule slider-value-range
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews// Constants for compression or performance
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews// MINORSTEP = 'minorStep',
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews// MAJORSTEP = 'majorStep',
0756445a735e2df39bf798d8de42ae5dd030aa3bMark Andrews * One class of value algorithm that can be built onto SliderBase. By default,
0756445a735e2df39bf798d8de42ae5dd030aa3bMark Andrews * values range between 0 and 100, but you can configure these on the
a02a0a8a7eb461619931f4a0e896afa247b52c54Mark Andrews * built Slider class by setting the <code>min</code> and <code>max</code>
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * configurations. Set the initial value (will cause the thumb to move to the
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * appropriate location on the rail) in configuration as well if appropriate.
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @class SliderValueRange
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews // Prototype properties and methods that will be added onto host class
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Factor used to translate value -> position -> value.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @property _factor
a0624cf8d5711cca4e3907859fbc8062a7e460faMark Andrews * @type {Number}
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @protected
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * Stub for construction logic. Override if extending this class and
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * you need to set something up during the initializer phase.
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @method _initSliderValueRange
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @protected
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Override of stub method in SliderBase that is called at the end of
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * its bindUI stage of render(). Subscribes to internal events to
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * trigger UI and related state updates.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _bindValueLogic
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @protected
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * Move the thumb to appropriate position if necessary. Also resets
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * the cached offsets and recalculates the conversion factor to
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * translate position to value.
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * @method _syncThumbPosition
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * Calculates and caches
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * (range between max and min) / (rail length)
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * for fast runtime calculation of position -> value.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _calculateFactor
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @protected
c25080dc50542213058c240226c9f342186e6285Mark Andrews thumbSize = this.thumb.getStyle( this._key.dim ),
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews // The default thumb width is based on Sam skin's thumb dimension.
c25080dc50542213058c240226c9f342186e6285Mark Andrews // This attempts to allow for rendering off-DOM, then attaching
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews // without the need to call syncUI(). It is still recommended
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews // to call syncUI() in these cases though, just to be sure.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews this._factor = ( max - min ) / ( length - thumbSize );
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews Y.log("Calculating factor(~" + this._factor.toFixed(3) + " = (max(" + max + ") - min(" + min + ")) / (length(" + length + ") - thumb size(" + thumbSize + "))","info","slider");
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * Dispatch the new position of the thumb into the value setting
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * operations.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _defThumbMoveFn
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @param e { EventFacade } The host's thumbMove event
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @protected
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews _defThumbMoveFn: function ( e ) {
c25080dc50542213058c240226c9f342186e6285Mark Andrews // To prevent set('value', x) from looping back around
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews this.set(VALUE, this._offsetToValue(e.offset));
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * <p>Converts a pixel position into a value. Calculates current
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * thumb offset from the leading edge of the rail multiplied by the
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * ratio of <code>(max - min) / (constraining dim)</code>.</p>
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * <p>Override this if you want to use a different value mapping
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * algorithm.</p>
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _offsetToValue
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @param offset { Number } X or Y pixel offset
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @return { mixed } Value corresponding to the provided pixel offset
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @protected
5752b9e296f14034f103149f18188770c2cc5239Mark Andrews var value = round( offset * this._factor ) + this.get( MIN );
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews Y.log("Offset: " + offset + " => Value: " + value, "info", "slider");
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Converts a value into a pixel offset for use in positioning
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * the thumb according to the reverse of the
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * <code>_offsetToValue( xy )</code> operation.
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @method _valueToOffset
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @param val { Number } The value to map to pixel X or Y position
0756445a735e2df39bf798d8de42ae5dd030aa3bMark Andrews * @return { Number } The pixel offset
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @protected
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson var offset = round( ( value - this.get( MIN ) ) / this._factor );
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews Y.log("Value: " + value + " => Offset: " + offset, "info", "slider");
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * Returns the current value. Override this if you want to introduce
09344332cf7840e7e219215128fd52ea4c3d6942Mark Andrews * output formatting. Otherwise equivalent to slider.get( "value" );
fd42a013f17611b34cd49cc0abee0a6b0d251a6bMark Andrews * @method getValue
09344332cf7840e7e219215128fd52ea4c3d6942Mark Andrews * @return {Number}
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Updates the current value. Override this if you want to introduce
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * input value parsing or preprocessing. Otherwise equivalent to
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * slider.set( "value", v );
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method setValue
5752b9e296f14034f103149f18188770c2cc5239Mark Andrews * @param val {Number} The new value
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @return {Slider}
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @chainable
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Update position according to new min value. If the new min results
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * in the current value being out of range, the value is set to the
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * closer of min or max.
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * @method _afterMinChange
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson * @param e { EventFacade } The <code>min</code> attribute change event.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @protected
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson _afterMinChange: function ( e ) {
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Update position according to new max value. If the new max results
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * in the current value being out of range, the value is set to the
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * closer of min or max.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _afterMaxChange
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @param e { EventFacade } The <code>max</code> attribute change event.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington _afterMaxChange: function ( e ) {
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * Verifies that the current value is within the min - max range. If
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * not, value is set to either min or max, depending on which is
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @method _verifyValue
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington // @TODO Can/should valueChange, minChange, etc be queued
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington // events? To make dd.set( 'min', n ); execute after minChange
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington // subscribers before on/after valueChange subscribers.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * Propagate change to the thumb position unless the change originated
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * from the thumbMove event.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @method _afterValueChange
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @param e { EventFacade } The <code>valueChange</code> event.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington _afterValueChange: function ( e ) {
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington Y.log("Positioning thumb after set('value',x)","info","slider");
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington this._setPosition( val, { source: 'set' } );
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * Positions the thumb in accordance with the translated value.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @method _setPosition
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @param value {Number} Value to translate to a pixel position
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @param [options] {Object} Details object to pass to `_uiMoveThumb`
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews this._uiMoveThumb( this._valueToOffset( value ), options );
d4ef65050feac78554addf6e16a06c6e2e0bd331Brian Wellington * Validates new values assigned to <code>min</code> attribute. Numbers
d4ef65050feac78554addf6e16a06c6e2e0bd331Brian Wellington * are acceptable. Override this to enforce different rules.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @method _validateNewMin
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @param value {Any} Value assigned to <code>min</code> attribute.
d4ef65050feac78554addf6e16a06c6e2e0bd331Brian Wellington * @return {Boolean} True for numbers. False otherwise.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * Validates new values assigned to <code>max</code> attribute. Numbers
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * are acceptable. Override this to enforce different rules.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _validateNewMax
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @param value { mixed } Value assigned to <code>max</code> attribute.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @return { Boolean } True for numbers. False otherwise.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @protected
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Restricts new values assigned to <code>value</code> attribute to be
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * between the configured <code>min</code> and <code>max</code>.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * Rounds to nearest integer value.
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @method _setNewValue
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @param value { Number } Value assigned to <code>value</code> attribute
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @return { Number } Normalized and constrained value
75216e007570b8ea36b3ac9cca096bf70c0ca6f6Mark Andrews * @protected
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington return round( this._nearestValue( value ) );
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * Returns the nearest valid value to the value input. If the provided
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * value is outside the min - max range, accounting for min > max
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * scenarios, the nearest of either min or max is returned. Otherwise,
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * the provided value is returned.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @method _nearestValue
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @param value { mixed } Value to test against current min - max range
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @return { Number } Current min, max, or value if within range
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington // Account for reverse value range (min > max)
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * Attributes that will be added onto host class.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @property ATTRS
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @type {Object}
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * The value associated with the farthest top, left position of the
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * rail. Can be greater than the configured <code>max</code> if you
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * want values to increase from right-to-left or bottom-to-top.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @attribute min
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @type { Number }
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * The value associated with the farthest bottom, right position of
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * the rail. Can be less than the configured <code>min</code> if
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * you want values to increase from right-to-left or bottom-to-top.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @attribute max
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @type { Number }
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @default 100
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * amount to increment/decrement the Slider value
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * when the arrow up/down/left/right keys are pressed
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @attribute minorStep
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @type {Number}
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @default 1
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * amount to increment/decrement the Slider value
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * when the page up/down keys are pressed
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @attribute majorStep
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @type {Number}
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @default 10
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * The value associated with the thumb's current position on the
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * rail. Defaults to the value inferred from the thumb's current
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * position. Specifying value in the constructor will move the
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * thumb to the position that corresponds to the supplied value.
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @attribute value
9e3a7b0faf417a10f5f689edf288807b2d5eedc5Brian Wellington * @type { Number }
068a66979695c77359e7a9181bb3f831c965b21cMark Andrews * @default (inferred from current thumb position)