Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Table.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-layout-container-Table'>/**
19 </span> * This layout allows you to easily render content into an HTML table. The total number of columns can be specified, and
20  * rowspan and colspan can be used to create complex layouts within the table. This class is intended to be extended or
21  * created via the `layout: {type: 'table'}` {@link Ext.container.Container#layout} config, and should generally not
22  * need to be created directly via the new keyword.
23  *
24  * Note that when creating a layout via config, the layout-specific config properties must be passed in via the {@link
25  * Ext.container.Container#layout} object which will then be applied internally to the layout. In the case of
26  * TableLayout, the only valid layout config properties are {@link #columns} and {@link #tableAttrs}. However, the items
27  * added to a TableLayout can supply the following table-specific config properties:
28  *
29  *   - **rowspan** Applied to the table cell containing the item.
30  *   - **colspan** Applied to the table cell containing the item.
31  *   - **cellId** An id applied to the table cell containing the item.
32  *   - **cellCls** A CSS class name added to the table cell containing the item.
33  *
34  * The basic concept of building up a TableLayout is conceptually very similar to building up a standard HTML table. You
35  * simply add each panel (or &quot;cell&quot;) that you want to include along with any span attributes specified as the special
36  * config properties of rowspan and colspan which work exactly like their HTML counterparts. Rather than explicitly
37  * creating and nesting rows and columns as you would in HTML, you simply specify the total column count in the
38  * layoutConfig and start adding panels in their natural order from left to right, top to bottom. The layout will
39  * automatically figure out, based on the column count, rowspans and colspans, how to position each panel within the
40  * table. Just like with HTML tables, your rowspans and colspans must add up correctly in your overall layout or you'll
41  * end up with missing and/or extra cells! Example usage:
42  *
43  *     @example
44  *     Ext.create('Ext.panel.Panel', {
45  *         title: 'Table Layout',
46  *         width: 300,
47  *         height: 150,
48  *         layout: {
49  *             type: 'table',
50  *             // The total column count must be specified here
51  *             columns: 3
52  *         },
53  *         defaults: {
54  *             // applied to each contained panel
55  *             bodyStyle: 'padding:20px'
56  *         },
57  *         items: [{
58  *             html: 'Cell A content',
59  *             rowspan: 2
60  *         },{
61  *             html: 'Cell B content',
62  *             colspan: 2
63  *         },{
64  *             html: 'Cell C content',
65  *             cellCls: 'highlight'
66  *         },{
67  *             html: 'Cell D content'
68  *         }],
69  *         renderTo: Ext.getBody()
70  *     });
71  */
72 Ext.define('Ext.layout.container.Table', {
73
74     /* Begin Definitions */
75
76     alias: ['layout.table'],
77     extend: 'Ext.layout.container.Auto',
78     alternateClassName: 'Ext.layout.TableLayout',
79
80     /* End Definitions */
81
82 <span id='Ext-layout-container-Table-cfg-columns'>    /**
83 </span>     * @cfg {Number} columns
84      * The total number of columns to create in the table for this layout. If not specified, all Components added to
85      * this layout will be rendered into a single row using one column per Component.
86      */
87
88     // private
89     monitorResize:false,
90
91     type: 'table',
92
93     // Table layout is a self-sizing layout. When an item of for example, a dock layout, the Panel must expand to accommodate
94     // a table layout. See in particular AbstractDock::onLayout for use of this flag.
95     autoSize: true,
96
97     clearEl: true, // Base class will not create it if already truthy. Not needed in tables.
98
99     targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
100     tableCls: Ext.baseCSSPrefix + 'table-layout',
101     cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
102
103 <span id='Ext-layout-container-Table-cfg-tableAttrs'>    /**
104 </span>     * @cfg {Object} tableAttrs
105      * An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification used to
106      * create the layout's `&lt;table&gt;` element. Example:
107      *
108      *     {
109      *         xtype: 'panel',
110      *         layout: {
111      *             type: 'table',
112      *             columns: 3,
113      *             tableAttrs: {
114      *                 style: {
115      *                     width: '100%'
116      *                 }
117      *             }
118      *         }
119      *     }
120      */
121     tableAttrs:null,
122
123 <span id='Ext-layout-container-Table-cfg-trAttrs'>    /**
124 </span>     * @cfg {Object} trAttrs
125      * An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification used to
126      * create the layout's &lt;tr&gt; elements.
127      */
128
129 <span id='Ext-layout-container-Table-cfg-tdAttrs'>    /**
130 </span>     * @cfg {Object} tdAttrs
131      * An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification used to
132      * create the layout's &lt;td&gt; elements.
133      */
134
135 <span id='Ext-layout-container-Table-method-renderItems'>    /**
136 </span>     * @private
137      * Iterates over all passed items, ensuring they are rendered in a cell in the proper
138      * location in the table structure.
139      */
140     renderItems: function(items) {
141         var tbody = this.getTable().tBodies[0],
142             rows = tbody.rows,
143             i = 0,
144             len = items.length,
145             cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
146
147         // Calculate the correct cell structure for the current items
148         cells = this.calculateCells(items);
149
150         // Loop over each cell and compare to the current cells in the table, inserting/
151         // removing/moving cells as needed, and making sure each item is rendered into
152         // the correct cell.
153         for (; i &lt; len; i++) {
154             curCell = cells[i];
155             rowIdx = curCell.rowIdx;
156             cellIdx = curCell.cellIdx;
157             item = items[i];
158
159             // If no row present, create and insert one
160             trEl = rows[rowIdx];
161             if (!trEl) {
162                 trEl = tbody.insertRow(rowIdx);
163                 if (this.trAttrs) {
164                     trEl.set(this.trAttrs);
165                 }
166             }
167
168             // If no cell present, create and insert one
169             itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx));
170             if (this.needsDivWrap()) { //create wrapper div if needed - see docs below
171                 itemCt = tdEl.first() || tdEl.createChild({tag: 'div'});
172                 itemCt.setWidth(null);
173             }
174
175             // Render or move the component into the cell
176             if (!item.rendered) {
177                 this.renderItem(item, itemCt, 0);
178             }
179             else if (!this.isValidParent(item, itemCt, 0)) {
180                 this.moveItem(item, itemCt, 0);
181             }
182
183             // Set the cell properties
184             if (this.tdAttrs) {
185                 tdEl.set(this.tdAttrs);
186             }
187             tdEl.set({
188                 colSpan: item.colspan || 1,
189                 rowSpan: item.rowspan || 1,
190                 id: item.cellId || '',
191                 cls: this.cellCls + ' ' + (item.cellCls || '')
192             });
193
194             // If at the end of a row, remove any extra cells
195             if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) {
196                 cellIdx++;
197                 while (trEl.cells[cellIdx]) {
198                     trEl.deleteCell(cellIdx);
199                 }
200             }
201         }
202
203         // Delete any extra rows
204         rowIdx++;
205         while (tbody.rows[rowIdx]) {
206             tbody.deleteRow(rowIdx);
207         }
208     },
209
210     afterLayout: function() {
211         this.callParent();
212
213         if (this.needsDivWrap()) {
214             // set wrapper div width to match layed out item - see docs below
215             Ext.Array.forEach(this.getLayoutItems(), function(item) {
216                 Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth());
217             });
218         }
219     },
220
221 <span id='Ext-layout-container-Table-method-calculateCells'>    /**
222 </span>     * @private
223      * Determine the row and cell indexes for each component, taking into consideration
224      * the number of columns and each item's configured colspan/rowspan values.
225      * @param {Array} items The layout components
226      * @return {Object[]} List of row and cell indexes for each of the components
227      */
228     calculateCells: function(items) {
229         var cells = [],
230             rowIdx = 0,
231             colIdx = 0,
232             cellIdx = 0,
233             totalCols = this.columns || Infinity,
234             rowspans = [], //rolling list of active rowspans for each column
235             i = 0, j,
236             len = items.length,
237             item;
238
239         for (; i &lt; len; i++) {
240             item = items[i];
241
242             // Find the first available row/col slot not taken up by a spanning cell
243             while (colIdx &gt;= totalCols || rowspans[colIdx] &gt; 0) {
244                 if (colIdx &gt;= totalCols) {
245                     // move down to next row
246                     colIdx = 0;
247                     cellIdx = 0;
248                     rowIdx++;
249
250                     // decrement all rowspans
251                     for (j = 0; j &lt; totalCols; j++) {
252                         if (rowspans[j] &gt; 0) {
253                             rowspans[j]--;
254                         }
255                     }
256                 } else {
257                     colIdx++;
258                 }
259             }
260
261             // Add the cell info to the list
262             cells.push({
263                 rowIdx: rowIdx,
264                 cellIdx: cellIdx
265             });
266
267             // Increment
268             for (j = item.colspan || 1; j; --j) {
269                 rowspans[colIdx] = item.rowspan || 1;
270                 ++colIdx;
271             }
272             ++cellIdx;
273         }
274
275         return cells;
276     },
277
278 <span id='Ext-layout-container-Table-method-getTable'>    /**
279 </span>     * @private
280      * Return the layout's table element, creating it if necessary.
281      */
282     getTable: function() {
283         var table = this.table;
284         if (!table) {
285             table = this.table = this.getTarget().createChild(
286                 Ext.apply({
287                     tag: 'table',
288                     role: 'presentation',
289                     cls: this.tableCls,
290                     cellspacing: 0, //TODO should this be specified or should CSS handle it?
291                     cn: {tag: 'tbody'}
292                 }, this.tableAttrs),
293                 null, true
294             );
295         }
296         return table;
297     },
298
299 <span id='Ext-layout-container-Table-method-needsDivWrap'>    /**
300 </span>     * @private
301      * Opera 10.5 has a bug where if a table cell's child has box-sizing:border-box and padding, it
302      * will include that padding in the size of the cell, making it always larger than the
303      * shrink-wrapped size of its contents. To get around this we have to wrap the contents in a div
304      * and then set that div's width to match the item rendered within it afterLayout. This method
305      * determines whether we need the wrapper div; it currently does a straight UA sniff as this bug
306      * seems isolated to just Opera 10.5, but feature detection could be added here if needed.
307      */
308     needsDivWrap: function() {
309         return Ext.isOpera10_5;
310     }
311 });</pre>
312 </body>
313 </html>