X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/2e847cf21b8ab9d15fa167b315ca5b2fa92638fc..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/docs/source/Table.html diff --git a/docs/source/Table.html b/docs/source/Table.html new file mode 100644 index 00000000..a611ea7a --- /dev/null +++ b/docs/source/Table.html @@ -0,0 +1,283 @@ +
\ No newline at end of file/** + * @class Ext.layout.container.Table + * @extends Ext.layout.container.Auto + * <p>This layout allows you to easily render content into an HTML table. The total number of columns can be + * specified, and rowspan and colspan can be used to create complex layouts within the table. + * This class is intended to be extended or created via the <code>layout: {type: 'table'}</code> + * {@link Ext.container.Container#layout} config, and should generally not need to be created directly via the new keyword.</p> + * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via + * the {@link Ext.container.Container#layout} object which will then be applied internally to the layout. In the + * case of TableLayout, the only valid layout config properties are {@link #columns} and {@link #tableAttrs}. + * However, the items added to a TableLayout can supply the following table-specific config properties:</p> + * <ul> + * <li><b>rowspan</b> Applied to the table cell containing the item.</li> + * <li><b>colspan</b> Applied to the table cell containing the item.</li> + * <li><b>cellId</b> An id applied to the table cell containing the item.</li> + * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li> + * </ul> + * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard + * HTML table. You simply add each panel (or "cell") that you want to include along with any span attributes + * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts. + * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the + * total column count in the layoutConfig and start adding panels in their natural order from left to right, + * top to bottom. The layout will automatically figure out, based on the column count, rowspans and colspans, + * how to position each panel within the table. Just like with HTML tables, your rowspans and colspans must add + * up correctly in your overall layout or you'll end up with missing and/or extra cells! Example usage:</p> + * {@img Ext.layout.container.Table/Ext.layout.container.Table.png Ext.layout.container.Table container layout} + * <pre><code> +// This code will generate a layout table that is 3 columns by 2 rows +// with some spanning included. The basic layout will be: +// +--------+-----------------+ +// | A | B | +// | |--------+--------| +// | | C | D | +// +--------+--------+--------+ + Ext.create('Ext.panel.Panel', { + title: 'Table Layout', + width: 300, + height: 150, + layout: { + type: 'table', + // The total column count must be specified here + columns: 3 + }, + defaults: { + // applied to each contained panel + bodyStyle:'padding:20px' + }, + items: [{ + html: 'Cell A content', + rowspan: 2 + },{ + html: 'Cell B content', + colspan: 2 + },{ + html: 'Cell C content', + cellCls: 'highlight' + },{ + html: 'Cell D content' + }], + renderTo: Ext.getBody() + }); +</code></pre> + */ + +Ext.define('Ext.layout.container.Table', { + + /* Begin Definitions */ + + alias: ['layout.table'], + extend: 'Ext.layout.container.Auto', + alternateClassName: 'Ext.layout.TableLayout', + + /* End Definitions */ + + /** + * @cfg {Number} columns + * The total number of columns to create in the table for this layout. If not specified, all Components added to + * this layout will be rendered into a single row using one column per Component. + */ + + // private + monitorResize:false, + + type: 'table', + + // Table layout is a self-sizing layout. When an item of for example, a dock layout, the Panel must expand to accommodate + // a table layout. See in particular AbstractDock::onLayout for use of this flag. + autoSize: true, + + clearEl: true, // Base class will not create it if already truthy. Not needed in tables. + + targetCls: Ext.baseCSSPrefix + 'table-layout-ct', + tableCls: Ext.baseCSSPrefix + 'table-layout', + cellCls: Ext.baseCSSPrefix + 'table-layout-cell', + + /** + * @cfg {Object} tableAttrs + * <p>An object containing properties which are added to the {@link Ext.core.DomHelper DomHelper} specification + * used to create the layout's <tt><table></tt> element. Example:</p><pre><code> +{ + xtype: 'panel', + layout: { + type: 'table', + columns: 3, + tableAttrs: { + style: { + width: '100%' + } + } + } +}</code></pre> + */ + tableAttrs:null, + + /** + * @private + * Iterates over all passed items, ensuring they are rendered in a cell in the proper + * location in the table structure. + */ + renderItems: function(items) { + var tbody = this.getTable().tBodies[0], + rows = tbody.rows, + i = 0, + len = items.length, + cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt; + + // Calculate the correct cell structure for the current items + cells = this.calculateCells(items); + + // Loop over each cell and compare to the current cells in the table, inserting/ + // removing/moving cells as needed, and making sure each item is rendered into + // the correct cell. + for (; i < len; i++) { + curCell = cells[i]; + rowIdx = curCell.rowIdx; + cellIdx = curCell.cellIdx; + item = items[i]; + + // If no row present, create and insert one + trEl = rows[rowIdx]; + if (!trEl) { + trEl = tbody.insertRow(rowIdx); + } + + // If no cell present, create and insert one + itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx)); + if (this.needsDivWrap()) { //create wrapper div if needed - see docs below + itemCt = tdEl.first() || tdEl.createChild({tag: 'div'}); + itemCt.setWidth(null); + } + + // Render or move the component into the cell + if (!item.rendered) { + this.renderItem(item, itemCt, 0); + } + else if (!this.isValidParent(item, itemCt, 0)) { + this.moveItem(item, itemCt, 0); + } + + // Set the cell properties + tdEl.set({ + colSpan: item.colspan || 1, + rowSpan: item.rowspan || 1, + id: item.cellId || '', + cls: this.cellCls + ' ' + (item.cellCls || '') + }); + + // If at the end of a row, remove any extra cells + if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) { + cellIdx++; + while (trEl.cells[cellIdx]) { + trEl.deleteCell(cellIdx); + } + } + } + + // Delete any extra rows + rowIdx++; + while (tbody.rows[rowIdx]) { + tbody.deleteRow(rowIdx); + } + }, + + afterLayout: function() { + this.callParent(); + + if (this.needsDivWrap()) { + // set wrapper div width to match layed out item - see docs below + Ext.Array.forEach(this.getLayoutItems(), function(item) { + Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth()); + }); + } + }, + + /** + * @private + * Determine the row and cell indexes for each component, taking into consideration + * the number of columns and each item's configured colspan/rowspan values. + * @param {Array} items The layout components + * @return {Array} List of row and cell indexes for each of the components + */ + calculateCells: function(items) { + var cells = [], + rowIdx = 0, + colIdx = 0, + cellIdx = 0, + totalCols = this.columns || Infinity, + rowspans = [], //rolling list of active rowspans for each column + i = 0, j, + len = items.length, + item; + + for (; i < len; i++) { + item = items[i]; + + // Find the first available row/col slot not taken up by a spanning cell + while (colIdx >= totalCols || rowspans[colIdx] > 0) { + if (colIdx >= totalCols) { + // move down to next row + colIdx = 0; + cellIdx = 0; + rowIdx++; + + // decrement all rowspans + for (j = 0; j < totalCols; j++) { + if (rowspans[j] > 0) { + rowspans[j]--; + } + } + } else { + colIdx++; + } + } + + // Add the cell info to the list + cells.push({ + rowIdx: rowIdx, + cellIdx: cellIdx + }); + + // Increment + rowspans[colIdx] = item.rowspan || 1; + colIdx += item.colspan || 1; + cellIdx++; + } + + return cells; + }, + + /** + * @private + * Return the layout's table element, creating it if necessary. + */ + getTable: function() { + var table = this.table; + if (!table) { + table = this.table = this.getTarget().createChild( + Ext.apply({ + tag: 'table', + role: 'presentation', + cls: this.tableCls, + cellspacing: 0, //TODO should this be specified or should CSS handle it? + cn: {tag: 'tbody'} + }, this.tableAttrs), + null, true + ); + } + return table; + }, + + /** + * @private + * Opera 10.5 has a bug where if a table cell's child has box-sizing:border-box and padding, it + * will include that padding in the size of the cell, making it always larger than the + * shrink-wrapped size of its contents. To get around this we have to wrap the contents in a div + * and then set that div's width to match the item rendered within it afterLayout. This method + * determines whether we need the wrapper div; it currently does a straight UA sniff as this bug + * seems isolated to just Opera 10.5, but feature detection could be added here if needed. + */ + needsDivWrap: function() { + return Ext.isOpera10_5; + } +});