Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / src / widgets / layout / TableLayout.js
1 /*!
2  * Ext JS Library 3.0.3
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**\r
8  * @class Ext.layout.TableLayout\r
9  * @extends Ext.layout.ContainerLayout\r
10  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be\r
11  * specified, and rowspan and colspan can be used to create complex layouts within the table.\r
12  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,\r
13  * and should generally not need to be created directly via the new keyword.</p>\r
14  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via\r
15  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the\r
16  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a\r
17  * TableLayout can supply the following table-specific config properties:</p>\r
18  * <ul>\r
19  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>\r
20  * <li><b>colspan</b> Applied to the table cell containing the item.</li>\r
21  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>\r
22  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>\r
23  * </ul>\r
24  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard\r
25  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes\r
26  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.\r
27  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the\r
28  * total column count in the layoutConfig and start adding panels in their natural order from left to right,\r
29  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,\r
30  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add\r
31  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>\r
32  * <pre><code>\r
33 // This code will generate a layout table that is 3 columns by 2 rows\r
34 // with some spanning included.  The basic layout will be:\r
35 // +--------+-----------------+\r
36 // |   A    |   B             |\r
37 // |        |--------+--------|\r
38 // |        |   C    |   D    |\r
39 // +--------+--------+--------+\r
40 var table = new Ext.Panel({\r
41     title: 'Table Layout',\r
42     layout:'table',\r
43     defaults: {\r
44         // applied to each contained panel\r
45         bodyStyle:'padding:20px'\r
46     },\r
47     layoutConfig: {\r
48         // The total column count must be specified here\r
49         columns: 3\r
50     },\r
51     items: [{\r
52         html: '&lt;p&gt;Cell A content&lt;/p&gt;',\r
53         rowspan: 2\r
54     },{\r
55         html: '&lt;p&gt;Cell B content&lt;/p&gt;',\r
56         colspan: 2\r
57     },{\r
58         html: '&lt;p&gt;Cell C content&lt;/p&gt;',\r
59         cellCls: 'highlight'\r
60     },{\r
61         html: '&lt;p&gt;Cell D content&lt;/p&gt;'\r
62     }]\r
63 });\r
64 </code></pre>\r
65  */\r
66 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
67     /**\r
68      * @cfg {Number} columns\r
69      * The total number of columns to create in the table for this layout.  If not specified, all Components added to\r
70      * this layout will be rendered into a single row using one column per Component.\r
71      */\r
72 \r
73     // private\r
74     monitorResize:false,\r
75 \r
76     /**\r
77      * @cfg {Object} tableAttrs\r
78      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
79      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>\r
80 {\r
81     xtype: 'panel',\r
82     layout: 'table',\r
83     layoutConfig: {\r
84         tableAttrs: {\r
85                 style: {\r
86                         width: '100%'\r
87                 }\r
88         },\r
89         columns: 3\r
90     }\r
91 }</code></pre>\r
92      */\r
93     tableAttrs:null,\r
94     \r
95     // private\r
96     setContainer : function(ct){\r
97         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
98 \r
99         this.currentRow = 0;\r
100         this.currentColumn = 0;\r
101         this.cells = [];\r
102     },\r
103 \r
104     // private\r
105     onLayout : function(ct, target){\r
106         var cs = ct.items.items, len = cs.length, c, i;\r
107 \r
108         if(!this.table){\r
109             target.addClass('x-table-layout-ct');\r
110 \r
111             this.table = target.createChild(\r
112                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
113         }\r
114         this.renderAll(ct, target);\r
115     },\r
116 \r
117     // private\r
118     getRow : function(index){\r
119         var row = this.table.tBodies[0].childNodes[index];\r
120         if(!row){\r
121             row = document.createElement('tr');\r
122             this.table.tBodies[0].appendChild(row);\r
123         }\r
124         return row;\r
125     },\r
126 \r
127     // private\r
128     getNextCell : function(c){\r
129         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
130         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
131         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
132             if(!this.cells[rowIndex]){\r
133                 this.cells[rowIndex] = [];\r
134             }\r
135             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
136                 this.cells[rowIndex][colIndex] = true;\r
137             }\r
138         }\r
139         var td = document.createElement('td');\r
140         if(c.cellId){\r
141             td.id = c.cellId;\r
142         }\r
143         var cls = 'x-table-layout-cell';\r
144         if(c.cellCls){\r
145             cls += ' ' + c.cellCls;\r
146         }\r
147         td.className = cls;\r
148         if(c.colspan){\r
149             td.colSpan = c.colspan;\r
150         }\r
151         if(c.rowspan){\r
152             td.rowSpan = c.rowspan;\r
153         }\r
154         this.getRow(curRow).appendChild(td);\r
155         return td;\r
156     },\r
157     \r
158     // private\r
159     getNextNonSpan: function(colIndex, rowIndex){\r
160         var cols = this.columns;\r
161         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
162             if(cols && colIndex >= cols){\r
163                 rowIndex++;\r
164                 colIndex = 0;\r
165             }else{\r
166                 colIndex++;\r
167             }\r
168         }\r
169         return [colIndex, rowIndex];\r
170     },\r
171 \r
172     // private\r
173     renderItem : function(c, position, target){\r
174         if(c && !c.rendered){\r
175             c.render(this.getNextCell(c));\r
176             this.configureItem(c, position);\r
177         }else if(c && !this.isValidParent(c, target)){\r
178             var container = this.getNextCell(c);\r
179             container.insertBefore(c.getDomPositionEl().dom, null);\r
180             c.container = Ext.get(container);\r
181             this.configureItem(c, position);\r
182         }\r
183     },\r
184 \r
185     // private\r
186     isValidParent : function(c, target){\r
187         return c.getDomPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
188     }\r
189 \r
190     /**\r
191      * @property activeItem\r
192      * @hide\r
193      */\r
194 });\r
195 \r
196 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;