checkout.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. Ext.require([
  2. 'Ext.form.*',
  3. 'Ext.data.*',
  4. 'Ext.window.MessageBox'
  5. ]);
  6. Ext.onReady(function() {
  7. var formPanel,
  8. // The data store for the State comboboxes
  9. statesStore = Ext.create('Ext.data.ArrayStore', {
  10. fields: ['abbr'],
  11. data : Ext.example.states // from states.js
  12. }),
  13. // The data store for the Month combobox
  14. monthsStore = Ext.create('Ext.data.Store', {
  15. fields: ['name', 'num'],
  16. data: (function() {
  17. var data = [];
  18. Ext.Array.forEach(Ext.Date.monthNames, function(name, i) {
  19. data[i] = {name: name, num: i + 1};
  20. });
  21. return data;
  22. })()
  23. });
  24. /**
  25. * Common change listener for the Mailing Address fields - if the checkbox to use the same
  26. * values for Billing Address is checked, this copies the values over as they change.
  27. */
  28. function onMailingAddrFieldChange(field) {
  29. var copyToBilling = formPanel.down('[name=billingSameAsMailing]').getValue();
  30. if (copyToBilling) {
  31. formPanel.down('[name=' + field.billingFieldName + ']').setValue(field.getValue());
  32. }
  33. }
  34. formPanel = Ext.widget('form', {
  35. renderTo: Ext.getBody(),
  36. title: 'Complete Check Out',
  37. frame: true,
  38. width: 550,
  39. bodyPadding: 5,
  40. fieldDefaults: {
  41. labelAlign: 'right',
  42. labelWidth: 90,
  43. msgTarget: 'qtip'
  44. },
  45. items: [
  46. // Contact info
  47. {
  48. xtype: 'fieldset',
  49. title: 'Your Contact Information',
  50. defaultType: 'textfield',
  51. layout: 'anchor',
  52. defaults: {
  53. anchor: '100%'
  54. },
  55. items: [{
  56. xtype: 'fieldcontainer',
  57. fieldLabel: 'Name',
  58. layout: 'hbox',
  59. combineErrors: true,
  60. defaultType: 'textfield',
  61. defaults: {
  62. hideLabel: 'true'
  63. },
  64. items: [{
  65. name: 'firstName',
  66. fieldLabel: 'First Name',
  67. flex: 2,
  68. emptyText: 'First',
  69. allowBlank: false
  70. }, {
  71. name: 'lastName',
  72. fieldLabel: 'Last Name',
  73. flex: 3,
  74. margins: '0 0 0 6',
  75. emptyText: 'Last',
  76. allowBlank: false
  77. }]
  78. }, {
  79. xtype: 'container',
  80. layout: 'hbox',
  81. defaultType: 'textfield',
  82. items: [{
  83. fieldLabel: 'Email Address',
  84. name: 'email',
  85. vtype: 'email',
  86. flex: 1,
  87. allowBlank: false
  88. }, {
  89. fieldLabel: 'Phone Number',
  90. labelWidth: 100,
  91. name: 'phone',
  92. width: 190,
  93. emptyText: 'xxx-xxx-xxxx',
  94. maskRe: /[\d\-]/,
  95. regex: /^\d{3}-\d{3}-\d{4}$/,
  96. regexText: 'Must be in the format xxx-xxx-xxxx'
  97. }]
  98. }]
  99. },
  100. // Mailing Address
  101. {
  102. xtype: 'fieldset',
  103. title: 'Mailing Address',
  104. defaultType: 'textfield',
  105. layout: 'anchor',
  106. defaults: {
  107. anchor: '100%'
  108. },
  109. items: [{
  110. fieldLabel: 'Street Address',
  111. name: 'mailingStreet',
  112. listeners: {change: onMailingAddrFieldChange},
  113. billingFieldName: 'billingStreet',
  114. allowBlank: false
  115. }, {
  116. xtype: 'container',
  117. layout: 'hbox',
  118. items: [{
  119. xtype: 'textfield',
  120. fieldLabel: 'City',
  121. name: 'mailingCity',
  122. listeners: {change: onMailingAddrFieldChange},
  123. billingFieldName: 'billingCity',
  124. flex: 1,
  125. allowBlank: false
  126. }, {
  127. xtype: 'combobox',
  128. name: 'mailingState',
  129. listeners: {change: onMailingAddrFieldChange},
  130. billingFieldName: 'billingState',
  131. fieldLabel: 'State',
  132. labelWidth: 50,
  133. width: 100,
  134. store: statesStore,
  135. valueField: 'abbr',
  136. displayField: 'abbr',
  137. typeAhead: true,
  138. queryMode: 'local',
  139. allowBlank: false,
  140. forceSelection: true
  141. }, {
  142. xtype: 'textfield',
  143. fieldLabel: 'Postal Code',
  144. labelWidth: 80,
  145. name: 'mailingPostalCode',
  146. listeners: {change: onMailingAddrFieldChange},
  147. billingFieldName: 'billingPostalCode',
  148. width: 160,
  149. allowBlank: false,
  150. maxLength: 10,
  151. enforceMaxLength: true,
  152. maskRe: /[\d\-]/,
  153. regex: /^\d{5}(\-\d{4})?$/,
  154. regexText: 'Must be in the format xxxxx or xxxxx-xxxx'
  155. }]
  156. }]
  157. },
  158. // Billing Address
  159. {
  160. xtype: 'fieldset',
  161. title: 'Billing Address',
  162. layout: 'anchor',
  163. defaults: {
  164. anchor: '100%'
  165. },
  166. items: [{
  167. xtype: 'checkbox',
  168. name: 'billingSameAsMailing',
  169. boxLabel: 'Same as Mailing Address?',
  170. hideLabel: true,
  171. checked: true,
  172. style: 'margin-bottom:10px',
  173. /**
  174. * Enables or disables the billing address fields according to whether the checkbox is checked.
  175. * In addition to disabling the fields, they are animated to a low opacity so they don't take
  176. * up visual attention.
  177. */
  178. handler: function(me, checked) {
  179. var fieldset = me.ownerCt;
  180. Ext.Array.forEach(fieldset.previousSibling().query('textfield'), onMailingAddrFieldChange);
  181. Ext.Array.forEach(fieldset.query('textfield'), function(field) {
  182. field.setDisabled(checked);
  183. // Animate the opacity on each field. Would be more efficient to wrap them in a container
  184. // and animate the opacity on just the single container element, but IE has a bug where
  185. // the alpha filter does not get applied on position:relative children.
  186. // This must only be applied when it is not IE6, as it has issues with opacity when cleartype
  187. // is enabled
  188. if (!Ext.isIE6) {
  189. field.el.animate({opacity: checked ? .3 : 1});
  190. }
  191. });
  192. }
  193. }, {
  194. xtype: 'textfield',
  195. fieldLabel: 'Street Address',
  196. name: 'billingStreet',
  197. //style: 'opacity:.3',
  198. disabled: true,
  199. allowBlank: false
  200. }, {
  201. xtype: 'container',
  202. layout: 'hbox',
  203. items: [{
  204. xtype: 'textfield',
  205. fieldLabel: 'City',
  206. name: 'billingCity',
  207. style: (!Ext.isIE6) ? 'opacity:.3' : '',
  208. flex: 1,
  209. disabled: true,
  210. allowBlank: false
  211. }, {
  212. xtype: 'combobox',
  213. name: 'billingState',
  214. style: (!Ext.isIE6) ? 'opacity:.3' : '',
  215. fieldLabel: 'State',
  216. labelWidth: 50,
  217. width: 100,
  218. store: statesStore,
  219. valueField: 'abbr',
  220. displayField: 'abbr',
  221. typeAhead: true,
  222. queryMode: 'local',
  223. disabled: true,
  224. allowBlank: false,
  225. forceSelection: true
  226. }, {
  227. xtype: 'textfield',
  228. fieldLabel: 'Postal Code',
  229. labelWidth: 80,
  230. name: 'billingPostalCode',
  231. style: (!Ext.isIE6) ? 'opacity:.3' : '',
  232. width: 160,
  233. disabled: true,
  234. allowBlank: false,
  235. maxLength: 10,
  236. enforceMaxLength: true,
  237. maskRe: /[\d\-]/,
  238. regex: /^\d{5}(\-\d{4})?$/,
  239. regexText: 'Must be in the format xxxxx or xxxxx-xxxx'
  240. }]
  241. }]
  242. },
  243. // Credit card info
  244. {
  245. xtype: 'fieldset',
  246. title: 'Payment',
  247. layout: 'anchor',
  248. defaults: {
  249. anchor: '100%'
  250. },
  251. items: [{
  252. xtype: 'radiogroup',
  253. anchor: 'none',
  254. layout: {
  255. autoFlex: false
  256. },
  257. defaults: {
  258. name: 'ccType',
  259. style: 'margin-right:15px'
  260. },
  261. items: [{
  262. inputValue: 'visa',
  263. boxLabel: 'VISA',
  264. checked: true
  265. }, {
  266. inputValue: 'mastercard',
  267. boxLabel: 'MasterCard'
  268. }, {
  269. inputValue: 'amex',
  270. boxLabel: 'American Express'
  271. }, {
  272. inputValue: 'discover',
  273. boxLabel: 'Discover'
  274. }]
  275. }, {
  276. xtype: 'textfield',
  277. name: 'ccName',
  278. fieldLabel: 'Name On Card',
  279. allowBlank: false
  280. }, {
  281. xtype: 'container',
  282. layout: 'hbox',
  283. items: [{
  284. xtype: 'textfield',
  285. name: 'ccNumber',
  286. fieldLabel: 'Card Number',
  287. flex: 1,
  288. allowBlank: false,
  289. minLength: 15,
  290. maxLength: 16,
  291. enforceMaxLength: true,
  292. maskRe: /\d/
  293. }, {
  294. xtype: 'fieldcontainer',
  295. fieldLabel: 'Expiration',
  296. labelWidth: 75,
  297. layout: 'hbox',
  298. width: 235,
  299. items: [{
  300. xtype: 'combobox',
  301. name: 'ccExpireMonth',
  302. displayField: 'name',
  303. valueField: 'num',
  304. queryMode: 'local',
  305. emptyText: 'Month',
  306. hideLabel: true,
  307. margins: '0 6 0 0',
  308. store: monthsStore,
  309. flex: 1,
  310. allowBlank: false,
  311. forceSelection: true
  312. }, {
  313. xtype: 'numberfield',
  314. name: 'ccExpireYear',
  315. hideLabel: true,
  316. width: 55,
  317. value: new Date().getFullYear(),
  318. minValue: new Date().getFullYear(),
  319. allowBlank: false
  320. }]
  321. }]
  322. }]
  323. }
  324. ],
  325. buttons: [{
  326. text: 'Reset',
  327. handler: function() {
  328. this.up('form').getForm().reset();
  329. }
  330. }, {
  331. text: 'Complete Purchase',
  332. width: 150,
  333. handler: function() {
  334. var form = this.up('form').getForm();
  335. if (form.isValid()) {
  336. Ext.MessageBox.alert('Submitted Values', form.getValues(true));
  337. }
  338. }
  339. }]
  340. });
  341. });