Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[extjs.git] / examples / ux / FieldLabeler.js
1 /*!
2  * Ext JS Library 3.2.2
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 Ext.ns("Ext.ux");
8
9 /**
10  * @class Ext.ux.FieldLabeler
11  * <p>A plugin for Field Components which renders standard Ext form wrapping and labels
12  * round the Field at render time regardless of the layout of the Container.</p>
13  * <p>Usage:</p>
14  * <pre><code>
15     {
16         xtype: 'combo',
17         plugins: [ Ext.ux.FieldLabeler ],
18         triggerAction: 'all',
19         fieldLabel: 'Select type',
20         store: typeStore
21     }
22  * </code></pre>
23  */
24 Ext.ux.FieldLabeler = (function(){
25
26 //  Pulls a named property down from the first ancestor Container it's found in
27     function getParentProperty(propName) {
28         for (var p = this.ownerCt; p; p = p.ownerCt) {
29             if (p[propName]) {
30                 return p[propName];
31             }
32         }
33     }
34
35     return {
36
37 //      Add behaviour at important points in the Field's lifecycle.
38         init: function(f) {
39 //          Replace the Field's onRender method with a sequence that calls the plugin's onRender after the Field's onRender
40             f.onRender = f.onRender.createSequence(this.onRender);
41
42 //          We need to completely override the onResize method because of the complexity
43             f.onResize = this.onResize;
44
45 //          Replace the Field's onDestroy method with a sequence that calls the plugin's onDestroy after the Field's onRender
46             f.onDestroy = f.onDestroy.createSequence(this.onDestroy);
47         },
48
49         onRender: function() {
50 //          Do nothing if being rendered by a form layout
51             if (this.ownerCt) {
52                 if (this.ownerCt.layout instanceof Ext.layout.FormLayout) {
53                     return;
54                 }
55             }
56
57             this.resizeEl = (this.wrap || this.el).wrap({
58                 cls: 'x-form-element',
59                 style: (Ext.isIE || Ext.isOpera) ? 'position:absolute;top:0;left:0;overflow:visible' : ''
60             });
61             this.positionEl = this.itemCt = this.resizeEl.wrap({
62                 cls: 'x-form-item '
63             });
64             if (this.nextSibling()) {
65                 this.margins = {
66                     top: 0,
67                     right: 0,
68                     bottom: this.positionEl.getMargins('b'),
69                     left: 0
70                 };
71             }
72             this.actionMode = 'itemCt';
73
74 //          If our Container is hiding labels, then we're done!
75             if (!Ext.isDefined(this.hideLabels)) {
76                 this.hideLabels = getParentProperty.call(this, "hideLabels");
77             }
78             if (this.hideLabels) {
79                 this.resizeEl.setStyle('padding-left', '0px');
80                 return;
81             }
82
83 //          Collect the info we need to render the label from our Container.
84             if (!Ext.isDefined(this.labelSeparator)) {
85                 this.labelSeparator = getParentProperty.call(this, "labelSeparator");
86             }
87             if (!Ext.isDefined(this.labelPad)) {
88                 this.labelPad = getParentProperty.call(this, "labelPad");
89             }
90             if (!Ext.isDefined(this.labelAlign)) {
91                 this.labelAlign = getParentProperty.call(this, "labelAlign") || 'left';
92             }
93             this.itemCt.addClass('x-form-label-' + this.labelAlign);
94
95             if(this.labelAlign == 'top'){
96                 if (!this.labelWidth) {
97                     this.labelWidth = 'auto';
98                 }
99                 this.resizeEl.setStyle('padding-left', '0px');
100             } else {
101                 if (!Ext.isDefined(this.labelWidth)) {
102                     this.labelWidth = getParentProperty.call(this, "labelWidth") || 100;
103                 }
104                 this.resizeEl.setStyle('padding-left', (this.labelWidth + (this.labelPad || 5)) + 'px');
105                 this.labelWidth += 'px';
106             }
107
108             this.label = this.itemCt.insertFirst({
109                 tag: 'label',
110                 cls: 'x-form-item-label',
111                 style: {
112                     width: this.labelWidth
113                 },
114                 html: this.fieldLabel + (this.labelSeparator || ':')
115             });
116         },
117
118 //      private
119 //      Ensure the input field is sized to fit in the content area of the resizeEl (to the right of its padding-left)
120 //      We perform all necessary sizing here. We do NOT call the current class's onResize because we need this control
121 //      we skip that and go up the hierarchy to Ext.form.Field
122         onResize: function(w, h) {
123             Ext.form.Field.prototype.onResize.apply(this, arguments);
124             w -= this.resizeEl.getPadding('l');
125             if (this.getTriggerWidth) {
126                 this.wrap.setWidth(w);
127                 this.el.setWidth(w - this.getTriggerWidth());
128             } else {
129                 this.el.setWidth(w);
130             }
131             if (this.el.dom.tagName.toLowerCase() == 'textarea') {
132                 var h = this.resizeEl.getHeight(true);
133                 if (!this.hideLabels && (this.labelAlign == 'top')) {
134                     h -= this.label.getHeight();
135                 }
136                 this.el.setHeight(h);
137             }
138         },
139
140 //      private
141 //      Ensure that we clean up on destroy.
142         onDestroy: function() {
143             this.itemCt.remove();
144         }
145     };
146 })();