]> git.proxmox.com Git - sencha-touch.git/blob - src/src/field/Checkbox.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / src / field / Checkbox.js
1 /**
2 * The checkbox field is an enhanced version of the native browser checkbox and is great for enabling your user to
3 * choose one or more items from a set (for example choosing toppings for a pizza order). It works like any other
4 * {@link Ext.field.Field field} and is usually found in the context of a form:
5 *
6 * ## Example
7 *
8 * @example miniphone preview
9 * var form = Ext.create('Ext.form.Panel', {
10 * fullscreen: true,
11 * items: [
12 * {
13 * xtype: 'checkboxfield',
14 * name : 'tomato',
15 * label: 'Tomato',
16 * value: 'tomato',
17 * checked: true
18 * },
19 * {
20 * xtype: 'checkboxfield',
21 * name : 'salami',
22 * label: 'Salami'
23 * },
24 * {
25 * xtype: 'toolbar',
26 * docked: 'bottom',
27 * items: [
28 * { xtype: 'spacer' },
29 * {
30 * text: 'getValues',
31 * handler: function() {
32 * var form = Ext.ComponentQuery.query('formpanel')[0],
33 * values = form.getValues();
34 *
35 * Ext.Msg.alert(null,
36 * "Tomato: " + ((values.tomato) ? "yes" : "no") +
37 * "<br />Salami: " + ((values.salami) ? "yes" : "no")
38 * );
39 * }
40 * },
41 * { xtype: 'spacer' }
42 * ]
43 * }
44 * ]
45 * });
46 *
47 *
48 * The form above contains two check boxes - one for Tomato, one for Salami. We configured the Tomato checkbox to be
49 * checked immediately on load, and the Salami checkbox to be unchecked. We also specified an optional text
50 * {@link #value} that will be sent when we submit the form. We can get this value using the Form's
51 * {@link Ext.form.Panel#getValues getValues} function, or have it sent as part of the data that is sent when the
52 * form is submitted:
53 *
54 * form.getValues(); //contains a key called 'tomato' if the Tomato field is still checked
55 * form.submit(); //will send 'tomato' in the form submission data
56 *
57 * For more information regarding forms and fields, please review [Using Forms in Sencha Touch Guide](../../../components/forms.html)
58 */
59 Ext.define('Ext.field.Checkbox', {
60 extend: 'Ext.field.Field',
61 alternateClassName: 'Ext.form.Checkbox',
62
63 xtype: 'checkboxfield',
64 qsaLeftRe: /[\[]/g,
65 qsaRightRe: /[\]]/g,
66
67 isCheckbox: true,
68
69 /**
70 * @event change
71 * Fires just before the field blurs if the field value has changed.
72 * @param {Ext.field.Checkbox} this This field.
73 * @param {Boolean} newValue The new value.
74 * @param {Boolean} oldValue The original value.
75 */
76
77 /**
78 * @event check
79 * Fires when the checkbox is checked.
80 * @param {Ext.field.Checkbox} this This checkbox.
81 * @param {Ext.EventObject} e This event object.
82 */
83
84 /**
85 * @event uncheck
86 * Fires when the checkbox is unchecked.
87 * @param {Ext.field.Checkbox} this This checkbox.
88 * @param {Ext.EventObject} e This event object.
89 */
90
91 config: {
92 /**
93 * @cfg
94 * @inheritdoc
95 */
96 ui: 'checkbox',
97
98 /**
99 * @cfg {String} value The string value to submit if the item is in a checked state.
100 * @accessor
101 */
102 value: '',
103
104 /**
105 * @cfg {Boolean} checked `true` if the checkbox should render initially checked.
106 * @accessor
107 */
108 checked: false,
109
110 /**
111 * @cfg {Number} tabIndex
112 * @hide
113 */
114 tabIndex: -1,
115
116 /**
117 * @cfg
118 * @inheritdoc
119 */
120 component: {
121 xtype: 'input',
122 type: 'checkbox',
123 useMask: true,
124 cls: Ext.baseCSSPrefix + 'input-checkbox'
125 }
126
127 /**
128 * @cfg {Boolean} labelMaskTap
129 * @private
130 */
131 },
132
133 platformConfig: [{
134 theme: ['Windows', 'Blackberry', 'Blackberry103', 'Tizen'],
135 labelAlign: 'left'
136 }],
137
138 // @private
139 initialize: function() {
140 var me = this,
141 component = me.getComponent();
142
143 me.callParent();
144
145 component.on({
146 scope: me,
147 order: 'before',
148 masktap: 'onMaskTap'
149 });
150
151 component.doMaskTap = Ext.emptyFn;
152
153 me.label.on({
154 scope: me,
155 tap: 'onMaskTap'
156 });
157 },
158
159 // @private
160 doInitValue: function() {
161 var me = this,
162 initialConfig = me.getInitialConfig();
163
164 // you can have a value or checked config, but checked get priority
165 if (initialConfig.hasOwnProperty('value')) {
166 me.originalState = initialConfig.value;
167 }
168
169 if (initialConfig.hasOwnProperty('checked')) {
170 me.originalState = initialConfig.checked;
171 }
172
173 me.callParent(arguments);
174 },
175
176 // @private
177 updateInputType: function(newInputType) {
178 var component = this.getComponent();
179 if (component) {
180 component.setType(newInputType);
181 }
182 },
183
184 // @private
185 updateName: function(newName) {
186 var component = this.getComponent();
187 if (component) {
188 component.setName(newName);
189 }
190 },
191
192 /**
193 * Returns the field checked value.
194 * @return {Mixed} The field value.
195 */
196 getChecked: function() {
197 // we need to get the latest value from the {@link #input} and then update the value
198 this._checked = this.getComponent().getChecked();
199 return this._checked;
200 },
201
202 /**
203 * Returns the submit value for the checkbox which can be used when submitting forms.
204 * @return {Boolean/String} value The value of {@link #value} or `true`, if {@link #checked}.
205 */
206 getSubmitValue: function() {
207 return (this.getChecked()) ? Ext.isEmpty(this._value) ? true : this._value : null;
208 },
209
210 setChecked: function(newChecked) {
211 this.updateChecked(newChecked);
212 this._checked = newChecked;
213 },
214
215 updateChecked: function(newChecked) {
216 this.getComponent().setChecked(newChecked);
217
218 // only call onChange (which fires events) if the component has been initialized
219 if (this.initialized) {
220 this.onChange();
221 }
222 },
223
224 // @private
225 onMaskTap: function(component, e) {
226 var me = this,
227 dom = me.getComponent().input.dom;
228
229 if (me.getDisabled()) {
230 return false;
231 }
232
233 //we must manually update the input dom with the new checked value
234 dom.checked = !dom.checked;
235
236 me.onChange(e);
237
238 //return false so the mask does not disappear
239 return false;
240 },
241
242 /**
243 * Fires the `check` or `uncheck` event when the checked value of this component changes.
244 * @private
245 */
246 onChange: function(e) {
247 var me = this,
248 oldChecked = me._checked,
249 newChecked = me.getChecked();
250
251 // only fire the event when the value changes
252 if (oldChecked != newChecked) {
253 if (newChecked) {
254 me.fireEvent('check', me, e);
255 } else {
256 me.fireEvent('uncheck', me, e);
257 }
258
259 me.fireEvent('change', me, newChecked, oldChecked);
260 }
261 },
262
263 /**
264 * @method
265 * Method called when this {@link Ext.field.Checkbox} has been checked.
266 */
267 doChecked: Ext.emptyFn,
268
269 /**
270 * @method
271 * Method called when this {@link Ext.field.Checkbox} has been unchecked.
272 */
273 doUnChecked: Ext.emptyFn,
274
275 /**
276 * Returns the checked state of the checkbox.
277 * @return {Boolean} `true` if checked, `false` otherwise.
278 */
279 isChecked: function() {
280 return this.getChecked();
281 },
282
283 /**
284 * Set the checked state of the checkbox to `true`.
285 * @return {Ext.field.Checkbox} This checkbox.
286 */
287 check: function() {
288 return this.setChecked(true);
289 },
290
291 /**
292 * Set the checked state of the checkbox to `false`.
293 * @return {Ext.field.Checkbox} This checkbox.
294 */
295 uncheck: function() {
296 return this.setChecked(false);
297 },
298
299 getSameGroupFields: function() {
300 var me = this,
301 component = me.up('formpanel') || me.up('fieldset'),
302 name = me.getName(),
303 replaceLeft = me.qsaLeftRe,
304 replaceRight = me.qsaRightRe,
305 //handle baseCls with multiple class values
306 baseCls = me.getBaseCls().split(' ').join('.'),
307 components = [],
308 elements, element, i, ln;
309
310 if (!component) {
311 // <debug>
312 Ext.Logger.warn('Ext.field.Radio components must always be descendants of an Ext.form.Panel or Ext.form.FieldSet.');
313 // </debug>
314 component = Ext.Viewport;
315 }
316
317 // This is to handle ComponentQuery's lack of handling [name=foo[bar]] properly
318 name = name.replace(replaceLeft, '\\[');
319 name = name.replace(replaceRight, '\\]');
320
321 elements = Ext.query('[name=' + name + ']', component.element.dom);
322 ln = elements.length;
323 for (i = 0; i < ln; i++) {
324 element = elements[i];
325 element = Ext.fly(element).up('.' + baseCls);
326 if (element && element.id) {
327 components.push(Ext.getCmp(element.id));
328 }
329 }
330 return components;
331 },
332
333 /**
334 * Returns an array of values from the checkboxes in the group that are checked.
335 * @return {Array}
336 */
337 getGroupValues: function() {
338 var values = [];
339
340 this.getSameGroupFields().forEach(function(field) {
341 if (field.getChecked()) {
342 values.push(field.getValue());
343 }
344 });
345
346 return values;
347 },
348
349 /**
350 * Set the status of all matched checkboxes in the same group to checked.
351 * @param {Array} values An array of values.
352 * @return {Ext.field.Checkbox} This checkbox.
353 */
354 setGroupValues: function(values) {
355 this.getSameGroupFields().forEach(function(field) {
356 field.setChecked((values.indexOf(field.getValue()) !== -1));
357 });
358
359 return this;
360 },
361
362 /**
363 * Resets the status of all matched checkboxes in the same group to checked.
364 * @return {Ext.field.Checkbox} This checkbox.
365 */
366 resetGroupValues: function() {
367 this.getSameGroupFields().forEach(function(field) {
368 field.setChecked(field.originalState);
369 });
370
371 return this;
372 },
373
374 reset: function() {
375 this.setChecked(this.originalState);
376 return this;
377 }
378 });