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; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
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.
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:
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.
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 "cell") 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:
44 * Ext.create('Ext.panel.Panel', {
45 * title: 'Table Layout',
50 * // The total column count must be specified here
54 * // applied to each contained panel
55 * bodyStyle: 'padding:20px'
58 * html: 'Cell A content',
61 * html: 'Cell B content',
64 * html: 'Cell C content',
65 * cellCls: 'highlight'
67 * html: 'Cell D content'
69 * renderTo: Ext.getBody()
72 Ext.define('Ext.layout.container.Table', {
74 /* Begin Definitions */
76 alias: ['layout.table'],
77 extend: 'Ext.layout.container.Auto',
78 alternateClassName: 'Ext.layout.TableLayout',
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.
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.
97 clearEl: true, // Base class will not create it if already truthy. Not needed in tables.
99 targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
100 tableCls: Ext.baseCSSPrefix + 'table-layout',
101 cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
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 `<table>` element. Example:
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 <tr> elements.
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 <td> elements.
135 <span id='Ext-layout-container-Table-method-renderItems'> /**
137 * Iterates over all passed items, ensuring they are rendered in a cell in the proper
138 * location in the table structure.
140 renderItems: function(items) {
141 var tbody = this.getTable().tBodies[0],
145 cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
147 // Calculate the correct cell structure for the current items
148 cells = this.calculateCells(items);
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
153 for (; i < len; i++) {
155 rowIdx = curCell.rowIdx;
156 cellIdx = curCell.cellIdx;
159 // If no row present, create and insert one
162 trEl = tbody.insertRow(rowIdx);
164 trEl.set(this.trAttrs);
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);
175 // Render or move the component into the cell
176 if (!item.rendered) {
177 this.renderItem(item, itemCt, 0);
179 else if (!this.isValidParent(item, itemCt, 0)) {
180 this.moveItem(item, itemCt, 0);
183 // Set the cell properties
185 tdEl.set(this.tdAttrs);
188 colSpan: item.colspan || 1,
189 rowSpan: item.rowspan || 1,
190 id: item.cellId || '',
191 cls: this.cellCls + ' ' + (item.cellCls || '')
194 // If at the end of a row, remove any extra cells
195 if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) {
197 while (trEl.cells[cellIdx]) {
198 trEl.deleteCell(cellIdx);
203 // Delete any extra rows
205 while (tbody.rows[rowIdx]) {
206 tbody.deleteRow(rowIdx);
210 afterLayout: function() {
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());
221 <span id='Ext-layout-container-Table-method-calculateCells'> /**
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
228 calculateCells: function(items) {
233 totalCols = this.columns || Infinity,
234 rowspans = [], //rolling list of active rowspans for each column
239 for (; i < len; i++) {
242 // Find the first available row/col slot not taken up by a spanning cell
243 while (colIdx >= totalCols || rowspans[colIdx] > 0) {
244 if (colIdx >= totalCols) {
245 // move down to next row
250 // decrement all rowspans
251 for (j = 0; j < totalCols; j++) {
252 if (rowspans[j] > 0) {
261 // Add the cell info to the list
268 for (j = item.colspan || 1; j; --j) {
269 rowspans[colIdx] = item.rowspan || 1;
278 <span id='Ext-layout-container-Table-method-getTable'> /**
280 * Return the layout's table element, creating it if necessary.
282 getTable: function() {
283 var table = this.table;
285 table = this.table = this.getTarget().createChild(
288 role: 'presentation',
290 cellspacing: 0, //TODO should this be specified or should CSS handle it?
299 <span id='Ext-layout-container-Table-method-needsDivWrap'> /**
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.
308 needsDivWrap: function() {
309 return Ext.isOpera10_5;