/** * The slider is a way to allow the user to select a value from a given numerical range. You might use it for choosing * a percentage, combine two of them to get min and max values, or use three of them to specify the hex values for a * color. Each slider contains a single 'thumb' that can be dragged along the slider's length to change the value. * Sliders are equally useful inside {@link Ext.form.Panel forms} and standalone. Here's how to quickly create a * slider in form, in this case enabling a user to choose a percentage: * * @example * Ext.create('Ext.form.Panel', { * fullscreen: true, * items: [ * { * xtype: 'sliderfield', * label: 'Percentage', * value: 50, * minValue: 0, * maxValue: 100 * } * ] * }); * * In this case we set a starting value of 50%, and defined the min and max values to be 0 and 100 respectively, giving * us a percentage slider. Because this is such a common use case, the defaults for {@link #minValue} and * {@link #maxValue} are already set to 0 and 100 so in the example above they could be removed. * * It's often useful to render sliders outside the context of a form panel too. In this example we create a slider that * allows a user to choose the waist measurement of a pair of jeans. Let's say the online store we're making this for * sells jeans with waist sizes from 24 inches to 60 inches in 2 inch increments - here's how we might achieve that: * * @example * Ext.create('Ext.form.Panel', { * fullscreen: true, * items: [ * { * xtype: 'sliderfield', * label: 'Waist Measurement', * minValue: 24, * maxValue: 60, * increment: 2, * value: 32 * } * ] * }); * * Now that we've got our slider, we can ask it what value it currently has and listen to events that it fires. For * example, if we wanted our app to show different images for different sizes, we can listen to the {@link #change} * event to be informed whenever the slider is moved: * * slider.on('change', function(field, newValue) { * if (newValue[0] > 40) { * imgComponent.setSrc('large.png'); * } else { * imgComponent.setSrc('small.png'); * } * }, this); * * Here we listened to the {@link #change} event on the slider and updated the background image of an * {@link Ext.Img image component} based on what size the user selected. Of course, you can use any logic inside your * event listener. */Ext.define('Ext.field.Slider', { extend : 'Ext.field.Field', xtype : 'sliderfield', requires: ['Ext.slider.Slider'], alternateClassName: 'Ext.form.Slider', /** * @event change * Fires when the value changes. * @param {Ext.field.Slider} me * @param {Number[]} newValue The new value. * @param {Number[]} oldValue The old value. */ /** * @event dragchange * Fires when a thumb value changes via drag. * @param {Ext.field.Slider} me * @param {Ext.slider.Slider} sl Slider Component. * @param {Ext.slider.Thumb} thumb * @param {Number[]} newValue The new value of this thumb. * @param {Number[]} oldValue The old value of this thumb. */ /** * @event dragstart * Fires when the slider thumb starts a drag operation. * @param {Ext.field.Slider} this * @param {Ext.slider.Slider} sl Slider Component. * @param {Ext.slider.Thumb} thumb The thumb being dragged. * @param {Array} value The start value. * @param {Ext.event.Event} e */ /** * @event drag * Fires when the slider thumb starts a drag operation. * @param {Ext.field.Slider} this * @param {Ext.slider.Slider} sl Slider Component. * @param {Ext.slider.Thumb} thumb The thumb being dragged. * @param {Ext.event.Event} e */ /** * @event dragend * Fires when the slider thumb ends a drag operation. * @param {Ext.field.Slider} this * @param {Ext.slider.Slider} sl Slider Component. * @param {Ext.slider.Thumb} thumb The thumb being dragged. * @param {Array} value The end value. * @param {Ext.event.Event} e */ config: { component: { xtype: 'slider' }, /** * @cfg {Boolean} liveUpdate * `true` to fire change events while the slider is dragging. `false` will * only fire a change once the drag is complete. */ liveUpdate: false, /** * @cfg tabIndex * @inheritdoc */ tabIndex: -1, /** * Will make this field read only, meaning it cannot be changed with used interaction. * @cfg {Boolean} readOnly * @accessor */ readOnly: false, /** * @inheritdoc Ext.slider.Slider#value * @cfg {Number/Number[]} value * @accessor */ value: 0 }, classCls: Ext.baseCSSPrefix + 'sliderfield', proxyConfig: { /** * @inheritdoc Ext.slider.Slider#increment * @cfg {Number} increment * @accessor */ increment : 1, /** * @inheritdoc Ext.slider.Slider#minValue * @cfg {Number} minValue * @accessor */ minValue: 0, /** * @inheritdoc Ext.slider.Slider#maxValue * @cfg {Number} maxValue * @accessor */ maxValue: 100 }, defaultBindProperty: 'value', twoWayBindable: { values: 1, value: 1 }, /** * @inheritdoc Ext.slider.Slider#values * @cfg {Number/Number[]} values */ constructor: function(config) { config = config || {}; if (config.hasOwnProperty('values')) { config.value = config.values; } this.callParent([config]); this.updateMultipleState(); }, /** * @private */ initialize: function() { this.callParent(); this.getComponent().on({ scope: this, change: 'onSliderChange', dragstart: 'onSliderDragStart', drag: 'onSliderDrag', dragend: 'onSliderDragEnd' }); }, /** * @private */ updateComponent: function(component, oldComponent) { this.callParent([component, oldComponent]); component.setMinValue(this.getMinValue()); component.setMaxValue(this.getMaxValue()); }, applyValue: function(value, oldValue) { value = value || 0; // If we are currently dragging, don't allow the binding // to push a value over the top of what the user is doing. if (this.dragging && this.isSyncing('value')) { value = undefined; } else if (Ext.isArray(value)) { value = value.slice(0); if (oldValue && Ext.Array.equals(value, oldValue)) { value = undefined; } } else { value = [value]; } return value; }, updateValue: function(value, oldValue) { var me = this; if (!me.dragging) { me.setComponentValue(value); } if (me.initialized) { me.fireEvent('change', me, value, oldValue); } }, setComponentValue: function(value) { this.getComponent().setValue(value); }, onSliderChange: function(slider, thumb, newValue, oldValue) { this.setValue(slider.getValue()); this.fireEvent('dragchange', this, slider, thumb, newValue, oldValue); }, onSliderDragStart: function(slider, thumb, startValue, e) { this.dragging = true; this.fireEvent('dragstart', this, slider, thumb, startValue, e); }, onSliderDrag: function(slider, thumb, value, e) { var me = this; if (me.getLiveUpdate()) { me.setValue(slider.getValue()); } me.fireEvent('drag', me, slider, thumb, value, e); }, onSliderDragEnd: function(slider, thumb, startValue, e) { this.dragging = false; this.fireEvent('dragend', this, slider, thumb, startValue, e); }, /** * Convenience method. Calls {@link #setValue}. * @param {Object} value */ setValues: function(value) { this.setValue(value); this.updateMultipleState(); }, /** * Convenience method. Calls {@link #getValue} * @return {Object} */ getValues: function() { return this.getValue(); }, reset: function() { var config = this.config, initialValue = (this.config.hasOwnProperty('values')) ? config.values : config.value; this.setValue(initialValue); }, updateReadOnly: function(newValue) { this.getComponent().setReadOnly(newValue); }, isDirty : function () { if (this.getDisabled()) { return false; } return this.getValue() !== this.originalValue; }, updateMultipleState: function() { var value = this.getValue(); if (value && value.length > 1) { this.addCls(Ext.baseCSSPrefix + 'slider-multiple'); } }});