]> git.proxmox.com Git - sencha-touch.git/blob - src/src/field/Slider.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / src / field / Slider.js
1 /**
2 * The slider is a way to allow the user to select a value from a given numerical range. You might use it for choosing
3 * a percentage, combine two of them to get min and max values, or use three of them to specify the hex values for a
4 * color. Each slider contains a single 'thumb' that can be dragged along the slider's length to change the value.
5 * Sliders are equally useful inside {@link Ext.form.Panel forms} and standalone. Here's how to quickly create a
6 * slider in form, in this case enabling a user to choose a percentage:
7 *
8 * @example
9 * Ext.create('Ext.form.Panel', {
10 * fullscreen: true,
11 * items: [
12 * {
13 * xtype: 'sliderfield',
14 * label: 'Percentage',
15 * value: 50,
16 * minValue: 0,
17 * maxValue: 100
18 * }
19 * ]
20 * });
21 *
22 * In this case we set a starting value of 50%, and defined the min and max values to be 0 and 100 respectively, giving
23 * us a percentage slider. Because this is such a common use case, the defaults for {@link #minValue} and
24 * {@link #maxValue} are already set to 0 and 100 so in the example above they could be removed.
25 *
26 * It's often useful to render sliders outside the context of a form panel too. In this example we create a slider that
27 * allows a user to choose the waist measurement of a pair of jeans. Let's say the online store we're making this for
28 * sells jeans with waist sizes from 24 inches to 60 inches in 2 inch increments - here's how we might achieve that:
29 *
30 * @example
31 * Ext.create('Ext.form.Panel', {
32 * fullscreen: true,
33 * items: [
34 * {
35 * xtype: 'sliderfield',
36 * label: 'Waist Measurement',
37 * minValue: 24,
38 * maxValue: 60,
39 * increment: 2,
40 * value: 32
41 * }
42 * ]
43 * });
44 *
45 * Now that we've got our slider, we can ask it what value it currently has and listen to events that it fires. For
46 * example, if we wanted our app to show different images for different sizes, we can listen to the {@link #change}
47 * event to be informed whenever the slider is moved:
48 *
49 * slider.on('change', function(field, newValue) {
50 * if (newValue[0] > 40) {
51 * imgComponent.setSrc('large.png');
52 * } else {
53 * imgComponent.setSrc('small.png');
54 * }
55 * }, this);
56 *
57 * Here we listened to the {@link #change} event on the slider and updated the background image of an
58 * {@link Ext.Img image component} based on what size the user selected. Of course, you can use any logic inside your
59 * event listener.
60 *
61 * For more information regarding forms and fields, please review [Using Forms in Sencha Touch Guide](../../../components/forms.html)
62 */
63 Ext.define('Ext.field.Slider', {
64 extend : 'Ext.field.Field',
65 xtype : 'sliderfield',
66 requires: ['Ext.slider.Slider'],
67 alternateClassName: 'Ext.form.Slider',
68
69 /**
70 * @event change
71 * Fires when an option selection has changed.
72 * @param {Ext.field.Slider} me
73 * @param {Ext.slider.Slider} sl Slider Component.
74 * @param {Ext.slider.Thumb} thumb
75 * @param {Number} newValue The new value of this thumb.
76 * @param {Number} oldValue The old value of this thumb.
77 */
78
79 /**
80 * @event dragstart
81 * Fires when the slider thumb starts a drag operation.
82 * @param {Ext.field.Slider} this
83 * @param {Ext.slider.Slider} sl Slider Component.
84 * @param {Ext.slider.Thumb} thumb The thumb being dragged.
85 * @param {Array} value The start value.
86 * @param {Ext.EventObject} e
87 */
88
89 /**
90 * @event drag
91 * Fires when the slider thumb starts a drag operation.
92 * @param {Ext.field.Slider} this
93 * @param {Ext.slider.Slider} sl Slider Component.
94 * @param {Ext.slider.Thumb} thumb The thumb being dragged.
95 * @param {Ext.EventObject} e
96 */
97
98 /**
99 * @event dragend
100 * Fires when the slider thumb ends a drag operation.
101 * @param {Ext.field.Slider} this
102 * @param {Ext.slider.Slider} sl Slider Component.
103 * @param {Ext.slider.Thumb} thumb The thumb being dragged.
104 * @param {Array} value The end value.
105 * @param {Ext.EventObject} e
106 */
107
108 config: {
109 /**
110 * @cfg
111 * @inheritdoc
112 */
113 cls: Ext.baseCSSPrefix + 'slider-field',
114
115 /**
116 * @cfg
117 * @inheritdoc
118 */
119 tabIndex: -1,
120
121 /**
122 * Will make this field read only, meaning it cannot be changed with used interaction.
123 * @cfg {Boolean} readOnly
124 * @accessor
125 */
126 readOnly: false
127 },
128
129 proxyConfig: {
130
131 /**
132 * @inheritdoc Ext.slider.Slider#increment
133 * @cfg {Number} increment
134 * @accessor
135 */
136 increment : 1,
137
138 /**
139 * @inheritdoc Ext.slider.Slider#value
140 * @cfg {Number/Number[]} value
141 * @accessor
142 */
143 value: 0,
144
145 /**
146 * @inheritdoc Ext.slider.Slider#minValue
147 * @cfg {Number} minValue
148 * @accessor
149 */
150 minValue: 0,
151
152 /**
153 * @inheritdoc Ext.slider.Slider#maxValue
154 * @cfg {Number} maxValue
155 * @accessor
156 */
157 maxValue: 100
158 },
159
160 /**
161 * @inheritdoc Ext.slider.Slider#values
162 * @cfg {Number/Number[]} values
163 */
164
165 constructor: function(config) {
166 config = config || {};
167
168 if (config.hasOwnProperty('values')) {
169 config.value = config.values;
170 }
171
172 this.callParent([config]);
173 this.updateMultipleState();
174 },
175
176 // @private
177 initialize: function() {
178 this.callParent();
179
180 this.getComponent().on({
181 scope: this,
182
183 change: 'onSliderChange',
184 dragstart: 'onSliderDragStart',
185 drag: 'onSliderDrag',
186 dragend: 'onSliderDragEnd'
187 });
188 },
189
190 // @private
191 applyComponent: function(config) {
192 return Ext.factory(config, Ext.slider.Slider);
193 },
194
195 // @private
196 updateComponent: function(component) {
197 this.callSuper(arguments);
198
199 component.setMinValue(this.getMinValue());
200 component.setMaxValue(this.getMaxValue());
201 },
202
203 onSliderChange: function() {
204 this.fireEvent.apply(this, [].concat('change', this, Array.prototype.slice.call(arguments)));
205 },
206
207 onSliderDragStart: function() {
208 this.fireEvent.apply(this, [].concat('dragstart', this, Array.prototype.slice.call(arguments)));
209 },
210
211 onSliderDrag: function() {
212 this.fireEvent.apply(this, [].concat('drag', this, Array.prototype.slice.call(arguments)));
213 },
214
215 onSliderDragEnd: function() {
216 this.fireEvent.apply(this, [].concat('dragend', this, Array.prototype.slice.call(arguments)));
217 },
218
219 /**
220 * Convenience method. Calls {@link #setValue}.
221 * @param {Object} value
222 */
223 setValues: function(value) {
224 this.setValue(value);
225 this.updateMultipleState();
226 },
227
228 /**
229 * Convenience method. Calls {@link #getValue}
230 * @return {Object}
231 */
232 getValues: function() {
233 return this.getValue();
234 },
235
236 reset: function() {
237 var config = this.config,
238 initialValue = (this.config.hasOwnProperty('values')) ? config.values : config.value;
239
240 this.setValue(initialValue);
241 },
242
243 doSetDisabled: function(disabled) {
244 this.callParent(arguments);
245
246 this.getComponent().setDisabled(disabled);
247 },
248
249 updateReadOnly: function(newValue) {
250 this.getComponent().setReadOnly(newValue);
251 },
252
253 isDirty : function () {
254 if (this.getDisabled()) {
255 return false;
256 }
257
258 return this.getValue() !== this.originalValue;
259 },
260
261 updateMultipleState: function() {
262 var value = this.getValue();
263 if (value && value.length > 1) {
264 this.addCls(Ext.baseCSSPrefix + 'slider-multiple');
265 }
266 }
267 });