Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / docs / source / BasicForm.html
1 <html>\r
2 <head>\r
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    \r
4   <title>The source code</title>\r
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
7 </head>\r
8 <body  onload="prettyPrint();">\r
9     <pre class="prettyprint lang-js"><div id="cls-Ext.form.BasicForm"></div>/**
10  * @class Ext.form.BasicForm
11  * @extends Ext.util.Observable
12  * <p>Encapsulates the DOM &lt;form> element at the heart of the {@link Ext.form.FormPanel FormPanel} class, and provides
13  * input field management, validation, submission, and form loading services.</p>
14  * <p>By default, Ext Forms are submitted through Ajax, using an instance of {@link Ext.form.Action.Submit}.
15  * To enable normal browser submission of an Ext Form, use the {@link #standardSubmit} config option.</p>
16  * <p><b><u>File Uploads</u></b></p>
17  * <p>{@link #fileUpload File uploads} are not performed using Ajax submission, that
18  * is they are <b>not</b> performed using XMLHttpRequests. Instead the form is submitted in the standard
19  * manner with the DOM <tt>&lt;form></tt> element temporarily modified to have its
20  * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
21  * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
22  * but removed after the return data has been gathered.</p>
23  * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
24  * server is using JSON to send the return object, then the
25  * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
26  * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
27  * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
28  * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
29  * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
30  * is created containing a <tt>responseText</tt> property in order to conform to the
31  * requirements of event handlers and callbacks.</p>
32  * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
33  * and some server technologies (notably JEE) may require some custom processing in order to
34  * retrieve parameter names and parameter values from the packet content.</p>
35  * @constructor
36  * @param {Mixed} el The form element or its id
37  * @param {Object} config Configuration options
38  */
39 Ext.form.BasicForm = function(el, config){
40     Ext.apply(this, config);
41     if(Ext.isString(this.paramOrder)){
42         this.paramOrder = this.paramOrder.split(/[\s,|]/);
43     }
44     <div id="prop-Ext.form.BasicForm-items"></div>/**
45      * A {@link Ext.util.MixedCollection MixedCollection} containing all the Ext.form.Fields in this form.
46      * @type MixedCollection
47      * @property items
48      */
49     this.items = new Ext.util.MixedCollection(false, function(o){
50         return o.getItemId();
51     });
52     this.addEvents(
53         <div id="event-Ext.form.BasicForm-beforeaction"></div>/**
54          * @event beforeaction
55          * Fires before any action is performed. Return false to cancel the action.
56          * @param {Form} this
57          * @param {Action} action The {@link Ext.form.Action} to be performed
58          */
59         'beforeaction',
60         <div id="event-Ext.form.BasicForm-actionfailed"></div>/**
61          * @event actionfailed
62          * Fires when an action fails.
63          * @param {Form} this
64          * @param {Action} action The {@link Ext.form.Action} that failed
65          */
66         'actionfailed',
67         <div id="event-Ext.form.BasicForm-actioncomplete"></div>/**
68          * @event actioncomplete
69          * Fires when an action is completed.
70          * @param {Form} this
71          * @param {Action} action The {@link Ext.form.Action} that completed
72          */
73         'actioncomplete'
74     );
75
76     if(el){
77         this.initEl(el);
78     }
79     Ext.form.BasicForm.superclass.constructor.call(this);
80 };
81
82 Ext.extend(Ext.form.BasicForm, Ext.util.Observable, {
83     <div id="cfg-Ext.form.BasicForm-method"></div>/**
84      * @cfg {String} method
85      * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
86      */
87     <div id="cfg-Ext.form.BasicForm-reader"></div>/**
88      * @cfg {DataReader} reader
89      * An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to read
90      * data when executing 'load' actions. This is optional as there is built-in
91      * support for processing JSON.  For additional information on using an XMLReader
92      * see the example provided in examples/form/xml-form.html.
93      */
94     <div id="cfg-Ext.form.BasicForm-errorReader"></div>/**
95      * @cfg {DataReader} errorReader
96      * <p>An Ext.data.DataReader (e.g. {@link Ext.data.XmlReader}) to be used to
97      * read field error messages returned from 'submit' actions. This is optional
98      * as there is built-in support for processing JSON.</p>
99      * <p>The Records which provide messages for the invalid Fields must use the
100      * Field name (or id) as the Record ID, and must contain a field called 'msg'
101      * which contains the error message.</p>
102      * <p>The errorReader does not have to be a full-blown implementation of a
103      * DataReader. It simply needs to implement a <tt>read(xhr)</tt> function
104      * which returns an Array of Records in an object with the following
105      * structure:</p><pre><code>
106 {
107     records: recordArray
108 }
109 </code></pre>
110      */
111     <div id="cfg-Ext.form.BasicForm-url"></div>/**
112      * @cfg {String} url
113      * The URL to use for form actions if one isn't supplied in the
114      * <code>{@link #doAction doAction} options</code>.
115      */
116     <div id="cfg-Ext.form.BasicForm-fileUpload"></div>/**
117      * @cfg {Boolean} fileUpload
118      * Set to true if this form is a file upload.
119      * <p>File uploads are not performed using normal 'Ajax' techniques, that is they are <b>not</b>
120      * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the
121      * DOM <tt>&lt;form></tt> element temporarily modified to have its
122      * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
123      * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
124      * but removed after the return data has been gathered.</p>
125      * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
126      * server is using JSON to send the return object, then the
127      * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
128      * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
129      * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
130      * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
131      * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
132      * is created containing a <tt>responseText</tt> property in order to conform to the
133      * requirements of event handlers and callbacks.</p>
134      * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
135      * and some server technologies (notably JEE) may require some custom processing in order to
136      * retrieve parameter names and parameter values from the packet content.</p>
137      */
138     <div id="cfg-Ext.form.BasicForm-baseParams"></div>/**
139      * @cfg {Object} baseParams
140      * <p>Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.</p>
141      * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p>
142      */
143     <div id="cfg-Ext.form.BasicForm-timeout"></div>/**
144      * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
145      */
146     timeout: 30,
147
148     <div id="cfg-Ext.form.BasicForm-api"></div>/**
149      * @cfg {Object} api (Optional) If specified load and submit actions will be handled
150      * with {@link Ext.form.Action.DirectLoad} and {@link Ext.form.Action.DirectSubmit}.
151      * Methods which have been imported by Ext.Direct can be specified here to load and submit
152      * forms.
153      * Such as the following:<pre><code>
154 api: {
155     load: App.ss.MyProfile.load,
156     submit: App.ss.MyProfile.submit
157 }
158 </code></pre>
159      * <p>Load actions can use <code>{@link #paramOrder}</code> or <code>{@link #paramsAsHash}</code>
160      * to customize how the load method is invoked.
161      * Submit actions will always use a standard form submit. The formHandler configuration must
162      * be set on the associated server-side method which has been imported by Ext.Direct</p>
163      */
164
165     <div id="cfg-Ext.form.BasicForm-paramOrder"></div>/**
166      * @cfg {Array/String} paramOrder <p>A list of params to be executed server side.
167      * Defaults to <tt>undefined</tt>. Only used for the <code>{@link #api}</code>
168      * <code>load</code> configuration.</p>
169      * <br><p>Specify the params in the order in which they must be executed on the
170      * server-side as either (1) an Array of String values, or (2) a String of params
171      * delimited by either whitespace, comma, or pipe. For example,
172      * any of the following would be acceptable:</p><pre><code>
173 paramOrder: ['param1','param2','param3']
174 paramOrder: 'param1 param2 param3'
175 paramOrder: 'param1,param2,param3'
176 paramOrder: 'param1|param2|param'
177      </code></pre>
178      */
179     paramOrder: undefined,
180
181     <div id="cfg-Ext.form.BasicForm-paramsAsHash"></div>/**
182      * @cfg {Boolean} paramsAsHash Only used for the <code>{@link #api}</code>
183      * <code>load</code> configuration. Send parameters as a collection of named
184      * arguments (defaults to <tt>false</tt>). Providing a
185      * <tt>{@link #paramOrder}</tt> nullifies this configuration.
186      */
187     paramsAsHash: false,
188     
189     <div id="cfg-Ext.form.BasicForm-waitTitle"></div>/**
190      * @cfg {String} waitTitle
191      * The default title to show for the waiting message box (defaults to <tt>'Please Wait...'</tt>)
192      */
193     waitTitle: 'Please Wait...',
194
195     // private
196     activeAction : null,
197
198     <div id="cfg-Ext.form.BasicForm-trackResetOnLoad"></div>/**
199      * @cfg {Boolean} trackResetOnLoad If set to <tt>true</tt>, {@link #reset}() resets to the last loaded
200      * or {@link #setValues}() data instead of when the form was first created.  Defaults to <tt>false</tt>.
201      */
202     trackResetOnLoad : false,
203
204     <div id="cfg-Ext.form.BasicForm-standardSubmit"></div>/**
205      * @cfg {Boolean} standardSubmit
206      * <p>If set to <tt>true</tt>, standard HTML form submits are used instead
207      * of XHR (Ajax) style form submissions. Defaults to <tt>false</tt>.</p>
208      * <br><p><b>Note:</b> When using <code>standardSubmit</code>, the
209      * <code>options</code> to <code>{@link #submit}</code> are ignored because
210      * Ext's Ajax infrastracture is bypassed. To pass extra parameters (e.g.
211      * <code>baseParams</code> and <code>params</code>), utilize hidden fields
212      * to submit extra data, for example:</p>
213      * <pre><code>
214 new Ext.FormPanel({
215     standardSubmit: true,
216     baseParams: {
217         foo: 'bar'
218     },
219     {@link url}: 'myProcess.php',
220     items: [{
221         xtype: 'textfield',
222         name: 'userName'
223     }],
224     buttons: [{
225         text: 'Save',
226         handler: function(){
227             var fp = this.ownerCt.ownerCt,
228                 form = fp.getForm();
229             if (form.isValid()) {
230                 // check if there are baseParams and if
231                 // hiddent items have been added already
232                 if (fp.baseParams && !fp.paramsAdded) {
233                     // add hidden items for all baseParams
234                     for (i in fp.baseParams) {
235                         fp.add({
236                             xtype: 'hidden',
237                             name: i,
238                             value: fp.baseParams[i]
239                         });
240                     }
241                     fp.doLayout();
242                     // set a custom flag to prevent re-adding
243                     fp.paramsAdded = true;
244                 }
245                 form.{@link #submit}();
246             }
247         }
248     }]
249 });
250      * </code></pre>
251      */
252     <div id="prop-Ext.form.BasicForm-waitMsgTarget"></div>/**
253      * By default wait messages are displayed with Ext.MessageBox.wait. You can target a specific
254      * element by passing it or its id or mask the form itself by passing in true.
255      * @type Mixed
256      * @property waitMsgTarget
257      */
258
259     // private
260     initEl : function(el){
261         this.el = Ext.get(el);
262         this.id = this.el.id || Ext.id();
263         if(!this.standardSubmit){
264             this.el.on('submit', this.onSubmit, this);
265         }
266         this.el.addClass('x-form');
267     },
268
269     <div id="method-Ext.form.BasicForm-getEl"></div>/**
270      * Get the HTML form Element
271      * @return Ext.Element
272      */
273     getEl: function(){
274         return this.el;
275     },
276
277     // private
278     onSubmit : function(e){
279         e.stopEvent();
280     },
281
282     // private
283     destroy: function() {
284         this.items.each(function(f){
285             Ext.destroy(f);
286         });
287         if(this.el){
288             this.el.removeAllListeners();
289             this.el.remove();
290         }
291         this.purgeListeners();
292     },
293
294     <div id="method-Ext.form.BasicForm-isValid"></div>/**
295      * Returns true if client-side validation on the form is successful.
296      * @return Boolean
297      */
298     isValid : function(){
299         var valid = true;
300         this.items.each(function(f){
301            if(!f.validate()){
302                valid = false;
303            }
304         });
305         return valid;
306     },
307
308     <div id="method-Ext.form.BasicForm-isDirty"></div>/**
309      * <p>Returns true if any fields in this form have changed from their original values.</p>
310      * <p>Note that if this BasicForm was configured with {@link #trackResetOnLoad} then the
311      * Fields' <i>original values</i> are updated when the values are loaded by {@link #setValues}
312      * or {@link #loadRecord}.</p>
313      * @return Boolean
314      */
315     isDirty : function(){
316         var dirty = false;
317         this.items.each(function(f){
318            if(f.isDirty()){
319                dirty = true;
320                return false;
321            }
322         });
323         return dirty;
324     },
325
326     <div id="method-Ext.form.BasicForm-doAction"></div>/**
327      * Performs a predefined action ({@link Ext.form.Action.Submit} or
328      * {@link Ext.form.Action.Load}) or a custom extension of {@link Ext.form.Action}
329      * to perform application-specific processing.
330      * @param {String/Object} actionName The name of the predefined action type,
331      * or instance of {@link Ext.form.Action} to perform.
332      * @param {Object} options (optional) The options to pass to the {@link Ext.form.Action}.
333      * All of the config options listed below are supported by both the
334      * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}
335      * actions unless otherwise noted (custom actions could also accept
336      * other config options):<ul>
337      *
338      * <li><b>url</b> : String<div class="sub-desc">The url for the action (defaults
339      * to the form's {@link #url}.)</div></li>
340      *
341      * <li><b>method</b> : String<div class="sub-desc">The form method to use (defaults
342      * to the form's method, or POST if not defined)</div></li>
343      *
344      * <li><b>params</b> : String/Object<div class="sub-desc"><p>The params to pass
345      * (defaults to the form's baseParams, or none if not defined)</p>
346      * <p>Parameters are encoded as standard HTTP parameters using {@link Ext#urlEncode}.</p></div></li>
347      *
348      * <li><b>headers</b> : Object<div class="sub-desc">Request headers to set for the action
349      * (defaults to the form's default headers)</div></li>
350      *
351      * <li><b>success</b> : Function<div class="sub-desc">The callback that will
352      * be invoked after a successful response (see top of
353      * {@link Ext.form.Action.Submit submit} and {@link Ext.form.Action.Load load}
354      * for a description of what constitutes a successful response).
355      * The function is passed the following parameters:<ul>
356      * <li><tt>form</tt> : Ext.form.BasicForm<div class="sub-desc">The form that requested the action</div></li>
357      * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.
358      * <div class="sub-desc">The action object contains these properties of interest:<ul>
359      * <li><tt>{@link Ext.form.Action#response response}</tt></li>
360      * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>
361      * <li><tt>{@link Ext.form.Action#type type}</tt></li>
362      * </ul></div></li></ul></div></li>
363      *
364      * <li><b>failure</b> : Function<div class="sub-desc">The callback that will be invoked after a
365      * failed transaction attempt. The function is passed the following parameters:<ul>
366      * <li><tt>form</tt> : The {@link Ext.form.BasicForm} that requested the action.</li>
367      * <li><tt>action</tt> : The {@link Ext.form.Action Action} object which performed the operation.
368      * <div class="sub-desc">The action object contains these properties of interest:<ul>
369      * <li><tt>{@link Ext.form.Action#failureType failureType}</tt></li>
370      * <li><tt>{@link Ext.form.Action#response response}</tt></li>
371      * <li><tt>{@link Ext.form.Action#result result}</tt> : interrogate for custom postprocessing</li>
372      * <li><tt>{@link Ext.form.Action#type type}</tt></li>
373      * </ul></div></li></ul></div></li>
374      *
375      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the
376      * callback functions (The <tt>this</tt> reference for the callback functions).</div></li>
377      *
378      * <li><b>clientValidation</b> : Boolean<div class="sub-desc">Submit Action only.
379      * Determines whether a Form's fields are validated in a final call to
380      * {@link Ext.form.BasicForm#isValid isValid} prior to submission. Set to <tt>false</tt>
381      * to prevent this. If undefined, pre-submission field validation is performed.</div></li></ul>
382      *
383      * @return {BasicForm} this
384      */
385     doAction : function(action, options){
386         if(Ext.isString(action)){
387             action = new Ext.form.Action.ACTION_TYPES[action](this, options);
388         }
389         if(this.fireEvent('beforeaction', this, action) !== false){
390             this.beforeAction(action);
391             action.run.defer(100, action);
392         }
393         return this;
394     },
395
396     <div id="method-Ext.form.BasicForm-submit"></div>/**
397      * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Submit submit action}.
398      * @param {Object} options The options to pass to the action (see {@link #doAction} for details).<br>
399      * <p><b>Note:</b> this is ignored when using the {@link #standardSubmit} option.</p>
400      * <p>The following code:</p><pre><code>
401 myFormPanel.getForm().submit({
402     clientValidation: true,
403     url: 'updateConsignment.php',
404     params: {
405         newStatus: 'delivered'
406     },
407     success: function(form, action) {
408        Ext.Msg.alert('Success', action.result.msg);
409     },
410     failure: function(form, action) {
411         switch (action.failureType) {
412             case Ext.form.Action.CLIENT_INVALID:
413                 Ext.Msg.alert('Failure', 'Form fields may not be submitted with invalid values');
414                 break;
415             case Ext.form.Action.CONNECT_FAILURE:
416                 Ext.Msg.alert('Failure', 'Ajax communication failed');
417                 break;
418             case Ext.form.Action.SERVER_INVALID:
419                Ext.Msg.alert('Failure', action.result.msg);
420        }
421     }
422 });
423 </code></pre>
424      * would process the following server response for a successful submission:<pre><code>
425 {
426     "success":true, // note this is Boolean, not string
427     "msg":"Consignment updated"
428 }
429 </code></pre>
430      * and the following server response for a failed submission:<pre><code>
431 {
432     "success":false, // note this is Boolean, not string
433     "msg":"You do not have permission to perform this operation"
434 }
435 </code></pre>
436      * @return {BasicForm} this
437      */
438     submit : function(options){
439         if(this.standardSubmit){
440             var v = this.isValid();
441             if(v){
442                 var el = this.el.dom;
443                 if(this.url && Ext.isEmpty(el.action)){
444                     el.action = this.url;
445                 }
446                 el.submit();
447             }
448             return v;
449         }
450         var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
451         this.doAction(submitAction, options);
452         return this;
453     },
454
455     <div id="method-Ext.form.BasicForm-load"></div>/**
456      * Shortcut to {@link #doAction do} a {@link Ext.form.Action.Load load action}.
457      * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
458      * @return {BasicForm} this
459      */
460     load : function(options){
461         var loadAction = String.format('{0}load', this.api ? 'direct' : '');
462         this.doAction(loadAction, options);
463         return this;
464     },
465
466     <div id="method-Ext.form.BasicForm-updateRecord"></div>/**
467      * Persists the values in this form into the passed {@link Ext.data.Record} object in a beginEdit/endEdit block.
468      * @param {Record} record The record to edit
469      * @return {BasicForm} this
470      */
471     updateRecord : function(record){
472         record.beginEdit();
473         var fs = record.fields;
474         fs.each(function(f){
475             var field = this.findField(f.name);
476             if(field){
477                 record.set(f.name, field.getValue());
478             }
479         }, this);
480         record.endEdit();
481         return this;
482     },
483
484     <div id="method-Ext.form.BasicForm-loadRecord"></div>/**
485      * Loads an {@link Ext.data.Record} into this form by calling {@link #setValues} with the
486      * {@link Ext.data.Record#data record data}.
487      * See also {@link #trackResetOnLoad}.
488      * @param {Record} record The record to load
489      * @return {BasicForm} this
490      */
491     loadRecord : function(record){
492         this.setValues(record.data);
493         return this;
494     },
495
496     // private
497     beforeAction : function(action){
498         var o = action.options;
499         if(o.waitMsg){
500             if(this.waitMsgTarget === true){
501                 this.el.mask(o.waitMsg, 'x-mask-loading');
502             }else if(this.waitMsgTarget){
503                 this.waitMsgTarget = Ext.get(this.waitMsgTarget);
504                 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
505             }else{
506                 Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
507             }
508         }
509     },
510
511     // private
512     afterAction : function(action, success){
513         this.activeAction = null;
514         var o = action.options;
515         if(o.waitMsg){
516             if(this.waitMsgTarget === true){
517                 this.el.unmask();
518             }else if(this.waitMsgTarget){
519                 this.waitMsgTarget.unmask();
520             }else{
521                 Ext.MessageBox.updateProgress(1);
522                 Ext.MessageBox.hide();
523             }
524         }
525         if(success){
526             if(o.reset){
527                 this.reset();
528             }
529             Ext.callback(o.success, o.scope, [this, action]);
530             this.fireEvent('actioncomplete', this, action);
531         }else{
532             Ext.callback(o.failure, o.scope, [this, action]);
533             this.fireEvent('actionfailed', this, action);
534         }
535     },
536
537     <div id="method-Ext.form.BasicForm-findField"></div>/**
538      * Find a {@link Ext.form.Field} in this form.
539      * @param {String} id The value to search for (specify either a {@link Ext.Component#id id},
540      * {@link Ext.grid.Column#dataIndex dataIndex}, {@link Ext.form.Field#getName name or hiddenName}).
541      * @return Field
542      */
543     findField : function(id){
544         var field = this.items.get(id);
545         if(!Ext.isObject(field)){
546             this.items.each(function(f){
547                 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
548                     field = f;
549                     return false;
550                 }
551             });
552         }
553         return field || null;
554     },
555
556
557     <div id="method-Ext.form.BasicForm-markInvalid"></div>/**
558      * Mark fields in this form invalid in bulk.
559      * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
560      * @return {BasicForm} this
561      */
562     markInvalid : function(errors){
563         if(Ext.isArray(errors)){
564             for(var i = 0, len = errors.length; i < len; i++){
565                 var fieldError = errors[i];
566                 var f = this.findField(fieldError.id);
567                 if(f){
568                     f.markInvalid(fieldError.msg);
569                 }
570             }
571         }else{
572             var field, id;
573             for(id in errors){
574                 if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
575                     field.markInvalid(errors[id]);
576                 }
577             }
578         }
579         return this;
580     },
581
582     <div id="method-Ext.form.BasicForm-setValues"></div>/**
583      * Set values for fields in this form in bulk.
584      * @param {Array/Object} values Either an array in the form:<pre><code>
585 [{id:'clientName', value:'Fred. Olsen Lines'},
586  {id:'portOfLoading', value:'FXT'},
587  {id:'portOfDischarge', value:'OSL'} ]</code></pre>
588      * or an object hash of the form:<pre><code>
589 {
590     clientName: 'Fred. Olsen Lines',
591     portOfLoading: 'FXT',
592     portOfDischarge: 'OSL'
593 }</code></pre>
594      * @return {BasicForm} this
595      */
596     setValues : function(values){
597         if(Ext.isArray(values)){ // array of objects
598             for(var i = 0, len = values.length; i < len; i++){
599                 var v = values[i];
600                 var f = this.findField(v.id);
601                 if(f){
602                     f.setValue(v.value);
603                     if(this.trackResetOnLoad){
604                         f.originalValue = f.getValue();
605                     }
606                 }
607             }
608         }else{ // object hash
609             var field, id;
610             for(id in values){
611                 if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
612                     field.setValue(values[id]);
613                     if(this.trackResetOnLoad){
614                         field.originalValue = field.getValue();
615                     }
616                 }
617             }
618         }
619         return this;
620     },
621
622     <div id="method-Ext.form.BasicForm-getValues"></div>/**
623      * <p>Returns the fields in this form as an object with key/value pairs as they would be submitted using a standard form submit.
624      * If multiple fields exist with the same name they are returned as an array.</p>
625      * <p><b>Note:</b> The values are collected from all enabled HTML input elements within the form, <u>not</u> from
626      * the Ext Field objects. This means that all returned values are Strings (or Arrays of Strings) and that the
627      * value can potentially be the emptyText of a field.</p>
628      * @param {Boolean} asString (optional) Pass true to return the values as a string. (defaults to false, returning an Object)
629      * @return {String/Object}
630      */
631     getValues : function(asString){
632         var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
633         if(asString === true){
634             return fs;
635         }
636         return Ext.urlDecode(fs);
637     },
638
639     <div id="method-Ext.form.BasicForm-getFieldValues"></div>/**
640      * Retrieves the fields in the form as a set of key/value pairs, using the {@link Ext.form.Field#getValue getValue()} method.
641      * If multiple fields exist with the same name they are returned as an array.
642      * @param {Boolean} dirtyOnly (optional) True to return only fields that are dirty.
643      * @return {Object} The values in the form
644      */
645     getFieldValues : function(dirtyOnly){
646         var o = {},
647             n,
648             key,
649             val;
650         this.items.each(function(f){
651             if(dirtyOnly !== true || f.isDirty()){
652                 n = f.getName();
653                 key = o[n];
654                 val = f.getValue();
655                 
656                 if(Ext.isDefined(key)){
657                     if(Ext.isArray(key)){
658                         o[n].push(val);
659                     }else{
660                         o[n] = [key, val];
661                     }
662                 }else{
663                     o[n] = val;
664                 }
665             }
666         });
667         return o;
668     },
669
670     <div id="method-Ext.form.BasicForm-clearInvalid"></div>/**
671      * Clears all invalid messages in this form.
672      * @return {BasicForm} this
673      */
674     clearInvalid : function(){
675         this.items.each(function(f){
676            f.clearInvalid();
677         });
678         return this;
679     },
680
681     <div id="method-Ext.form.BasicForm-reset"></div>/**
682      * Resets this form.
683      * @return {BasicForm} this
684      */
685     reset : function(){
686         this.items.each(function(f){
687             f.reset();
688         });
689         return this;
690     },
691
692     <div id="method-Ext.form.BasicForm-add"></div>/**
693      * Add Ext.form Components to this form's Collection. This does not result in rendering of
694      * the passed Component, it just enables the form to validate Fields, and distribute values to
695      * Fields.
696      * <p><b>You will not usually call this function. In order to be rendered, a Field must be added
697      * to a {@link Ext.Container Container}, usually an {@link Ext.form.FormPanel FormPanel}.
698      * The FormPanel to which the field is added takes care of adding the Field to the BasicForm's
699      * collection.</b></p>
700      * @param {Field} field1
701      * @param {Field} field2 (optional)
702      * @param {Field} etc (optional)
703      * @return {BasicForm} this
704      */
705     add : function(){
706         this.items.addAll(Array.prototype.slice.call(arguments, 0));
707         return this;
708     },
709
710
711     <div id="method-Ext.form.BasicForm-remove"></div>/**
712      * Removes a field from the items collection (does NOT remove its markup).
713      * @param {Field} field
714      * @return {BasicForm} this
715      */
716     remove : function(field){
717         this.items.remove(field);
718         return this;
719     },
720
721     <div id="method-Ext.form.BasicForm-render"></div>/**
722      * Iterates through the {@link Ext.form.Field Field}s which have been {@link #add add}ed to this BasicForm,
723      * checks them for an id attribute, and calls {@link Ext.form.Field#applyToMarkup} on the existing dom element with that id.
724      * @return {BasicForm} this
725      */
726     render : function(){
727         this.items.each(function(f){
728             if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
729                 f.applyToMarkup(f.id);
730             }
731         });
732         return this;
733     },
734
735     <div id="method-Ext.form.BasicForm-applyToFields"></div>/**
736      * Calls {@link Ext#apply} for all fields in this form with the passed object.
737      * @param {Object} values
738      * @return {BasicForm} this
739      */
740     applyToFields : function(o){
741         this.items.each(function(f){
742            Ext.apply(f, o);
743         });
744         return this;
745     },
746
747     <div id="method-Ext.form.BasicForm-applyIfToFields"></div>/**
748      * Calls {@link Ext#applyIf} for all field in this form with the passed object.
749      * @param {Object} values
750      * @return {BasicForm} this
751      */
752     applyIfToFields : function(o){
753         this.items.each(function(f){
754            Ext.applyIf(f, o);
755         });
756         return this;
757     },
758
759     callFieldMethod : function(fnName, args){
760         args = args || [];
761         this.items.each(function(f){
762             if(Ext.isFunction(f[fnName])){
763                 f[fnName].apply(f, args);
764             }
765         });
766         return this;
767     }
768 });
769
770 // back compat
771 Ext.BasicForm = Ext.form.BasicForm;</pre>    \r
772 </body>\r
773 </html>