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