source: trunk/web/addons/job_monarch/lib/extjs-30/src/widgets/form/BasicForm.js @ 625

Last change on this file since 625 was 625, checked in by ramonb, 15 years ago

lib/extjs-30:

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