]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | /**\r |
2 | * This shows an example of a common shopping cart checkout form. It demonstrates uses\r | |
3 | * of FieldContainer and various layouts for arranging and aligning fields, ComboBox\r | |
4 | * fields for state and month selection, and listening to change events to automatically\r | |
5 | * copy values from Mailing Address to Billing Address fields.\r | |
6 | */\r | |
7 | Ext.define('KitchenSink.view.form.Checkout', {\r | |
8 | extend: 'Ext.form.Panel',\r | |
9 | xtype: 'form-checkout',\r | |
10 | \r | |
11 | //<example>\r | |
12 | requires: [\r | |
13 | 'KitchenSink.model.State',\r | |
14 | 'KitchenSink.store.States'\r | |
15 | ],\r | |
16 | \r | |
17 | exampleTitle: 'Checkout Form',\r | |
18 | otherContent: [{\r | |
19 | type: 'Model',\r | |
20 | path: 'classic/samples/model/State.js'\r | |
21 | },{\r | |
22 | type: 'Data',\r | |
23 | path: 'classic/samples/data/DataSets.js'\r | |
24 | }],\r | |
25 | profiles: {\r | |
26 | classic: {\r | |
27 | formWidth: 550,\r | |
28 | normalLabelWidth: 90,\r | |
29 | longLabelWidth: 90,\r | |
30 | phoneWidth: 200,\r | |
31 | phoneLabelWidth: 100,\r | |
32 | stateWidth: 115,\r | |
33 | postalCodeLabelWidth: 80,\r | |
34 | expirationMonthWidth: 100,\r | |
35 | expirationYearWidth: 70\r | |
36 | },\r | |
37 | neptune: {\r | |
38 | formWidth: 550,\r | |
39 | normalLabelWidth: 90,\r | |
40 | longLabelWidth: 110,\r | |
41 | phoneWidth: 200,\r | |
42 | phoneLabelWidth: 100,\r | |
43 | stateWidth: 115,\r | |
44 | postalCodeLabelWidth: 80,\r | |
45 | expirationMonthWidth: 100,\r | |
46 | expirationYearWidth: 70\r | |
47 | },\r | |
48 | 'neptune-touch': {\r | |
49 | formWidth: 650,\r | |
50 | normalLabelWidth: 100,\r | |
51 | longLabelWidth: 130,\r | |
52 | phoneWidth: 230,\r | |
53 | phoneLabelWidth: 120,\r | |
54 | stateWidth: 125,\r | |
55 | postalCodeLabelWidth: 90,\r | |
56 | expirationMonthWidth: 120,\r | |
57 | expirationYearWidth: 110\r | |
58 | }\r | |
59 | },\r | |
60 | //</example>\r | |
61 | \r | |
62 | frame: true,\r | |
63 | title: 'Complete Check Out',\r | |
64 | bodyPadding: 5,\r | |
65 | \r | |
66 | initComponent: function(){\r | |
67 | var states = new Ext.data.Store({\r | |
68 | model: KitchenSink.model.State,\r | |
69 | proxy: {\r | |
70 | type: 'memory',\r | |
71 | reader: {\r | |
72 | type: 'array'\r | |
73 | }\r | |
74 | },\r | |
75 | data: KitchenSink.data.DataSets.states\r | |
76 | }),\r | |
77 | billingStates = new Ext.data.Store({\r | |
78 | model: KitchenSink.model.State,\r | |
79 | proxy: {\r | |
80 | type: 'memory',\r | |
81 | reader: {\r | |
82 | type: 'array'\r | |
83 | }\r | |
84 | },\r | |
85 | data: KitchenSink.data.DataSets.states\r | |
86 | });\r | |
87 | \r | |
88 | if (!this.monthStore) {\r | |
89 | this.self.prototype.monthStore = new Ext.data.Store({\r | |
90 | fields: ['name', 'num'],\r | |
91 | data: (function() {\r | |
92 | var data = new Array(12);\r | |
93 | Ext.Array.forEach(Ext.Date.monthNames, function(name, i) {\r | |
94 | data[i] = {name: name, num: i + 1};\r | |
95 | });\r | |
96 | return data;\r | |
97 | })()\r | |
98 | });\r | |
99 | }\r | |
100 | \r | |
101 | Ext.apply(this, {\r | |
102 | width: this.profileInfo.formWidth,\r | |
103 | fieldDefaults: {\r | |
104 | labelAlign: 'right',\r | |
105 | labelWidth: this.profileInfo.normalLabelWidth,\r | |
106 | msgTarget: Ext.supports.Touch ? 'side' : 'qtip'\r | |
107 | },\r | |
108 | \r | |
109 | items: [{\r | |
110 | xtype: 'fieldset',\r | |
111 | title: 'Your Contact Information',\r | |
112 | defaultType: 'textfield',\r | |
113 | layout: 'anchor',\r | |
114 | defaults: {\r | |
115 | anchor: '100%'\r | |
116 | },\r | |
117 | items: [{\r | |
118 | xtype: 'fieldcontainer',\r | |
119 | fieldLabel: 'Name',\r | |
120 | layout: 'hbox',\r | |
121 | combineErrors: true,\r | |
122 | defaultType: 'textfield',\r | |
123 | defaults: {\r | |
124 | hideLabel: 'true'\r | |
125 | },\r | |
126 | items: [{\r | |
127 | name: 'firstName',\r | |
128 | fieldLabel: 'First Name',\r | |
129 | flex: 2,\r | |
130 | emptyText: 'First',\r | |
131 | allowBlank: false\r | |
132 | }, {\r | |
133 | name: 'lastName',\r | |
134 | fieldLabel: 'Last Name',\r | |
135 | flex: 3,\r | |
136 | margin: '0 0 0 6',\r | |
137 | emptyText: 'Last',\r | |
138 | allowBlank: false\r | |
139 | }]\r | |
140 | }, {\r | |
141 | xtype: 'container',\r | |
142 | layout: 'hbox',\r | |
143 | defaultType: 'textfield',\r | |
144 | margin: '0 0 5 0',\r | |
145 | items: [{\r | |
146 | fieldLabel: 'Email Address',\r | |
147 | name: 'email',\r | |
148 | vtype: 'email',\r | |
149 | flex: 1,\r | |
150 | allowBlank: false\r | |
151 | }, {\r | |
152 | fieldLabel: 'Phone Number',\r | |
153 | labelWidth: this.profileInfo.phoneLabelWidth,\r | |
154 | name: 'phone',\r | |
155 | width: this.profileInfo.phoneWidth,\r | |
156 | emptyText: 'xxx-xxx-xxxx',\r | |
157 | maskRe: /[\d\-]/,\r | |
158 | regex: /^\d{3}-\d{3}-\d{4}$/,\r | |
159 | regexText: 'Must be in the format xxx-xxx-xxxx'\r | |
160 | }]\r | |
161 | }]\r | |
162 | }, {\r | |
163 | xtype: 'fieldset',\r | |
164 | title: 'Mailing Address',\r | |
165 | defaultType: 'textfield',\r | |
166 | layout: 'anchor',\r | |
167 | defaults: {\r | |
168 | anchor: '100%'\r | |
169 | },\r | |
170 | items: [{\r | |
171 | labelWidth: this.profileInfo.longLabelWidth,\r | |
172 | fieldLabel: 'Street Address',\r | |
173 | name: 'mailingStreet',\r | |
174 | listeners: {\r | |
175 | scope: this,\r | |
176 | change: this.onMailingAddrFieldChange\r | |
177 | },\r | |
178 | billingFieldName: 'billingStreet',\r | |
179 | allowBlank: false\r | |
180 | }, {\r | |
181 | xtype: 'container',\r | |
182 | layout: 'hbox',\r | |
183 | margin: '0 0 5 0',\r | |
184 | items: [{\r | |
185 | labelWidth: this.profileInfo.longLabelWidth,\r | |
186 | xtype: 'textfield',\r | |
187 | fieldLabel: 'City',\r | |
188 | name: 'mailingCity',\r | |
189 | listeners: {\r | |
190 | scope: this,\r | |
191 | change: this.onMailingAddrFieldChange\r | |
192 | },\r | |
193 | billingFieldName: 'billingCity',\r | |
194 | flex: 1,\r | |
195 | allowBlank: false\r | |
196 | }, {\r | |
197 | xtype: 'combobox',\r | |
198 | name: 'mailingState',\r | |
199 | forceSelection: true,\r | |
200 | enforceMaxLength: true,\r | |
201 | listeners: {\r | |
202 | scope: this,\r | |
203 | change: this.onMailingAddrFieldChange\r | |
204 | },\r | |
205 | billingFieldName: 'billingState',\r | |
206 | fieldLabel: 'State',\r | |
207 | labelWidth: 50,\r | |
208 | width: this.profileInfo.stateWidth,\r | |
209 | listConfig: {\r | |
210 | minWidth: null\r | |
211 | },\r | |
212 | store: states,\r | |
213 | valueField: 'abbr',\r | |
214 | displayField: 'abbr',\r | |
215 | typeAhead: true,\r | |
216 | queryMode: 'local',\r | |
217 | allowBlank: false\r | |
218 | }, {\r | |
219 | xtype: 'textfield',\r | |
220 | fieldLabel: 'Postal Code',\r | |
221 | labelWidth: this.profileInfo.postalCodeLabelWidth,\r | |
222 | name: 'mailingPostalCode',\r | |
223 | listeners: {\r | |
224 | scope: this,\r | |
225 | change: this.onMailingAddrFieldChange\r | |
226 | },\r | |
227 | billingFieldName: 'billingPostalCode',\r | |
228 | width: 160,\r | |
229 | allowBlank: false,\r | |
230 | maxLength: 10,\r | |
231 | enforceMaxLength: true,\r | |
232 | maskRe: /[\d\-]/,\r | |
233 | regex: /^\d{5}(\-\d{4})?$/,\r | |
234 | regexText: 'Must be in the format xxxxx or xxxxx-xxxx'\r | |
235 | }]\r | |
236 | }]\r | |
237 | }, {\r | |
238 | xtype: 'fieldset',\r | |
239 | title: 'Billing Address',\r | |
240 | layout: 'anchor',\r | |
241 | defaults: {\r | |
242 | anchor: '100%'\r | |
243 | },\r | |
244 | items: [{\r | |
245 | xtype: 'checkbox',\r | |
246 | name: 'billingSameAsMailing',\r | |
247 | boxLabel: 'Same as Mailing Address?',\r | |
248 | hideLabel: true,\r | |
249 | checked: true,\r | |
250 | margin: '0 0 10 0',\r | |
251 | scope: this,\r | |
252 | handler: this.onSameAddressChange\r | |
253 | }, {\r | |
254 | labelWidth: this.profileInfo.longLabelWidth,\r | |
255 | xtype: 'textfield',\r | |
256 | fieldLabel: 'Street Address',\r | |
257 | name: 'billingStreet',\r | |
258 | style: 'opacity:.3',\r | |
259 | disabled: true,\r | |
260 | allowBlank: false\r | |
261 | }, {\r | |
262 | xtype: 'container',\r | |
263 | layout: 'hbox',\r | |
264 | margin: '0 0 5 0',\r | |
265 | items: [{\r | |
266 | labelWidth: this.profileInfo.longLabelWidth,\r | |
267 | xtype: 'textfield',\r | |
268 | fieldLabel: 'City',\r | |
269 | name: 'billingCity',\r | |
270 | style: 'opacity:.3',\r | |
271 | flex: 1,\r | |
272 | disabled: true,\r | |
273 | allowBlank: false\r | |
274 | }, {\r | |
275 | xtype: 'combobox',\r | |
276 | name: 'billingState',\r | |
277 | enforceMaxLength: true,\r | |
278 | style: 'opacity:.3',\r | |
279 | fieldLabel: 'State',\r | |
280 | labelWidth: 50,\r | |
281 | listConfig: {\r | |
282 | minWidth: null\r | |
283 | },\r | |
284 | width: this.profileInfo.stateWidth,\r | |
285 | store: billingStates,\r | |
286 | valueField: 'abbr',\r | |
287 | displayField: 'abbr',\r | |
288 | typeAhead: true,\r | |
289 | queryMode: 'local',\r | |
290 | disabled: true,\r | |
291 | allowBlank: false,\r | |
292 | forceSelection: true\r | |
293 | }, {\r | |
294 | xtype: 'textfield',\r | |
295 | fieldLabel: 'Postal Code',\r | |
296 | labelWidth: this.profileInfo.postalCodeLabelWidth,\r | |
297 | name: 'billingPostalCode',\r | |
298 | style: 'opacity:.3',\r | |
299 | width: 160,\r | |
300 | disabled: true,\r | |
301 | allowBlank: false,\r | |
302 | maxLength: 10,\r | |
303 | enforceMaxLength: true,\r | |
304 | maskRe: /[\d\-]/,\r | |
305 | regex: /^\d{5}(\-\d{4})?$/,\r | |
306 | regexText: 'Must be in the format xxxxx or xxxxx-xxxx'\r | |
307 | }]\r | |
308 | }]\r | |
309 | }, {\r | |
310 | xtype: 'fieldset',\r | |
311 | title: 'Payment',\r | |
312 | layout: 'anchor',\r | |
313 | defaults: {\r | |
314 | anchor: '100%'\r | |
315 | },\r | |
316 | items: [{\r | |
317 | xtype: 'radiogroup',\r | |
318 | layout: {\r | |
319 | autoFlex: false\r | |
320 | },\r | |
321 | defaults: {\r | |
322 | name: 'ccType',\r | |
323 | margin: '0 15 0 0'\r | |
324 | },\r | |
325 | items: [{\r | |
326 | inputValue: 'visa',\r | |
327 | boxLabel: 'VISA',\r | |
328 | checked: true\r | |
329 | }, {\r | |
330 | inputValue: 'mastercard',\r | |
331 | boxLabel: 'MasterCard'\r | |
332 | }, {\r | |
333 | inputValue: 'amex',\r | |
334 | boxLabel: 'American Express'\r | |
335 | }, {\r | |
336 | inputValue: 'discover',\r | |
337 | boxLabel: 'Discover'\r | |
338 | }]\r | |
339 | }, {\r | |
340 | xtype: 'textfield',\r | |
341 | name: 'ccName',\r | |
342 | fieldLabel: 'Name On Card',\r | |
343 | labelWidth: 110,\r | |
344 | allowBlank: false\r | |
345 | }, {\r | |
346 | xtype: 'container',\r | |
347 | layout: 'hbox',\r | |
348 | margin: '0 0 5 0',\r | |
349 | items: [{\r | |
350 | xtype: 'textfield',\r | |
351 | name: 'ccNumber',\r | |
352 | fieldLabel: 'Card Number',\r | |
353 | labelWidth: 110,\r | |
354 | flex: 1,\r | |
355 | allowBlank: false,\r | |
356 | minLength: 15,\r | |
357 | maxLength: 16,\r | |
358 | enforceMaxLength: true,\r | |
359 | maskRe: /\d/\r | |
360 | }, {\r | |
361 | xtype: 'fieldcontainer',\r | |
362 | fieldLabel: 'Expiration',\r | |
363 | labelWidth: 75,\r | |
364 | layout: 'hbox',\r | |
365 | items: [{\r | |
366 | xtype: 'combobox',\r | |
367 | name: 'ccExpireMonth',\r | |
368 | displayField: 'name',\r | |
369 | valueField: 'num',\r | |
370 | queryMode: 'local',\r | |
371 | emptyText: 'Month',\r | |
372 | hideLabel: true,\r | |
373 | margin: '0 6 0 0',\r | |
374 | store: this.monthStore,\r | |
375 | width: this.profileInfo.expirationMonthWidth,\r | |
376 | allowBlank: false,\r | |
377 | forceSelection: true\r | |
378 | }, {\r | |
379 | xtype: 'numberfield',\r | |
380 | name: 'ccExpireYear',\r | |
381 | hideLabel: true,\r | |
382 | width: this.profileInfo.expirationYearWidth,\r | |
383 | value: new Date().getFullYear(),\r | |
384 | minValue: new Date().getFullYear(),\r | |
385 | allowBlank: false\r | |
386 | }]\r | |
387 | }]\r | |
388 | }]\r | |
389 | }\r | |
390 | ],\r | |
391 | \r | |
392 | buttons: [{\r | |
393 | text: 'Reset',\r | |
394 | scope: this,\r | |
395 | handler: this.onResetClick\r | |
396 | }, {\r | |
397 | text: 'Complete Purchase',\r | |
398 | width: 150,\r | |
399 | scope: this,\r | |
400 | handler: this.onCompleteClick\r | |
401 | }]\r | |
402 | });\r | |
403 | this.callParent();\r | |
404 | },\r | |
405 | \r | |
406 | onResetClick: function(){\r | |
407 | this.getForm().reset();\r | |
408 | },\r | |
409 | \r | |
410 | onCompleteClick: function(){\r | |
411 | var form = this.getForm();\r | |
412 | if (form.isValid()) {\r | |
413 | Ext.MessageBox.alert('Submitted Values', form.getValues(true));\r | |
414 | }\r | |
415 | },\r | |
416 | \r | |
417 | onMailingAddrFieldChange: function(field){\r | |
418 | var copyToBilling = this.down('[name=billingSameAsMailing]').getValue(),\r | |
419 | copyField = this.down('[name=' + field.billingFieldName + ']');\r | |
420 | \r | |
421 | if (copyToBilling) {\r | |
422 | copyField.setValue(field.getValue());\r | |
423 | } else {\r | |
424 | copyField.clearInvalid();\r | |
425 | }\r | |
426 | },\r | |
427 | \r | |
428 | /**\r | |
429 | * Enables or disables the billing address fields according to whether the checkbox is checked.\r | |
430 | * In addition to disabling the fields, they are animated to a low opacity so they don't take\r | |
431 | * up visual attention.\r | |
432 | */\r | |
433 | onSameAddressChange: function(box, checked){\r | |
434 | var fieldset = box.ownerCt;\r | |
435 | Ext.Array.forEach(fieldset.previousSibling().query('textfield'), this.onMailingAddrFieldChange, this);\r | |
436 | Ext.Array.forEach(fieldset.query('textfield'), function(field) {\r | |
437 | field.setDisabled(checked);\r | |
438 | field.el.animate({opacity: checked ? 0.3 : 1});\r | |
439 | });\r | |
440 | }\r | |
441 | });\r |