/** * Utility class used by Ext.field.Slider. * @private */ Ext.define('Ext.slider.Slider', { extend : 'Ext.Container', alias : 'widget.slider', requires: ['Ext.slider.Thumb'], config: { // @inherit layout: null, /** * @cfg {Array} thumbs An array of {@link Ext.slider.Thumb}'s to be used in this slider. * @accessor */ thumbs: [], /** * @cfg {Number/String/Number[]/String[]} value The value(s) of the sliders {@link #thumbs}. If you pass * a number or a string, it will assume you have just 1 thumb. * @accessor */ value: 0, /** * @cfg {Number} tabIndex * @hide * @accessor */ tabIndex: -1, /** * @cfg {Number} minValue The lowest value any thumb on this slider can be set to. * @accessor */ minValue: 0, /** * @cfg {Number} maxValue The highest value any thumb on this slider can be set to. * @accessor */ maxValue: 100, /** * @cfg {Number} increment The increment by which to snap each thumb when its value changes. Defaults to 1. Any thumb movement * will be snapped to the nearest value that is a multiple of the increment (e.g. if increment is 10 and the user tries to move * the thumb to 67, it will be snapped to 70 instead) * @accessor */ increment: 1 }, // @private constructor: function(config) { config = config || {}; if (config.hasOwnProperty('values')) { config.value = config.values; } this.callParent([config]); }, // @private initialize: function() { var me = this; me.callParent(arguments); me.on({ scope: this, delegate: 'thumb', change: 'onChange' }); }, // @private refreshThumbs: function() { var me = this; //loop through each of the thumbs and refresh their values var thumbs = this.getThumbs(), ln = thumbs.length, i; for (i = ln - 1; i >= 0; i--) { thumbs[i].refreshValue(); } }, // @private applyThumbs: function(thumbs) { var i, ln, config, currentThumb, instance, currentThumbs = this.getThumbs() || [], instances = []; if (thumbs && thumbs.length > 0) { //convert it into an array if it is not already if (!Ext.isArray(thumbs)) { thumbs = [thumbs]; } ln = thumbs.length; for (i = 0; i < ln; i++) { config = thumbs[i]; config.slider = this; currentThumb = currentThumbs[i]; instance = Ext.factory(config, 'Ext.slider.Thumb', currentThumb); instances.push(instance); } return instances; } return thumbs; }, // @private updateThumbs: function(newThumbs) { if (newThumbs) { this.add(newThumbs); } }, // @private applyValue: function(value) { //sync the values from the thumbs this.getValue(); //convert it into an array if it is not already if (!Ext.isArray(value)) { value = [value]; } return value; }, /** * Updates the slides {@link #thumbs} with their new value(s) */ updateValue: function(newValue) { var thumbs = this.getThumbs(), newThumbs = [], ln = newValue.length, thumb, i; //if there are no thumbs defined, create them if (thumbs.length === 0) { for (i = 0; i < ln; i++) { newThumbs.push({ value: newValue[i] }); } this.setThumbs(newThumbs); return; } //update the thumb values ln = newValue.length; for (i = ln - 1; i >= 0; i--) { thumb = thumbs[i]; if (thumb) { thumbs[i].setValue(newValue[i]); } //<debug> else { throw new Error("Ext.slider.Slider: [setValue] calling setValue() with more values than there are thumbs (" + thumbs.length + " thumb(s), " + ln +" value(s))."); } //</debug> } this._value = newValue; }, // @inherit getValue: function() { var thumbs = this.getThumbs(), ln = thumbs.length, value = [], i; //update the thumb values for (i = 0; i < ln; i++) { value.push(thumbs[i].getValue()); } this._value = value; return value; }, /** * Convience method. Calls {@link #setValue} */ setValues: function(value) { this.updateValue(this.applyValue(value)); this._value = value; }, // setValue: function(value) { // this.updateValue(this.applyValue(value)); // this._value = this._values = value; // }, /** * Convience method. Calls {@link #getValue} */ getValues: function() { return this.getValue(); }, // Sets the {@link #increment} configuration applyIncrement: function(increment) { if (increment === 0) { increment = 1; } increment = Math.abs(increment); return increment; }, // @private updateMinValue: function(newMinValue) { this.refreshThumbs(); }, // @private updateMaxValue: function(newMaxValue) { this.refreshThumbs(); }, // @private updateIncrement: function(newIncrement) { this.refreshThumbs(); }, /** * Returns an instance of a thumb for a specifed index * @param {Number} index The index of the thumb (defaults to 0) * @return {Ext.slider.Thumb} The thumb instance */ getThumb: function(index) { var thumbs = this.getThumbs(); return thumbs[index || 0]; }, /** * Finds the closest thumb for a specified value * @return {Ext.slider.Thumb} The thumb */ getClosestThumb: function(value) { var thumbs = this.getThumbs(), ln = thumbs.length, thumb = thumbs[0], difference = Infinity, thumbDifference, thumbValue, i; if (ln == 1) { return thumb; } // loop through each of thumbs and find the one with the least amount of difference for (i = 0; i < ln; i++) { thumbValue = thumbs[i].getValue(); thumbDifference = Math.abs(thumbValue - value); if (thumbDifference < difference) { difference = thumbDifference; thumb = thumbs[i]; } } return thumb; }, /** * Returns the index of a specified thumb * @param {Ext.slider.Thumb} thumb * @return {Number} Index of the thumb */ indexOf: function(thumb) { return this.getThumbs().indexOf(thumb); }, /** * Returns the correct offset for a specified value, based on the {@link #minWidth}, {@link #maxWidth} and * {@link #increment} configurations * @private */ getOffsetForValue: function(value) { var me = this, minValue = me.getMinValue(), maxValue = me.getMaxValue(), range = maxValue - minValue, trackWidth = me.innerElement.getWidth(), thumbWidth = 0, thumb, ratio; thumb = me.getThumb(); if (thumb) { thumbWidth = thumb.renderElement.getWidth(); } trackWidth = trackWidth - thumbWidth; value = this.constrain(value); ratio = trackWidth / range; return Math.round((ratio * (value - minValue))); }, /** * Returns the correct value for a specified offset, based on the {@link #minWidth}, {@link #maxWidth} and * {@link #increment} configurations. Rerverse of {@link #getOffsetForValue} * @private */ getValueForOffset: function(offset, isTap) { var me = this, minValue = me.getMinValue(), maxValue = me.getMaxValue(), range = maxValue - minValue, trackWidth = me.innerElement.getWidth(), thumbWidth = 0, thumb, ratio; thumb = me.getThumb(); if (thumb) { thumbWidth = thumb.renderElement.getWidth(); } trackWidth = trackWidth - ((isTap) ? 0 : thumbWidth); ratio = range / trackWidth; return Math.round(minValue + (ratio * (offset))); }, /** * @private * Takes a desired value of a thumb and returns the nearest snap value. e.g if minValue = 0, maxValue = 100, increment = 10 and we * pass a value of 67 here, the returned value will be 70. The returned number is constrained within {@link minValue} and {@link maxValue}, * so in the above example 68 would be returned if {@link maxValue} was set to 68. * @param {Number} value The value to snap * @return {Number} The snapped value */ constrain: function(value) { var me = this, minValue = me.getMinValue(), maxValue = me.getMaxValue(), increment = me.getIncrement(), remainder = value % increment; value -= remainder; if (Math.abs(remainder) >= (increment / 2)) { value += (remainder > 0) ? increment : -increment; } value = Math.max(minValue, value); value = Math.min(maxValue, value); return value; }, /** * @private * Loops through each of the sliders {@link #thumbs} and calls disable/enable on each of them depending * on the param specified. * @param {Boolean} disable True to disable, false to enable */ setThumbsDisabled: function(disable) { var me = this, thumbs = me.getThumbs(), ln = thumbs.length, i; for (i = 0; i < ln; i++) { thumbs[i][disable ? 'disable' : 'enable'](); } }, /** * Called when the value of any child {@link #thumbs} changes. * @private */ onChange: function(thumb, value) { var thumbs = this.getThumbs(), ln = thumbs.length, thumbWidth = thumb.renderElement.getWidth(), previousThumb, offset, previousOffset, i, thumbDraggable, previousThumbDraggable; for (i = 0; i < ln; i++) { thumb = thumbs[i]; previousThumb = thumbs[i - 1]; thumbDraggable = (thumb) ? thumb.getDraggable() : null; previousThumbDraggable = (previousThumb) ? previousThumb.getDraggable() : null; if (previousThumb && thumbDraggable && previousThumbDraggable) { offset = thumbDraggable.getOffset().x; previousOffset = previousThumb.getDraggable().getOffset().x; thumbDraggable.setConstraint({ min: { x: (previousOffset === 0) ? thumbWidth : previousOffset + thumbWidth } }); previousThumbDraggable.setConstraint({ max: { x: offset - thumbWidth } }); } } this.fireEvent('change', this, thumb, value); }, doSetDisabled: function(disabled) { this.callParent(arguments); this.setThumbsDisabled(disabled); }, // @inherit reset: function() { this.setValues(this.originalValue); } });