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