Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/ext/src/widgets/form/CompositeField.js @ 76

Revision 76, 13.7 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/*!
2 * Ext JS Library 3.4.0
3 * Copyright(c) 2006-2011 Sencha Inc.
4 * licensing@sencha.com
5 * http://www.sencha.com/license
6 */
7/**
8 * @class Ext.form.CompositeField
9 * @extends Ext.form.Field
10 * Composite field allowing a number of form Fields to be rendered on the same row. The fields are rendered
11 * using an hbox layout internally, so all of the normal HBox layout config items are available. Example usage:
12 * <pre>
13{
14    xtype: 'compositefield',
15    labelWidth: 120
16    items: [
17        {
18            xtype     : 'textfield',
19            fieldLabel: 'Title',
20            width     : 20
21        },
22        {
23            xtype     : 'textfield',
24            fieldLabel: 'First',
25            flex      : 1
26        },
27        {
28            xtype     : 'textfield',
29            fieldLabel: 'Last',
30            flex      : 1
31        }
32    ]
33}
34 * </pre>
35 * In the example above the composite's fieldLabel will be set to 'Title, First, Last' as it groups the fieldLabels
36 * of each of its children. This can be overridden by setting a fieldLabel on the compositefield itself:
37 * <pre>
38{
39    xtype: 'compositefield',
40    fieldLabel: 'Custom label',
41    items: [...]
42}
43 * </pre>
44 * Any Ext.form.* component can be placed inside a composite field.
45 */
46Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
47
48    /**
49     * @property defaultMargins
50     * @type String
51     * The margins to apply by default to each field in the composite
52     */
53    defaultMargins: '0 5 0 0',
54
55    /**
56     * @property skipLastItemMargin
57     * @type Boolean
58     * If true, the defaultMargins are not applied to the last item in the composite field set (defaults to true)
59     */
60    skipLastItemMargin: true,
61
62    /**
63     * @property isComposite
64     * @type Boolean
65     * Signifies that this is a Composite field
66     */
67    isComposite: true,
68
69    /**
70     * @property combineErrors
71     * @type Boolean
72     * True to combine errors from the individual fields into a single error message at the CompositeField level (defaults to true)
73     */
74    combineErrors: true,
75   
76    /**
77     * @cfg {String} labelConnector The string to use when joining segments of the built label together (defaults to ', ')
78     */
79    labelConnector: ', ',
80   
81    /**
82     * @cfg {Object} defaults Any default properties to assign to the child fields.
83     */
84
85    //inherit docs
86    //Builds the composite field label
87    initComponent: function() {
88        var labels = [],
89            items  = this.items,
90            item;
91
92        for (var i=0, j = items.length; i < j; i++) {
93            item = items[i];
94           
95            if (!Ext.isEmpty(item.ref)){
96                item.ref = '../' + item.ref;
97            }
98
99            labels.push(item.fieldLabel);
100
101            //apply any defaults
102            Ext.applyIf(item, this.defaults);
103
104            //apply default margins to each item except the last
105            if (!(i == j - 1 && this.skipLastItemMargin)) {
106                Ext.applyIf(item, {margins: this.defaultMargins});
107            }
108        }
109
110        this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
111
112        /**
113         * @property fieldErrors
114         * @type Ext.util.MixedCollection
115         * MixedCollection of current errors on the Composite's subfields. This is used internally to track when
116         * to show and hide error messages at the Composite level. Listeners are attached to the MixedCollection's
117         * add, remove and replace events to update the error icon in the UI as errors are added or removed.
118         */
119        this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
120            return item.field;
121        });
122
123        this.fieldErrors.on({
124            scope  : this,
125            add    : this.updateInvalidMark,
126            remove : this.updateInvalidMark,
127            replace: this.updateInvalidMark
128        });
129
130        Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
131       
132        this.innerCt = new Ext.Container({
133            layout  : 'hbox',
134            items   : this.items,
135            cls     : 'x-form-composite',
136            defaultMargins: '0 3 0 0',
137            ownerCt: this
138        });
139        this.innerCt.ownerCt = undefined;
140       
141        var fields = this.innerCt.findBy(function(c) {
142            return c.isFormField;
143        }, this);
144
145        /**
146         * @property items
147         * @type Ext.util.MixedCollection
148         * Internal collection of all of the subfields in this Composite
149         */
150        this.items = new Ext.util.MixedCollection();
151        this.items.addAll(fields);
152       
153    },
154
155    /**
156     * @private
157     * Creates an internal container using hbox and renders the fields to it
158     */
159    onRender: function(ct, position) {
160        if (!this.el) {
161            /**
162             * @property innerCt
163             * @type Ext.Container
164             * A container configured with hbox layout which is responsible for laying out the subfields
165             */
166            var innerCt = this.innerCt;
167            innerCt.render(ct);
168
169            this.el = innerCt.getEl();
170
171            //if we're combining subfield errors into a single message, override the markInvalid and clearInvalid
172            //methods of each subfield and show them at the Composite level instead
173            if (this.combineErrors) {
174                this.eachItem(function(field) {
175                    Ext.apply(field, {
176                        markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
177                        clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
178                    });
179                });
180            }
181
182            //set the label 'for' to the first item
183            var l = this.el.parent().parent().child('label', true);
184            if (l) {
185                l.setAttribute('for', this.items.items[0].id);
186            }
187        }
188
189        Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
190    },
191
192    /**
193     * Called if combineErrors is true and a subfield's markInvalid method is called.
194     * By default this just adds the subfield's error to the internal fieldErrors MixedCollection
195     * @param {Ext.form.Field} field The field that was marked invalid
196     * @param {String} message The error message
197     */
198    onFieldMarkInvalid: function(field, message) {
199        var name  = field.getName(),
200            error = {
201                field: name, 
202                errorName: field.fieldLabel || name,
203                error: message
204            };
205
206        this.fieldErrors.replace(name, error);
207
208        if (!field.preventMark) {
209            field.el.addClass(field.invalidClass);
210        }
211    },
212
213    /**
214     * Called if combineErrors is true and a subfield's clearInvalid method is called.
215     * By default this just updates the internal fieldErrors MixedCollection.
216     * @param {Ext.form.Field} field The field that was marked invalid
217     */
218    onFieldClearInvalid: function(field) {
219        this.fieldErrors.removeKey(field.getName());
220
221        field.el.removeClass(field.invalidClass);
222    },
223
224    /**
225     * @private
226     * Called after a subfield is marked valid or invalid, this checks to see if any of the subfields are
227     * currently invalid. If any subfields are invalid it builds a combined error message marks the composite
228     * invalid, otherwise clearInvalid is called
229     */
230    updateInvalidMark: function() {
231        var ieStrict = Ext.isIE6 && Ext.isStrict;
232
233        if (this.fieldErrors.length == 0) {
234            this.clearInvalid();
235
236            //IE6 in strict mode has a layout bug when using 'under' as the error message target. This fixes it
237            if (ieStrict) {
238                this.clearInvalid.defer(50, this);
239            }
240        } else {
241            var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
242
243            this.sortErrors();
244            this.markInvalid(message);
245
246            //IE6 in strict mode has a layout bug when using 'under' as the error message target. This fixes it
247            if (ieStrict) {
248                this.markInvalid(message);
249            }
250        }
251    },
252
253    /**
254     * Performs validation checks on each subfield and returns false if any of them fail validation.
255     * @return {Boolean} False if any subfield failed validation
256     */
257    validateValue: function(value, preventMark) {
258        var valid = true;
259
260        this.eachItem(function(field) {
261            if (!field.isValid(preventMark)) {
262                valid = false;
263            }
264        });
265
266        return valid;
267    },
268
269    /**
270     * Takes an object containing error messages for contained fields, returning a combined error
271     * string (defaults to just placing each item on a new line). This can be overridden to provide
272     * custom combined error message handling.
273     * @param {Array} errors Array of errors in format: [{field: 'title', error: 'some error'}]
274     * @return {String} The combined error message
275     */
276    buildCombinedErrorMessage: function(errors) {
277        var combined = [],
278            error;
279
280        for (var i = 0, j = errors.length; i < j; i++) {
281            error = errors[i];
282
283            combined.push(String.format("{0}: {1}", error.errorName, error.error));
284        }
285
286        return combined.join("<br />");
287    },
288
289    /**
290     * Sorts the internal fieldErrors MixedCollection by the order in which the fields are defined.
291     * This is called before displaying errors to ensure that the errors are presented in the expected order.
292     * This function can be overridden to provide a custom sorting order if needed.
293     */
294    sortErrors: function() {
295        var fields = this.items;
296
297        this.fieldErrors.sort("ASC", function(a, b) {
298            var findByName = function(key) {
299                return function(field) {
300                    return field.getName() == key;
301                };
302            };
303
304            var aIndex = fields.findIndexBy(findByName(a.field)),
305                bIndex = fields.findIndexBy(findByName(b.field));
306
307            return aIndex < bIndex ? -1 : 1;
308        });
309    },
310
311    /**
312     * Resets each field in the composite to their previous value
313     */
314    reset: function() {
315        this.eachItem(function(item) {
316            item.reset();
317        });
318
319        // Defer the clearInvalid so if BaseForm's collection is being iterated it will be called AFTER it is complete.
320        // Important because reset is being called on both the group and the individual items.
321        (function() {
322            this.clearInvalid();
323        }).defer(50, this);
324    },
325   
326    /**
327     * Calls clearInvalid on all child fields. This is a convenience function and should not often need to be called
328     * as fields usually take care of clearing themselves
329     */
330    clearInvalidChildren: function() {
331        this.eachItem(function(item) {
332            item.clearInvalid();
333        });
334    },
335
336    /**
337     * Builds a label string from an array of subfield labels.
338     * By default this just joins the labels together with a comma
339     * @param {Array} segments Array of each of the labels in the composite field's subfields
340     * @return {String} The built label
341     */
342    buildLabel: function(segments) {
343        return Ext.clean(segments).join(this.labelConnector);
344    },
345
346    /**
347     * Checks each field in the composite and returns true if any is dirty
348     * @return {Boolean} True if any field is dirty
349     */
350    isDirty: function(){
351        //override the behaviour to check sub items.
352        if (this.disabled || !this.rendered) {
353            return false;
354        }
355
356        var dirty = false;
357        this.eachItem(function(item){
358            if(item.isDirty()){
359                dirty = true;
360                return false;
361            }
362        });
363        return dirty;
364    },
365
366    /**
367     * @private
368     * Convenience function which passes the given function to every item in the composite
369     * @param {Function} fn The function to call
370     * @param {Object} scope Optional scope object
371     */
372    eachItem: function(fn, scope) {
373        if(this.items && this.items.each){
374            this.items.each(fn, scope || this);
375        }
376    },
377
378    /**
379     * @private
380     * Passes the resize call through to the inner panel
381     */
382    onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
383        var innerCt = this.innerCt;
384
385        if (this.rendered && innerCt.rendered) {
386            innerCt.setSize(adjWidth, adjHeight);
387        }
388
389        Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
390    },
391
392    /**
393     * @private
394     * Forces the internal container to be laid out again
395     */
396    doLayout: function(shallow, force) {
397        if (this.rendered) {
398            var innerCt = this.innerCt;
399
400            innerCt.forceLayout = this.ownerCt.forceLayout;
401            innerCt.doLayout(shallow, force);
402        }
403    },
404
405    /**
406     * @private
407     */
408    beforeDestroy: function(){
409        Ext.destroy(this.innerCt);
410
411        Ext.form.CompositeField.superclass.beforeDestroy.call(this);
412    },
413
414    //override the behaviour to check sub items.
415    setReadOnly : function(readOnly) {
416        if (readOnly == undefined) {
417            readOnly = true;
418        }
419        readOnly = !!readOnly;
420
421        if(this.rendered){
422            this.eachItem(function(item){
423                item.setReadOnly(readOnly);
424            });
425        }
426        this.readOnly = readOnly;
427    },
428
429    onShow : function() {
430        Ext.form.CompositeField.superclass.onShow.call(this);
431        this.doLayout();
432    },
433
434    //override the behaviour to check sub items.
435    onDisable : function(){
436        this.eachItem(function(item){
437            item.disable();
438        });
439    },
440
441    //override the behaviour to check sub items.
442    onEnable : function(){
443        this.eachItem(function(item){
444            item.enable();
445        });
446    }
447});
448
449Ext.reg('compositefield', Ext.form.CompositeField);
Note: See TracBrowser for help on using the repository browser.