Basic.html 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-form-Basic'>/**
  19. </span> * Provides input field management, validation, submission, and form loading services for the collection
  20. * of {@link Ext.form.field.Field Field} instances within a {@link Ext.container.Container}. It is recommended
  21. * that you use a {@link Ext.form.Panel} as the form container, as that has logic to automatically
  22. * hook up an instance of {@link Ext.form.Basic} (plus other conveniences related to field configuration.)
  23. *
  24. * ## Form Actions
  25. *
  26. * The Basic class delegates the handling of form loads and submits to instances of {@link Ext.form.action.Action}.
  27. * See the various Action implementations for specific details of each one's functionality, as well as the
  28. * documentation for {@link #doAction} which details the configuration options that can be specified in
  29. * each action call.
  30. *
  31. * The default submit Action is {@link Ext.form.action.Submit}, which uses an Ajax request to submit the
  32. * form's values to a configured URL. To enable normal browser submission of an Ext form, use the
  33. * {@link #standardSubmit} config option.
  34. *
  35. * ## File uploads
  36. *
  37. * File uploads are not performed using normal 'Ajax' techniques; see the description for
  38. * {@link #hasUpload} for details. If you're using file uploads you should read the method description.
  39. *
  40. * ## Example usage:
  41. *
  42. * @example
  43. * Ext.create('Ext.form.Panel', {
  44. * title: 'Basic Form',
  45. * renderTo: Ext.getBody(),
  46. * bodyPadding: 5,
  47. * width: 350,
  48. *
  49. * // Any configuration items here will be automatically passed along to
  50. * // the Ext.form.Basic instance when it gets created.
  51. *
  52. * // The form will submit an AJAX request to this URL when submitted
  53. * url: 'save-form.php',
  54. *
  55. * items: [{
  56. * xtype: 'textfield',
  57. * fieldLabel: 'Field',
  58. * name: 'theField'
  59. * }],
  60. *
  61. * buttons: [{
  62. * text: 'Submit',
  63. * handler: function() {
  64. * // The getForm() method returns the Ext.form.Basic instance:
  65. * var form = this.up('form').getForm();
  66. * if (form.isValid()) {
  67. * // Submit the Ajax request and handle the response
  68. * form.submit({
  69. * success: function(form, action) {
  70. * Ext.Msg.alert('Success', action.result.message);
  71. * },
  72. * failure: function(form, action) {
  73. * Ext.Msg.alert('Failed', action.result ? action.result.message : 'No response');
  74. * }
  75. * });
  76. * }
  77. * }
  78. * }]
  79. * });
  80. *
  81. * @docauthor Jason Johnston &lt;jason@sencha.com&gt;
  82. */
  83. Ext.define('Ext.form.Basic', {
  84. extend: 'Ext.util.Observable',
  85. alternateClassName: 'Ext.form.BasicForm',
  86. requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
  87. 'Ext.window.MessageBox', 'Ext.data.Errors', 'Ext.util.DelayedTask'],
  88. <span id='Ext-form-Basic-method-constructor'> /**
  89. </span> * Creates new form.
  90. * @param {Ext.container.Container} owner The component that is the container for the form, usually a {@link Ext.form.Panel}
  91. * @param {Object} config Configuration options. These are normally specified in the config to the
  92. * {@link Ext.form.Panel} constructor, which passes them along to the BasicForm automatically.
  93. */
  94. constructor: function(owner, config) {
  95. var me = this,
  96. onItemAddOrRemove = me.onItemAddOrRemove,
  97. api,
  98. fn;
  99. <span id='Ext-form-Basic-property-owner'> /**
  100. </span> * @property {Ext.container.Container} owner
  101. * The container component to which this BasicForm is attached.
  102. */
  103. me.owner = owner;
  104. // Listen for addition/removal of fields in the owner container
  105. me.mon(owner, {
  106. add: onItemAddOrRemove,
  107. remove: onItemAddOrRemove,
  108. scope: me
  109. });
  110. Ext.apply(me, config);
  111. // Normalize the paramOrder to an Array
  112. if (Ext.isString(me.paramOrder)) {
  113. me.paramOrder = me.paramOrder.split(/[\s,|]/);
  114. }
  115. if (me.api) {
  116. api = me.api = Ext.apply({}, me.api);
  117. for (fn in api) {
  118. if (api.hasOwnProperty(fn)) {
  119. api[fn] = Ext.direct.Manager.parseMethod(api[fn]);
  120. }
  121. }
  122. }
  123. me.checkValidityTask = new Ext.util.DelayedTask(me.checkValidity, me);
  124. me.addEvents(
  125. <span id='Ext-form-Basic-event-beforeaction'> /**
  126. </span> * @event beforeaction
  127. * Fires before any action is performed. Return false to cancel the action.
  128. * @param {Ext.form.Basic} this
  129. * @param {Ext.form.action.Action} action The {@link Ext.form.action.Action} to be performed
  130. */
  131. 'beforeaction',
  132. <span id='Ext-form-Basic-event-actionfailed'> /**
  133. </span> * @event actionfailed
  134. * Fires when an action fails.
  135. * @param {Ext.form.Basic} this
  136. * @param {Ext.form.action.Action} action The {@link Ext.form.action.Action} that failed
  137. */
  138. 'actionfailed',
  139. <span id='Ext-form-Basic-event-actioncomplete'> /**
  140. </span> * @event actioncomplete
  141. * Fires when an action is completed.
  142. * @param {Ext.form.Basic} this
  143. * @param {Ext.form.action.Action} action The {@link Ext.form.action.Action} that completed
  144. */
  145. 'actioncomplete',
  146. <span id='Ext-form-Basic-event-validitychange'> /**
  147. </span> * @event validitychange
  148. * Fires when the validity of the entire form changes.
  149. * @param {Ext.form.Basic} this
  150. * @param {Boolean} valid `true` if the form is now valid, `false` if it is now invalid.
  151. */
  152. 'validitychange',
  153. <span id='Ext-form-Basic-event-dirtychange'> /**
  154. </span> * @event dirtychange
  155. * Fires when the dirty state of the entire form changes.
  156. * @param {Ext.form.Basic} this
  157. * @param {Boolean} dirty `true` if the form is now dirty, `false` if it is no longer dirty.
  158. */
  159. 'dirtychange'
  160. );
  161. me.callParent();
  162. },
  163. <span id='Ext-form-Basic-method-initialize'> /**
  164. </span> * Do any post layout initialization
  165. * @private
  166. */
  167. initialize : function() {
  168. var me = this;
  169. me.initialized = true;
  170. me.onValidityChange(!me.hasInvalidField());
  171. },
  172. <span id='Ext-form-Basic-cfg-method'> /**
  173. </span> * @cfg {String} method
  174. * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
  175. */
  176. <span id='Ext-form-Basic-cfg-reader'> /**
  177. </span> * @cfg {Ext.data.reader.Reader} reader
  178. * An Ext.data.DataReader (e.g. {@link Ext.data.reader.Xml}) to be used to read
  179. * data when executing 'load' actions. This is optional as there is built-in
  180. * support for processing JSON responses.
  181. */
  182. <span id='Ext-form-Basic-cfg-errorReader'> /**
  183. </span> * @cfg {Ext.data.reader.Reader} errorReader
  184. * An Ext.data.DataReader (e.g. {@link Ext.data.reader.Xml}) to be used to
  185. * read field error messages returned from 'submit' actions. This is optional
  186. * as there is built-in support for processing JSON responses.
  187. *
  188. * The Records which provide messages for the invalid Fields must use the
  189. * Field name (or id) as the Record ID, and must contain a field called 'msg'
  190. * which contains the error message.
  191. *
  192. * The errorReader does not have to be a full-blown implementation of a
  193. * Reader. It simply needs to implement a `read(xhr)` function
  194. * which returns an Array of Records in an object with the following
  195. * structure:
  196. *
  197. * {
  198. * records: recordArray
  199. * }
  200. */
  201. <span id='Ext-form-Basic-cfg-url'> /**
  202. </span> * @cfg {String} url
  203. * The URL to use for form actions if one isn't supplied in the
  204. * {@link #doAction doAction} options.
  205. */
  206. <span id='Ext-form-Basic-cfg-baseParams'> /**
  207. </span> * @cfg {Object} baseParams
  208. * Parameters to pass with all requests. e.g. baseParams: `{id: '123', foo: 'bar'}`.
  209. *
  210. * Parameters are encoded as standard HTTP parameters using {@link Ext.Object#toQueryString}.
  211. */
  212. <span id='Ext-form-Basic-cfg-timeout'> /**
  213. </span> * @cfg {Number} timeout
  214. * Timeout for form actions in seconds.
  215. */
  216. timeout: 30,
  217. <span id='Ext-form-Basic-cfg-api'> /**
  218. </span> * @cfg {Object} api
  219. * If specified, load and submit actions will be handled with {@link Ext.form.action.DirectLoad DirectLoad}
  220. * and {@link Ext.form.action.DirectSubmit DirectSubmit}. Methods which have been imported by
  221. * {@link Ext.direct.Manager} can be specified here to load and submit forms. API methods may also be
  222. * specified as strings. See {@link Ext.data.proxy.Direct#directFn}. Such as the following:
  223. *
  224. * api: {
  225. * load: App.ss.MyProfile.load,
  226. * submit: App.ss.MyProfile.submit
  227. * }
  228. *
  229. * Load actions can use {@link #paramOrder} or {@link #paramsAsHash} to customize how the load method
  230. * is invoked. Submit actions will always use a standard form submit. The `formHandler` configuration
  231. * (see Ext.direct.RemotingProvider#action) must be set on the associated server-side method which has
  232. * been imported by {@link Ext.direct.Manager}.
  233. */
  234. <span id='Ext-form-Basic-cfg-paramOrder'> /**
  235. </span> * @cfg {String/String[]} paramOrder
  236. * A list of params to be executed server side. Only used for the {@link #api} `load`
  237. * configuration.
  238. *
  239. * Specify the params in the order in which they must be executed on the
  240. * server-side as either (1) an Array of String values, or (2) a String of params
  241. * delimited by either whitespace, comma, or pipe. For example,
  242. * any of the following would be acceptable:
  243. *
  244. * paramOrder: ['param1','param2','param3']
  245. * paramOrder: 'param1 param2 param3'
  246. * paramOrder: 'param1,param2,param3'
  247. * paramOrder: 'param1|param2|param'
  248. */
  249. <span id='Ext-form-Basic-cfg-paramsAsHash'> /**
  250. </span> * @cfg {Boolean} paramsAsHash
  251. * Only used for the {@link #api} `load` configuration. If true, parameters will be sent as a
  252. * single hash collection of named arguments. Providing a {@link #paramOrder} nullifies this
  253. * configuration.
  254. */
  255. paramsAsHash: false,
  256. //&lt;locale&gt;
  257. <span id='Ext-form-Basic-cfg-waitTitle'> /**
  258. </span> * @cfg {String} waitTitle
  259. * The default title to show for the waiting message box
  260. */
  261. waitTitle: 'Please Wait...',
  262. //&lt;/locale&gt;
  263. <span id='Ext-form-Basic-cfg-trackResetOnLoad'> /**
  264. </span> * @cfg {Boolean} trackResetOnLoad
  265. * If set to true, {@link #reset}() resets to the last loaded or {@link #setValues}() data instead of
  266. * when the form was first created.
  267. */
  268. trackResetOnLoad: false,
  269. <span id='Ext-form-Basic-cfg-standardSubmit'> /**
  270. </span> * @cfg {Boolean} standardSubmit
  271. * If set to true, a standard HTML form submit is used instead of a XHR (Ajax) style form submission.
  272. * All of the field values, plus any additional params configured via {@link #baseParams}
  273. * and/or the `options` to {@link #submit}, will be included in the values submitted in the form.
  274. */
  275. <span id='Ext-form-Basic-cfg-waitMsgTarget'> /**
  276. </span> * @cfg {String/HTMLElement/Ext.Element} waitMsgTarget
  277. * By default wait messages are displayed with Ext.MessageBox.wait. You can target a specific
  278. * element by passing it or its id or mask the form itself by passing in true.
  279. */
  280. // Private
  281. wasDirty: false,
  282. <span id='Ext-form-Basic-method-destroy'> /**
  283. </span> * Destroys this object.
  284. */
  285. destroy: function() {
  286. this.clearListeners();
  287. this.checkValidityTask.cancel();
  288. },
  289. <span id='Ext-form-Basic-method-onItemAddOrRemove'> /**
  290. </span> * @private
  291. * Handle addition or removal of descendant items. Invalidates the cached list of fields
  292. * so that {@link #getFields} will do a fresh query next time it is called. Also adds listeners
  293. * for state change events on added fields, and tracks components with formBind=true.
  294. */
  295. onItemAddOrRemove: function(parent, child) {
  296. var me = this,
  297. isAdding = !!child.ownerCt,
  298. isContainer = child.isContainer;
  299. function handleField(field) {
  300. // Listen for state change events on fields
  301. me[isAdding ? 'mon' : 'mun'](field, {
  302. validitychange: me.checkValidity,
  303. dirtychange: me.checkDirty,
  304. scope: me,
  305. buffer: 100 //batch up sequential calls to avoid excessive full-form validation
  306. });
  307. // Flush the cached list of fields
  308. delete me._fields;
  309. }
  310. if (child.isFormField) {
  311. handleField(child);
  312. } else if (isContainer) {
  313. // Walk down
  314. if (child.isDestroyed || child.destroying) {
  315. // the container is destroyed, this means we may have child fields, so here
  316. // we just invalidate all the fields to be sure.
  317. delete me._fields;
  318. } else {
  319. Ext.Array.forEach(child.query('[isFormField]'), handleField);
  320. }
  321. }
  322. // Flush the cached list of formBind components
  323. delete this._boundItems;
  324. // Check form bind, but only after initial add. Batch it to prevent excessive validation
  325. // calls when many fields are being added at once.
  326. if (me.initialized) {
  327. me.checkValidityTask.delay(10);
  328. }
  329. },
  330. <span id='Ext-form-Basic-method-getFields'> /**
  331. </span> * Return all the {@link Ext.form.field.Field} components in the owner container.
  332. * @return {Ext.util.MixedCollection} Collection of the Field objects
  333. */
  334. getFields: function() {
  335. var fields = this._fields;
  336. if (!fields) {
  337. fields = this._fields = new Ext.util.MixedCollection();
  338. fields.addAll(this.owner.query('[isFormField]'));
  339. }
  340. return fields;
  341. },
  342. <span id='Ext-form-Basic-method-getBoundItems'> /**
  343. </span> * @private
  344. * Finds and returns the set of all items bound to fields inside this form
  345. * @return {Ext.util.MixedCollection} The set of all bound form field items
  346. */
  347. getBoundItems: function() {
  348. var boundItems = this._boundItems;
  349. if (!boundItems || boundItems.getCount() === 0) {
  350. boundItems = this._boundItems = new Ext.util.MixedCollection();
  351. boundItems.addAll(this.owner.query('[formBind]'));
  352. }
  353. return boundItems;
  354. },
  355. <span id='Ext-form-Basic-method-hasInvalidField'> /**
  356. </span> * Returns true if the form contains any invalid fields. No fields will be marked as invalid
  357. * as a result of calling this; to trigger marking of fields use {@link #isValid} instead.
  358. */
  359. hasInvalidField: function() {
  360. return !!this.getFields().findBy(function(field) {
  361. var preventMark = field.preventMark,
  362. isValid;
  363. field.preventMark = true;
  364. isValid = field.isValid();
  365. field.preventMark = preventMark;
  366. return !isValid;
  367. });
  368. },
  369. <span id='Ext-form-Basic-method-isValid'> /**
  370. </span> * Returns true if client-side validation on the form is successful. Any invalid fields will be
  371. * marked as invalid. If you only want to determine overall form validity without marking anything,
  372. * use {@link #hasInvalidField} instead.
  373. * @return Boolean
  374. */
  375. isValid: function() {
  376. var me = this,
  377. invalid;
  378. Ext.suspendLayouts();
  379. invalid = me.getFields().filterBy(function(field) {
  380. return !field.validate();
  381. });
  382. Ext.resumeLayouts(true);
  383. return invalid.length &lt; 1;
  384. },
  385. <span id='Ext-form-Basic-method-checkValidity'> /**
  386. </span> * Check whether the validity of the entire form has changed since it was last checked, and
  387. * if so fire the {@link #validitychange validitychange} event. This is automatically invoked
  388. * when an individual field's validity changes.
  389. */
  390. checkValidity: function() {
  391. var me = this,
  392. valid = !me.hasInvalidField();
  393. if (valid !== me.wasValid) {
  394. me.onValidityChange(valid);
  395. me.fireEvent('validitychange', me, valid);
  396. me.wasValid = valid;
  397. }
  398. },
  399. <span id='Ext-form-Basic-method-onValidityChange'> /**
  400. </span> * @private
  401. * Handle changes in the form's validity. If there are any sub components with
  402. * formBind=true then they are enabled/disabled based on the new validity.
  403. * @param {Boolean} valid
  404. */
  405. onValidityChange: function(valid) {
  406. var boundItems = this.getBoundItems(),
  407. items, i, iLen, cmp;
  408. if (boundItems) {
  409. items = boundItems.items;
  410. iLen = items.length;
  411. for (i = 0; i &lt; iLen; i++) {
  412. cmp = items[i];
  413. if (cmp.disabled === valid) {
  414. cmp.setDisabled(!valid);
  415. }
  416. }
  417. }
  418. },
  419. <span id='Ext-form-Basic-method-isDirty'> /**
  420. </span> * Returns true if any fields in this form have changed from their original values.
  421. *
  422. * Note that if this BasicForm was configured with {@link #trackResetOnLoad} then the
  423. * Fields' *original values* are updated when the values are loaded by {@link #setValues}
  424. * or {@link #loadRecord}.
  425. *
  426. * @return Boolean
  427. */
  428. isDirty: function() {
  429. return !!this.getFields().findBy(function(f) {
  430. return f.isDirty();
  431. });
  432. },
  433. <span id='Ext-form-Basic-method-checkDirty'> /**
  434. </span> * Check whether the dirty state of the entire form has changed since it was last checked, and
  435. * if so fire the {@link #dirtychange dirtychange} event. This is automatically invoked
  436. * when an individual field's dirty state changes.
  437. */
  438. checkDirty: function() {
  439. var dirty = this.isDirty();
  440. if (dirty !== this.wasDirty) {
  441. this.fireEvent('dirtychange', this, dirty);
  442. this.wasDirty = dirty;
  443. }
  444. },
  445. <span id='Ext-form-Basic-method-hasUpload'> /**
  446. </span> * Returns true if the form contains a file upload field. This is used to determine the method for submitting the
  447. * form: File uploads are not performed using normal 'Ajax' techniques, that is they are **not** performed using
  448. * XMLHttpRequests. Instead a hidden `&lt;form&gt;` element containing all the fields is created temporarily and submitted
  449. * with its [target][1] set to refer to a dynamically generated, hidden `&lt;iframe&gt;` which is inserted into the document
  450. * but removed after the return data has been gathered.
  451. *
  452. * The server response is parsed by the browser to create the document for the IFRAME. If the server is using JSON
  453. * to send the return object, then the [Content-Type][2] header must be set to &quot;text/html&quot; in order to tell the
  454. * browser to insert the text unchanged into the document body.
  455. *
  456. * Characters which are significant to an HTML parser must be sent as HTML entities, so encode `&quot;&lt;&quot;` as `&quot;&amp;lt;&quot;`,
  457. * `&quot;&amp;&quot;` as `&quot;&amp;amp;&quot;` etc.
  458. *
  459. * The response text is retrieved from the document, and a fake XMLHttpRequest object is created containing a
  460. * responseText property in order to conform to the requirements of event handlers and callbacks.
  461. *
  462. * Be aware that file upload packets are sent with the content type [multipart/form][3] and some server technologies
  463. * (notably JEE) may require some custom processing in order to retrieve parameter names and parameter values from
  464. * the packet content.
  465. *
  466. * [1]: http://www.w3.org/TR/REC-html40/present/frames.html#adef-target
  467. * [2]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
  468. * [3]: http://www.faqs.org/rfcs/rfc2388.html
  469. *
  470. * @return Boolean
  471. */
  472. hasUpload: function() {
  473. return !!this.getFields().findBy(function(f) {
  474. return f.isFileUpload();
  475. });
  476. },
  477. <span id='Ext-form-Basic-method-doAction'> /**
  478. </span> * Performs a predefined action (an implementation of {@link Ext.form.action.Action}) to perform application-
  479. * specific processing.
  480. *
  481. * @param {String/Ext.form.action.Action} action The name of the predefined action type, or instance of {@link
  482. * Ext.form.action.Action} to perform.
  483. *
  484. * @param {Object} [options] The options to pass to the {@link Ext.form.action.Action} that will get created,
  485. * if the action argument is a String.
  486. *
  487. * All of the config options listed below are supported by both the {@link Ext.form.action.Submit submit} and
  488. * {@link Ext.form.action.Load load} actions unless otherwise noted (custom actions could also accept other
  489. * config options):
  490. *
  491. * @param {String} options.url
  492. * The url for the action (defaults to the form's {@link #url}.)
  493. *
  494. * @param {String} options.method
  495. * The form method to use (defaults to the form's method, or POST if not defined)
  496. *
  497. * @param {String/Object} options.params
  498. * The params to pass (defaults to the form's baseParams, or none if not defined)
  499. *
  500. * Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode Ext.Object.toQueryString}.
  501. *
  502. * @param {Object} options.headers
  503. * Request headers to set for the action.
  504. *
  505. * @param {Function} options.success
  506. * The callback that will be invoked after a successful response (see top of {@link Ext.form.action.Submit submit}
  507. * and {@link Ext.form.action.Load load} for a description of what constitutes a successful response).
  508. * @param {Ext.form.Basic} options.success.form The form that requested the action.
  509. * @param {Ext.form.action.Action} options.success.action The Action object which performed the operation.
  510. * The action object contains these properties of interest:
  511. *
  512. * - {@link Ext.form.action.Action#response response}
  513. * - {@link Ext.form.action.Action#result result} - interrogate for custom postprocessing
  514. * - {@link Ext.form.action.Action#type type}
  515. *
  516. * @param {Function} options.failure
  517. * The callback that will be invoked after a failed transaction attempt.
  518. * @param {Ext.form.Basic} options.failure.form The form that requested the action.
  519. * @param {Ext.form.action.Action} options.failure.action The Action object which performed the operation.
  520. * The action object contains these properties of interest:
  521. *
  522. * - {@link Ext.form.action.Action#failureType failureType}
  523. * - {@link Ext.form.action.Action#response response}
  524. * - {@link Ext.form.action.Action#result result} - interrogate for custom postprocessing
  525. * - {@link Ext.form.action.Action#type type}
  526. *
  527. * @param {Object} options.scope
  528. * The scope in which to call the callback functions (The this reference for the callback functions).
  529. *
  530. * @param {Boolean} options.clientValidation
  531. * Submit Action only. Determines whether a Form's fields are validated in a final call to {@link
  532. * Ext.form.Basic#isValid isValid} prior to submission. Set to false to prevent this. If undefined, pre-submission
  533. * field validation is performed.
  534. *
  535. * @return {Ext.form.Basic} this
  536. */
  537. doAction: function(action, options) {
  538. if (Ext.isString(action)) {
  539. action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this}));
  540. }
  541. if (this.fireEvent('beforeaction', this, action) !== false) {
  542. this.beforeAction(action);
  543. Ext.defer(action.run, 100, action);
  544. }
  545. return this;
  546. },
  547. <span id='Ext-form-Basic-method-submit'> /**
  548. </span> * Shortcut to {@link #doAction do} a {@link Ext.form.action.Submit submit action}. This will use the
  549. * {@link Ext.form.action.Submit AJAX submit action} by default. If the {@link #standardSubmit} config
  550. * is enabled it will use a standard form element to submit, or if the {@link #api} config is present
  551. * it will use the {@link Ext.form.action.DirectLoad Ext.direct.Direct submit action}.
  552. *
  553. * The following code:
  554. *
  555. * myFormPanel.getForm().submit({
  556. * clientValidation: true,
  557. * url: 'updateConsignment.php',
  558. * params: {
  559. * newStatus: 'delivered'
  560. * },
  561. * success: function(form, action) {
  562. * Ext.Msg.alert('Success', action.result.msg);
  563. * },
  564. * failure: function(form, action) {
  565. * switch (action.failureType) {
  566. * case Ext.form.action.Action.CLIENT_INVALID:
  567. * Ext.Msg.alert('Failure', 'Form fields may not be submitted with invalid values');
  568. * break;
  569. * case Ext.form.action.Action.CONNECT_FAILURE:
  570. * Ext.Msg.alert('Failure', 'Ajax communication failed');
  571. * break;
  572. * case Ext.form.action.Action.SERVER_INVALID:
  573. * Ext.Msg.alert('Failure', action.result.msg);
  574. * }
  575. * }
  576. * });
  577. *
  578. * would process the following server response for a successful submission:
  579. *
  580. * {
  581. * &quot;success&quot;:true, // note this is Boolean, not string
  582. * &quot;msg&quot;:&quot;Consignment updated&quot;
  583. * }
  584. *
  585. * and the following server response for a failed submission:
  586. *
  587. * {
  588. * &quot;success&quot;:false, // note this is Boolean, not string
  589. * &quot;msg&quot;:&quot;You do not have permission to perform this operation&quot;
  590. * }
  591. *
  592. * @param {Object} options The options to pass to the action (see {@link #doAction} for details).
  593. * @return {Ext.form.Basic} this
  594. */
  595. submit: function(options) {
  596. options = options || {};
  597. var me = this,
  598. action;
  599. if (options.standardSubmit || me.standardSubmit) {
  600. action = 'standardsubmit';
  601. } else {
  602. action = me.api ? 'directsubmit' : 'submit';
  603. }
  604. return me.doAction(action, options);
  605. },
  606. <span id='Ext-form-Basic-method-load'> /**
  607. </span> * Shortcut to {@link #doAction do} a {@link Ext.form.action.Load load action}.
  608. * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
  609. * @return {Ext.form.Basic} this
  610. */
  611. load: function(options) {
  612. return this.doAction(this.api ? 'directload' : 'load', options);
  613. },
  614. <span id='Ext-form-Basic-method-updateRecord'> /**
  615. </span> * Persists the values in this form into the passed {@link Ext.data.Model} object in a beginEdit/endEdit block.
  616. * If the record is not specified, it will attempt to update (if it exists) the record provided to loadRecord.
  617. * @param {Ext.data.Model} [record] The record to edit
  618. * @return {Ext.form.Basic} this
  619. */
  620. updateRecord: function(record) {
  621. record = record || this._record;
  622. //&lt;debug&gt;
  623. if (!record) {
  624. Ext.Error.raise(&quot;A record is required.&quot;);
  625. }
  626. //&lt;/debug&gt;
  627. var fields = record.fields.items,
  628. values = this.getFieldValues(),
  629. obj = {},
  630. i = 0,
  631. len = fields.length,
  632. name;
  633. for (; i &lt; len; ++i) {
  634. name = fields[i].name;
  635. if (values.hasOwnProperty(name)) {
  636. obj[name] = values[name];
  637. }
  638. }
  639. record.beginEdit();
  640. record.set(obj);
  641. record.endEdit();
  642. return this;
  643. },
  644. <span id='Ext-form-Basic-method-loadRecord'> /**
  645. </span> * Loads an {@link Ext.data.Model} into this form by calling {@link #setValues} with the
  646. * {@link Ext.data.Model#raw record data}.
  647. * See also {@link #trackResetOnLoad}.
  648. * @param {Ext.data.Model} record The record to load
  649. * @return {Ext.form.Basic} this
  650. */
  651. loadRecord: function(record) {
  652. this._record = record;
  653. return this.setValues(record.data);
  654. },
  655. <span id='Ext-form-Basic-method-getRecord'> /**
  656. </span> * Returns the last Ext.data.Model instance that was loaded via {@link #loadRecord}
  657. * @return {Ext.data.Model} The record
  658. */
  659. getRecord: function() {
  660. return this._record;
  661. },
  662. <span id='Ext-form-Basic-method-beforeAction'> /**
  663. </span> * @private
  664. * Called before an action is performed via {@link #doAction}.
  665. * @param {Ext.form.action.Action} action The Action instance that was invoked
  666. */
  667. beforeAction: function(action) {
  668. var waitMsg = action.waitMsg,
  669. maskCls = Ext.baseCSSPrefix + 'mask-loading',
  670. fields = this.getFields().items,
  671. f,
  672. fLen = fields.length,
  673. field, waitMsgTarget;
  674. // Call HtmlEditor's syncValue before actions
  675. for (f = 0; f &lt; fLen; f++) {
  676. field = fields[f];
  677. if (field.isFormField &amp;&amp; field.syncValue) {
  678. field.syncValue();
  679. }
  680. }
  681. if (waitMsg) {
  682. waitMsgTarget = this.waitMsgTarget;
  683. if (waitMsgTarget === true) {
  684. this.owner.el.mask(waitMsg, maskCls);
  685. } else if (waitMsgTarget) {
  686. waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
  687. waitMsgTarget.mask(waitMsg, maskCls);
  688. } else {
  689. Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
  690. }
  691. }
  692. },
  693. <span id='Ext-form-Basic-method-afterAction'> /**
  694. </span> * @private
  695. * Called after an action is performed via {@link #doAction}.
  696. * @param {Ext.form.action.Action} action The Action instance that was invoked
  697. * @param {Boolean} success True if the action completed successfully, false, otherwise.
  698. */
  699. afterAction: function(action, success) {
  700. if (action.waitMsg) {
  701. var messageBox = Ext.MessageBox,
  702. waitMsgTarget = this.waitMsgTarget;
  703. if (waitMsgTarget === true) {
  704. this.owner.el.unmask();
  705. } else if (waitMsgTarget) {
  706. waitMsgTarget.unmask();
  707. } else {
  708. // Do not fire the hide event because that triggers complex processing
  709. // which is not necessary just for the wait window, and which may interfere with the app.
  710. messageBox.suspendEvents();
  711. messageBox.hide();
  712. messageBox.resumeEvents();
  713. }
  714. }
  715. if (success) {
  716. if (action.reset) {
  717. this.reset();
  718. }
  719. Ext.callback(action.success, action.scope || action, [this, action]);
  720. this.fireEvent('actioncomplete', this, action);
  721. } else {
  722. Ext.callback(action.failure, action.scope || action, [this, action]);
  723. this.fireEvent('actionfailed', this, action);
  724. }
  725. },
  726. <span id='Ext-form-Basic-method-findField'> /**
  727. </span> * Find a specific {@link Ext.form.field.Field} in this form by id or name.
  728. * @param {String} id The value to search for (specify either a {@link Ext.Component#id id} or
  729. * {@link Ext.form.field.Field#getName name or hiddenName}).
  730. * @return {Ext.form.field.Field} The first matching field, or `null` if none was found.
  731. */
  732. findField: function(id) {
  733. return this.getFields().findBy(function(f) {
  734. return f.id === id || f.getName() === id;
  735. });
  736. },
  737. <span id='Ext-form-Basic-method-markInvalid'> /**
  738. </span> * Mark fields in this form invalid in bulk.
  739. * @param {Object/Object[]/Ext.data.Errors} errors
  740. * Either an array in the form `[{id:'fieldId', msg:'The message'}, ...]`,
  741. * an object hash of `{id: msg, id2: msg2}`, or a {@link Ext.data.Errors} object.
  742. * @return {Ext.form.Basic} this
  743. */
  744. markInvalid: function(errors) {
  745. var me = this,
  746. e, eLen, error, value,
  747. key;
  748. function mark(fieldId, msg) {
  749. var field = me.findField(fieldId);
  750. if (field) {
  751. field.markInvalid(msg);
  752. }
  753. }
  754. if (Ext.isArray(errors)) {
  755. eLen = errors.length;
  756. for (e = 0; e &lt; eLen; e++) {
  757. error = errors[e];
  758. mark(error.id, error.msg);
  759. }
  760. } else if (errors instanceof Ext.data.Errors) {
  761. eLen = errors.items.length;
  762. for (e = 0; e &lt; eLen; e++) {
  763. error = errors.items[e];
  764. mark(error.field, error.message);
  765. }
  766. } else {
  767. for (key in errors) {
  768. if (errors.hasOwnProperty(key)) {
  769. value = errors[key];
  770. mark(key, value, errors);
  771. }
  772. }
  773. }
  774. return this;
  775. },
  776. <span id='Ext-form-Basic-method-setValues'> /**
  777. </span> * Set values for fields in this form in bulk.
  778. *
  779. * @param {Object/Object[]} values Either an array in the form:
  780. *
  781. * [{id:'clientName', value:'Fred. Olsen Lines'},
  782. * {id:'portOfLoading', value:'FXT'},
  783. * {id:'portOfDischarge', value:'OSL'} ]
  784. *
  785. * or an object hash of the form:
  786. *
  787. * {
  788. * clientName: 'Fred. Olsen Lines',
  789. * portOfLoading: 'FXT',
  790. * portOfDischarge: 'OSL'
  791. * }
  792. *
  793. * @return {Ext.form.Basic} this
  794. */
  795. setValues: function(values) {
  796. var me = this,
  797. v, vLen, val, field;
  798. function setVal(fieldId, val) {
  799. var field = me.findField(fieldId);
  800. if (field) {
  801. field.setValue(val);
  802. if (me.trackResetOnLoad) {
  803. field.resetOriginalValue();
  804. }
  805. }
  806. }
  807. if (Ext.isArray(values)) {
  808. // array of objects
  809. vLen = values.length;
  810. for (v = 0; v &lt; vLen; v++) {
  811. val = values[v];
  812. setVal(val.id, val.value);
  813. }
  814. } else {
  815. // object hash
  816. Ext.iterate(values, setVal);
  817. }
  818. return this;
  819. },
  820. <span id='Ext-form-Basic-method-getValues'> /**
  821. </span> * Retrieves the fields in the form as a set of key/value pairs, using their
  822. * {@link Ext.form.field.Field#getSubmitData getSubmitData()} method to collect the values.
  823. * If multiple fields return values under the same name those values will be combined into an Array.
  824. * This is similar to {@link Ext.form.Basic#getFieldValues getFieldValues} except that this method
  825. * collects only String values for submission, while getFieldValues collects type-specific data
  826. * values (e.g. Date objects for date fields.)
  827. *
  828. * @param {Boolean} [asString=false] If true, will return the key/value collection as a single
  829. * URL-encoded param string.
  830. * @param {Boolean} [dirtyOnly=false] If true, only fields that are dirty will be included in the result.
  831. * @param {Boolean} [includeEmptyText=false] If true, the configured emptyText of empty fields will be used.
  832. * @param {Boolean} [useDataValues=false] If true, the {@link Ext.form.field.Field#getModelData getModelData}
  833. * method is used to retrieve values from fields, otherwise the {@link Ext.form.field.Field#getSubmitData getSubmitData}
  834. * method is used.
  835. * @return {String/Object}
  836. */
  837. getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
  838. var values = {},
  839. fields = this.getFields().items,
  840. f,
  841. fLen = fields.length,
  842. isArray = Ext.isArray,
  843. field, data, val, bucket, name;
  844. for (f = 0; f &lt; fLen; f++) {
  845. field = fields[f];
  846. if (!dirtyOnly || field.isDirty()) {
  847. data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
  848. if (Ext.isObject(data)) {
  849. for (name in data) {
  850. if (data.hasOwnProperty(name)) {
  851. val = data[name];
  852. if (includeEmptyText &amp;&amp; val === '') {
  853. val = field.emptyText || '';
  854. }
  855. if (values.hasOwnProperty(name)) {
  856. bucket = values[name];
  857. if (!isArray(bucket)) {
  858. bucket = values[name] = [bucket];
  859. }
  860. if (isArray(val)) {
  861. values[name] = values[name] = bucket.concat(val);
  862. } else {
  863. bucket.push(val);
  864. }
  865. } else {
  866. values[name] = val;
  867. }
  868. }
  869. }
  870. }
  871. }
  872. }
  873. if (asString) {
  874. values = Ext.Object.toQueryString(values);
  875. }
  876. return values;
  877. },
  878. <span id='Ext-form-Basic-method-getFieldValues'> /**
  879. </span> * Retrieves the fields in the form as a set of key/value pairs, using their
  880. * {@link Ext.form.field.Field#getModelData getModelData()} method to collect the values.
  881. * If multiple fields return values under the same name those values will be combined into an Array.
  882. * This is similar to {@link #getValues} except that this method collects type-specific data values
  883. * (e.g. Date objects for date fields) while getValues returns only String values for submission.
  884. *
  885. * @param {Boolean} [dirtyOnly=false] If true, only fields that are dirty will be included in the result.
  886. * @return {Object}
  887. */
  888. getFieldValues: function(dirtyOnly) {
  889. return this.getValues(false, dirtyOnly, false, true);
  890. },
  891. <span id='Ext-form-Basic-method-clearInvalid'> /**
  892. </span> * Clears all invalid field messages in this form.
  893. * @return {Ext.form.Basic} this
  894. */
  895. clearInvalid: function() {
  896. Ext.suspendLayouts();
  897. var me = this,
  898. fields = me.getFields().items,
  899. f,
  900. fLen = fields.length;
  901. for (f = 0; f &lt; fLen; f++) {
  902. fields[f].clearInvalid();
  903. }
  904. Ext.resumeLayouts(true);
  905. return me;
  906. },
  907. <span id='Ext-form-Basic-method-reset'> /**
  908. </span> * Resets all fields in this form.
  909. * @return {Ext.form.Basic} this
  910. */
  911. reset: function() {
  912. Ext.suspendLayouts();
  913. var me = this,
  914. fields = me.getFields().items,
  915. f,
  916. fLen = fields.length;
  917. for (f = 0; f &lt; fLen; f++) {
  918. fields[f].reset();
  919. }
  920. Ext.resumeLayouts(true);
  921. return me;
  922. },
  923. <span id='Ext-form-Basic-method-applyToFields'> /**
  924. </span> * Calls {@link Ext#apply Ext.apply} for all fields in this form with the passed object.
  925. * @param {Object} obj The object to be applied
  926. * @return {Ext.form.Basic} this
  927. */
  928. applyToFields: function(obj) {
  929. var fields = this.getFields().items,
  930. f,
  931. fLen = fields.length;
  932. for (f = 0; f &lt; fLen; f++) {
  933. Ext.apply(fields[f], obj);
  934. }
  935. return this;
  936. },
  937. <span id='Ext-form-Basic-method-applyIfToFields'> /**
  938. </span> * Calls {@link Ext#applyIf Ext.applyIf} for all field in this form with the passed object.
  939. * @param {Object} obj The object to be applied
  940. * @return {Ext.form.Basic} this
  941. */
  942. applyIfToFields: function(obj) {
  943. var fields = this.getFields().items,
  944. f,
  945. fLen = fields.length;
  946. for (f = 0; f &lt; fLen; f++) {
  947. Ext.applyIf(fields[f], obj);
  948. }
  949. return this;
  950. }
  951. });
  952. </pre>
  953. </body>
  954. </html>