X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/c930e9176a5a85509c5b0230e2bff5c22a591432..HEAD:/docs/source/Table.html diff --git a/docs/source/Table.html b/docs/source/Table.html index 0fb385ff..9f5068d8 100644 --- a/docs/source/Table.html +++ b/docs/source/Table.html @@ -1,95 +1,313 @@ - - - The source code - - - - -
Ext.sql.Table = function(conn, name, keyName){
-	this.conn = conn;
-	this.name = name;
-	this.keyName = keyName;
-};
-
-Ext.sql.Table.prototype = {
-	update : function(o){
-		var clause = this.keyName + " = ?";
-		return this.updateBy(o, clause, [o[this.keyName]]);
-	},
-
-	updateBy : function(o, clause, args){
-		var sql = "UPDATE " + this.name + " set ";
-		var fs = [], a = [];
-		for(var key in o){
-			if(o.hasOwnProperty(key)){
-				fs[fs.length] = key + ' = ?';
-				a[a.length] = o[key];
-			}
-		}
-		for(var key in args){
-			if(args.hasOwnProperty(key)){
-				a[a.length] = args[key];
-			}
-		}
-		sql = [sql, fs.join(','), ' WHERE ', clause].join('');
-		return this.conn.execBy(sql, a);
-	},
-
-	insert : function(o){
-		var sql = "INSERT into " + this.name + " ";
-		var fs = [], vs = [], a = [];
-		for(var key in o){
-			if(o.hasOwnProperty(key)){
-				fs[fs.length] = key;
-				vs[vs.length] = '?';
-				a[a.length] = o[key];
-			}
-		}
-		sql = [sql, '(', fs.join(','), ') VALUES (', vs.join(','), ')'].join('');
-        return this.conn.execBy(sql, a);
-    },
-
-	lookup : function(id){
-		return this.selectBy('where ' + this.keyName + " = ?", [id])[0] || null;
-	},
-
-	exists : function(id){
-		return !!this.lookup(id);
-	},
-
-	save : function(o){
-		if(this.exists(o[this.keyName])){
-            this.update(o);
-        }else{
-            this.insert(o);
-        }
-	},
-
-	select : function(clause){
-		return this.selectBy(clause, null);
-	},
-
-	selectBy : function(clause, args){
-		var sql = "select * from " + this.name;
-		if(clause){
-			sql += ' ' + clause;
-		}
-		args = args || {};
-		return this.conn.queryBy(sql, args);
-	},
-
-	remove : function(clause){
-		this.deleteBy(clause, null);
-	},
-
-	removeBy : function(clause, args){
-		var sql = "delete from " + this.name;
-		if(clause){
-			sql += ' where ' + clause;
-		}
-		args = args || {};
-		this.conn.execBy(sql, args);
-	}
-};
- - \ No newline at end of file + + + + + The source code + + + + + + +
/**
+ * 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 `layout: {type: 'table'}` {@link Ext.container.Container#layout} config, and should generally not
+ * need to be created directly via the new keyword.
+ *
+ * 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:
+ *
+ *   - **rowspan** Applied to the table cell containing the item.
+ *   - **colspan** Applied to the table cell containing the item.
+ *   - **cellId** An id applied to the table cell containing the item.
+ *   - **cellCls** A CSS class name added to the table cell containing the item.
+ *
+ * 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:
+ *
+ *     @example
+ *     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()
+ *     });
+ */
+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
+     * An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification used to
+     * create the layout's `<table>` element. Example:
+     *
+     *     {
+     *         xtype: 'panel',
+     *         layout: {
+     *             type: 'table',
+     *             columns: 3,
+     *             tableAttrs: {
+     *                 style: {
+     *                     width: '100%'
+     *                 }
+     *             }
+     *         }
+     *     }
+     */
+    tableAttrs:null,
+
+    /**
+     * @cfg {Object} trAttrs
+     * An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification used to
+     * create the layout's <tr> elements.
+     */
+
+    /**
+     * @cfg {Object} tdAttrs
+     * An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification used to
+     * create the layout's <td> elements.
+     */
+
+    /**
+     * @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 (this.trAttrs) {
+                    trEl.set(this.trAttrs);
+                }
+            }
+
+            // 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
+            if (this.tdAttrs) {
+                tdEl.set(this.tdAttrs);
+            }
+            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 {Object[]} 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
+            for (j = item.colspan || 1; j; --j) {
+                rowspans[colIdx] = item.rowspan || 1;
+                ++colIdx;
+            }
+            ++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;
+    }
+});
+ +