X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/3789b528d8dd8aad4558e38e22d775bcab1cbd36..6746dc89c47ed01b165cc1152533605f97eb8e8d:/docs/source/Container2.html diff --git a/docs/source/Container2.html b/docs/source/Container2.html index 812ac75f..2240c5f8 100644 --- a/docs/source/Container2.html +++ b/docs/source/Container2.html @@ -15,771 +15,186 @@
-/** - * @class Ext.grid.header.Container - * @extends Ext.container.Container - * @private +/** + * @class Ext.container.Container + * @extends Ext.container.AbstractContainer + * <p>Base class for any {@link Ext.Component} that may contain other Components. Containers handle the + * basic behavior of containing items, namely adding, inserting and removing items.</p> * - * Container which holds headers and is docked at the top or bottom of a TablePanel. - * The HeaderContainer drives resizing/moving/hiding of columns within the TableView. - * As headers are hidden, moved or resized the headercontainer is responsible for - * triggering changes within the view. + * <p>The most commonly used Container classes are {@link Ext.panel.Panel}, {@link Ext.window.Window} and {@link Ext.tab.Panel}. + * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight + * Container to be encapsulated by an HTML element to your specifications by using the + * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option.</p> * - * @xtype headercontainer - */ -Ext.define('Ext.grid.header.Container', { - extend: 'Ext.container.Container', - uses: [ - 'Ext.grid.ColumnLayout', - 'Ext.grid.column.Column', - 'Ext.menu.Menu', - 'Ext.menu.CheckItem', - 'Ext.menu.Separator', - 'Ext.grid.plugin.HeaderResizer', - 'Ext.grid.plugin.HeaderReorderer' - ], - border: true, - - alias: 'widget.headercontainer', - - baseCls: Ext.baseCSSPrefix + 'grid-header-ct', - dock: 'top', - - /** - * @cfg {Number} weight - * HeaderContainer overrides the default weight of 0 for all docked items to 100. - * This is so that it has more priority over things like toolbars. - */ - weight: 100, - defaultType: 'gridcolumn', - /** - * @cfg {Number} defaultWidth - * Width of the header if no width or flex is specified. Defaults to 100. - */ - defaultWidth: 100, - - - sortAscText: 'Sort Ascending', - sortDescText: 'Sort Descending', - sortClearText: 'Clear Sort', - columnsText: 'Columns', - - lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last', - firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first', - headerOpenCls: Ext.baseCSSPrefix + 'column-header-open', - - // private; will probably be removed by 4.0 - triStateSort: false, - - ddLock: false, - - dragging: false, - - /** - * <code>true</code> if this HeaderContainer is in fact a group header which contains sub headers. - * @type Boolean - * @property isGroupHeader - */ - - /** - * @cfg {Boolean} sortable - * Provides the default sortable state for all Headers within this HeaderContainer. - * Also turns on or off the menus in the HeaderContainer. Note that the menu is - * shared across every header and therefore turning it off will remove the menu - * items for every header. - */ - sortable: true, - - initComponent: function() { - var me = this; - - me.headerCounter = 0; - me.plugins = me.plugins || []; - - // TODO: Pass in configurations to turn on/off dynamic - // resizing and disable resizing all together - - // Only set up a Resizer and Reorderer for the topmost HeaderContainer. - // Nested Group Headers are themselves HeaderContainers - if (!me.isHeader) { - me.resizer = Ext.create('Ext.grid.plugin.HeaderResizer'); - me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer'); - if (!me.enableColumnResize) { - me.resizer.disable(); - } - if (!me.enableColumnMove) { - me.reorderer.disable(); - } - me.plugins.push(me.reorderer, me.resizer); - } - - // Base headers do not need a box layout - if (me.isHeader && !me.items) { - me.layout = 'auto'; - } - // HeaderContainer and Group header needs a gridcolumn layout. - else { - me.layout = { - type: 'gridcolumn', - availableSpaceOffset: me.availableSpaceOffset, - align: 'stretchmax', - resetStretch: true - }; - } - me.defaults = me.defaults || {}; - Ext.applyIf(me.defaults, { - width: me.defaultWidth, - triStateSort: me.triStateSort, - sortable: me.sortable - }); - me.callParent(); - me.addEvents( - /** - * @event columnresize - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - * @param {Number} width - */ - 'columnresize', - - /** - * @event headerclick - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - * @param {Ext.EventObject} e - * @param {HTMLElement} t - */ - 'headerclick', - - /** - * @event headertriggerclick - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - * @param {Ext.EventObject} e - * @param {HTMLElement} t - */ - 'headertriggerclick', - - /** - * @event columnmove - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - * @param {Number} fromIdx - * @param {Number} toIdx - */ - 'columnmove', - /** - * @event columnhide - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - */ - 'columnhide', - /** - * @event columnshow - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - */ - 'columnshow', - /** - * @event sortchange - * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. - * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition - * @param {String} direction - */ - 'sortchange', - * @event menucreate - * Fired immediately after the column header menu is created. - * @param {Ext.grid.header.Container} ct This instance - * @param {Ext.menu.Menu} menu The Menu that was created - */ - 'menucreate' - ); - }, - - onDestroy: function() { - Ext.destroy(this.resizer, this.reorderer); - this.callParent(); - }, - - // Invalidate column cache on add - // We cannot refresh the View on every add because this method is called - // when the HeaderDropZone moves Headers around, that will also refresh the view - onAdd: function(c) { - var me = this; - if (!c.headerId) { - c.headerId = 'h' + (++me.headerCounter); - } - me.callParent(arguments); - me.purgeCache(); - }, - - // Invalidate column cache on remove - // We cannot refresh the View on every remove because this method is called - // when the HeaderDropZone moves Headers around, that will also refresh the view - onRemove: function(c) { - var me = this; - me.callParent(arguments); - me.purgeCache(); - }, - - afterRender: function() { - this.callParent(); - var store = this.up('[store]').store, - sorters = store.sorters, - first = sorters.first(), - hd; - - if (first) { - hd = this.down('gridcolumn[dataIndex=' + first.property +']'); - if (hd) { - hd.setSortState(first.direction, false, true); - } - } - }, - - afterLayout: function() { - if (!this.isHeader) { - var me = this, - topHeaders = me.query('>gridcolumn:not([hidden])'), - viewEl; - - me.callParent(arguments); - - if (topHeaders.length) { - topHeaders[0].el.radioCls(me.firstHeaderCls); - topHeaders[topHeaders.length - 1].el.radioCls(me.lastHeaderCls); - } - } - }, - - onHeaderShow: function(header) { - // Pass up to the GridSection - var me = this, - gridSection = me.ownerCt, - menu = me.getMenu(), - topItems, topItemsVisible, - colCheckItem, - itemToEnable, - len, i; - - if (menu) { - - colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']'); - if (colCheckItem) { - colCheckItem.setChecked(true, true); - } - - // There's more than one header visible, and we've disabled some checked items... re-enable them - topItems = menu.query('#columnItem>menucheckitem[checked]'); - topItemsVisible = topItems.length; - if ((me.getVisibleGridColumns().length > 1) && me.disabledMenuItems && me.disabledMenuItems.length) { - if (topItemsVisible == 1) { - Ext.Array.remove(me.disabledMenuItems, topItems[0]); - } - for (i = 0, len = me.disabledMenuItems.length; i < len; i++) { - itemToEnable = me.disabledMenuItems[i]; - if (!itemToEnable.isDestroyed) { - itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable'](); - } - } - if (topItemsVisible == 1) { - me.disabledMenuItems = topItems; - } else { - me.disabledMenuItems = []; - } - } - } - - // Only update the grid UI when we are notified about base level Header shows; - // Group header shows just cause a layout of the HeaderContainer - if (!header.isGroupHeader) { - if (me.view) { - me.view.onHeaderShow(me, header, true); - } - if (gridSection) { - gridSection.onHeaderShow(me, header); - } - } - me.fireEvent('columnshow', me, header); - - // The header's own hide suppresses cascading layouts, so lay the headers out now - me.doLayout(); - }, - - onHeaderHide: function(header, suppressLayout) { - // Pass up to the GridSection - var me = this, - gridSection = me.ownerCt, - menu = me.getMenu(), - colCheckItem; - - if (menu) { - - // If the header was hidden programmatically, sync the Menu state - colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']'); - if (colCheckItem) { - colCheckItem.setChecked(false, true); - } - me.setDisabledItems(); - } - - // Only update the UI when we are notified about base level Header hides; - if (!header.isGroupHeader) { - if (me.view) { - me.view.onHeaderHide(me, header, true); - } - if (gridSection) { - gridSection.onHeaderHide(me, header); - } - - // The header's own hide suppresses cascading layouts, so lay the headers out now - if (!suppressLayout) { - me.doLayout(); - } - } - me.fireEvent('columnhide', me, header); - }, - - setDisabledItems: function(){ - var me = this, - menu = me.getMenu(), - i = 0, - len, - itemsToDisable, - itemToDisable; - - // Find what to disable. If only one top level item remaining checked, we have to disable stuff. - itemsToDisable = menu.query('#columnItem>menucheckitem[checked]'); - if ((itemsToDisable.length === 1)) { - if (!me.disabledMenuItems) { - me.disabledMenuItems = []; - } - - // If down to only one column visible, also disable any descendant checkitems - if ((me.getVisibleGridColumns().length === 1) && itemsToDisable[0].menu) { - itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]')); - } - - len = itemsToDisable.length; - // Disable any further unchecking at any level. - for (i = 0; i < len; i++) { - itemToDisable = itemsToDisable[i]; - if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) { - itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable'](); - me.disabledMenuItems.push(itemToDisable); - } - } - } - }, - - /** - * Temporarily lock the headerCt. This makes it so that clicking on headers - * don't trigger actions like sorting or opening of the header menu. This is - * done because extraneous events may be fired on the headers after interacting - * with a drag drop operation. - * @private - */ - tempLock: function() { - this.ddLock = true; - Ext.Function.defer(function() { - this.ddLock = false; - }, 200, this); - }, - - onHeaderResize: function(header, w, suppressFocus) { - this.tempLock(); - if (this.view && this.view.rendered) { - this.view.onHeaderResize(header, w, suppressFocus); - } - this.fireEvent('columnresize', this, header, w); - }, - - onHeaderClick: function(header, e, t) { - this.fireEvent("headerclick", this, header, e, t); - }, - - onHeaderTriggerClick: function(header, e, t) { - // generate and cache menu, provide ability to cancel/etc - if (this.fireEvent("headertriggerclick", this, header, e, t) !== false) { - this.showMenuBy(t, header); - } - }, - - showMenuBy: function(t, header) { - var menu = this.getMenu(), - ascItem = menu.down('#ascItem'), - descItem = menu.down('#descItem'), - sortableMth; - - menu.activeHeader = menu.ownerCt = header; - menu.setFloatParent(header); - // TODO: remove coupling to Header's titleContainer el - header.titleContainer.addCls(this.headerOpenCls); - - // enable or disable asc & desc menu items based on header being sortable - sortableMth = header.sortable ? 'enable' : 'disable'; - if (ascItem) { - ascItem[sortableMth](); - } - if (descItem) { - descItem[sortableMth](); - } - menu.showBy(t); - }, - - // remove the trigger open class when the menu is hidden - onMenuDeactivate: function() { - var menu = this.getMenu(); - // TODO: remove coupling to Header's titleContainer el - menu.activeHeader.titleContainer.removeCls(this.headerOpenCls); - }, - - moveHeader: function(fromIdx, toIdx) { - - // An automatically expiring lock - this.tempLock(); - this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx); - }, - - purgeCache: function() { - var me = this; - // Delete column cache - column order has changed. - delete me.gridDataColumns; - - // Menu changes when columns are moved. It will be recreated. - if (me.menu) { - me.menu.destroy(); - delete me.menu; - } - }, - - onHeaderMoved: function(header, fromIdx, toIdx) { - var me = this, - gridSection = me.ownerCt; - - if (gridSection) { - gridSection.onHeaderMove(me, header, fromIdx, toIdx); - } - me.fireEvent("columnmove", me, header, fromIdx, toIdx); - }, - - /** - * Gets the menu (and will create it if it doesn't already exist) - * @private - */ - getMenu: function() { - var me = this; - - if (!me.menu) { - me.menu = Ext.create('Ext.menu.Menu', { - items: me.getMenuItems(), - listeners: { - deactivate: me.onMenuDeactivate, - scope: me - } - }); - me.setDisabledItems(); - me.fireEvent('menucreate', me, me.menu); - } - return me.menu; - }, - - /** - * Returns an array of menu items to be placed into the shared menu - * across all headers in this header container. - * @returns {Array} menuItems - */ - getMenuItems: function() { - var me = this, - menuItems = [{ - itemId: 'columnItem', - text: me.columnsText, - cls: Ext.baseCSSPrefix + 'cols-icon', - menu: me.getColumnMenu(me) - }]; - - if (me.sortable) { - menuItems.unshift({ - itemId: 'ascItem', - text: me.sortAscText, - cls: 'xg-hmenu-sort-asc', - handler: me.onSortAscClick, - scope: me - },{ - itemId: 'descItem', - text: me.sortDescText, - cls: 'xg-hmenu-sort-desc', - handler: me.onSortDescClick, - scope: me - },'-'); - } - return menuItems; - }, - - // sort asc when clicking on item in menu - onSortAscClick: function() { - var menu = this.getMenu(), - activeHeader = menu.activeHeader; - - activeHeader.setSortState('ASC'); - }, - - // sort desc when clicking on item in menu - onSortDescClick: function() { - var menu = this.getMenu(), - activeHeader = menu.activeHeader; - - activeHeader.setSortState('DESC'); - }, - - /** - * Returns an array of menu CheckItems corresponding to all immediate children of the passed Container which have been configured as hideable. - */ - getColumnMenu: function(headerContainer) { - var menuItems = [], - i = 0, - item, - items = headerContainer.query('>gridcolumn[hideable]'), - itemsLn = items.length, - menuItem; - - for (; i < itemsLn; i++) { - item = items[i]; - menuItem = Ext.create('Ext.menu.CheckItem', { - text: item.text, - checked: !item.hidden, - hideOnClick: false, - headerId: item.id, - menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined, - checkHandler: this.onColumnCheckChange, - scope: this - }); - if (itemsLn === 1) { - menuItem.disabled = true; - } - menuItems.push(menuItem); - - // If the header is ever destroyed - for instance by dragging out the last remaining sub header, - // then the associated menu item must also be destroyed. - item.on({ - destroy: Ext.Function.bind(menuItem.destroy, menuItem) - }); - } - return menuItems; - }, - - onColumnCheckChange: function(checkItem, checked) { - var header = Ext.getCmp(checkItem.headerId); - header[checked ? 'show' : 'hide'](); - }, + * {@img Ext.Container/Ext.Container.png Ext.Container component} + * <p>The code below illustrates how to explicitly create a Container:<pre><code> +// explicitly create a Container +Ext.create('Ext.container.Container', { + layout: { + type: 'hbox' + }, + width: 400, + renderTo: Ext.getBody(), + border: 1, + style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'}, + defaults: { + labelWidth: 80, + // implicitly create Container by specifying xtype + xtype: 'datefield', + flex: 1, + style: { + padding: '10px' + } + }, + items: [{ + xtype: 'datefield', + name: 'startDate', + fieldLabel: 'Start date' + },{ + xtype: 'datefield', + name: 'endDate', + fieldLabel: 'End date' + }] +}); +</code></pre></p> + * + * <p><u><b>Layout</b></u></p> + * <p>Container classes delegate the rendering of child Components to a layout + * manager class which must be configured into the Container using the + * <code><b>{@link #layout}</b></code> configuration property.</p> + * <p>When either specifying child <code>{@link #items}</code> of a Container, + * or dynamically {@link #add adding} Components to a Container, remember to + * consider how you wish the Container to arrange those child elements, and + * whether those child elements need to be sized using one of Ext's built-in + * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the + * {@link Ext.layout.container.Auto Auto} scheme which only + * renders child components, appending them one after the other inside the + * Container, and <b>does not apply any sizing</b> at all.</p> + * <p>A common mistake is when a developer neglects to specify a + * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or + * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code> + * has been specified). If a Container is left to use the default + * {Ext.layout.container.Auto Auto} scheme, none of its + * child components will be resized, or changed in any way when the Container + * is resized.</p> + * <p>Certain layout managers allow dynamic addition of child components. + * Those that do include {@link Ext.layout.container.Card}, + * {@link Ext.layout.container.Anchor}, {@link Ext.layout.container.VBox}, {@link Ext.layout.container.HBox}, and + * {@link Ext.layout.container.Table}. For example:<pre><code> +// Create the GridPanel. +var myNewGrid = new Ext.grid.Panel({ + store: myStore, + headers: myHeaders, + title: 'Results', // the title becomes the title of the tab +}); - /** - * Get the columns used for generating a template via TableChunker. - * Returns an array of all columns and their - * - dataIndex - * - align - * - width - * - id - * - columnId - used to create an identifying CSS class - * - cls The tdCls configuration from the Column object - * @private - */ - getColumnsForTpl: function(flushCache) { - var cols = [], - headers = this.getGridColumns(flushCache), - headersLn = headers.length, +myTabPanel.add(myNewGrid); // {@link Ext.tab.Panel} implicitly uses {@link Ext.layout.container.Card Card} +myTabPanel.{@link Ext.tab.Panel#setActiveTab setActiveTab}(myNewGrid); + * </code></pre></p> + * <p>The example above adds a newly created GridPanel to a TabPanel. Note that + * a TabPanel uses {@link Ext.layout.container.Card} as its layout manager which + * means all its child items are sized to {@link Ext.layout.container.Fit fit} + * exactly into its client area. + * <p><b><u>Overnesting is a common problem</u></b>. + * An example of overnesting occurs when a GridPanel is added to a TabPanel + * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no + * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel + * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a + * Component which can be added directly to a Container. If the wrapping Panel + * has no <code><b>{@link #layout}</b></code> configuration, then the overnested + * GridPanel will not be sized as expected.<p> + * + * <p><u><b>Adding via remote configuration</b></u></p> + * + * <p>A server side script can be used to add Components which are generated dynamically on the server. + * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server + * based on certain parameters: + * </p><pre><code> +// execute an Ajax request to invoke server side script: +Ext.Ajax.request({ + url: 'gen-invoice-grid.php', + // send additional parameters to instruct server script + params: { + startDate: Ext.getCmp('start-date').getValue(), + endDate: Ext.getCmp('end-date').getValue() + }, + // process the response object to add it to the TabPanel: + success: function(xhr) { + var newComponent = eval(xhr.responseText); // see discussion below + myTabPanel.add(newComponent); // add the component to the TabPanel + myTabPanel.setActiveTab(newComponent); + }, + failure: function() { + Ext.Msg.alert("Grid create failed", "Server communication failure"); + } +}); +</code></pre> + * <p>The server script needs to return a JSON representation of a configuration object, which, when decoded + * will return a config object with an {@link Ext.Component#xtype xtype}. The server might return the following + * JSON:</p><pre><code> +{ + "xtype": 'grid', + "title": 'Invoice Report', + "store": { + "model": 'Invoice', + "proxy": { + "type": 'ajax', + "url": 'get-invoice-data.php', + "reader": { + "type": 'json' + "record": 'transaction', + "idProperty": 'id', + "totalRecords": 'total' + }) + }, + "autoLoad": { + "params": { + "startDate": '01/01/2008', + "endDate": '01/31/2008' + } + } + }, + "headers": [ + {"header": "Customer", "width": 250, "dataIndex": 'customer', "sortable": true}, + {"header": "Invoice Number", "width": 120, "dataIndex": 'invNo', "sortable": true}, + {"header": "Invoice Date", "width": 100, "dataIndex": 'date', "renderer": Ext.util.Format.dateRenderer('M d, y'), "sortable": true}, + {"header": "Value", "width": 120, "dataIndex": 'value', "renderer": 'usMoney', "sortable": true} + ] +} +</code></pre> + * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler + * of the Ajax request, the result will be a config object which, when added to a Container, will cause instantiation + * of a GridPanel. <b>Be sure that the Container is configured with a layout which sizes and positions the child items to your requirements.</b></p> + * <p>Note: since the code above is <i>generated</i> by a server script, the <code>autoLoad</code> params for + * the Store, the user's preferred date format, the metadata to allow generation of the Model layout, and the ColumnModel + * can all be generated into the code since these are all known on the server.</p> + */ +Ext.define('Ext.container.Container', { + extend: 'Ext.container.AbstractContainer', + alias: 'widget.container', + alternateClassName: 'Ext.Container', + + /** + * Return the immediate child Component in which the passed element is located. + * @param el The element to test. + * @return {Component} The child item which contains the passed element. + */ + getChildByElement: function(el) { + var item, + itemEl, i = 0, - header; - - for (; i < headersLn; i++) { - header = headers[i]; - cols.push({ - dataIndex: header.dataIndex, - align: header.align, - width: header.hidden ? 0 : header.getDesiredWidth(), - id: header.id, - cls: header.tdCls, - columnId: header.getItemId() - }); - } - return cols; - }, - - /** - * Returns the number of <b>grid columns</b> descended from this HeaderContainer. - * Group Columns are HeaderContainers. All grid columns are returned, including hidden ones. - */ - getColumnCount: function() { - return this.getGridColumns().length; - }, - - /** - * Gets the full width of all columns that are visible. - */ - getFullWidth: function(flushCache) { - var fullWidth = 0, - headers = this.getVisibleGridColumns(flushCache), - headersLn = headers.length, - i = 0; - - for (; i < headersLn; i++) { - if (!isNaN(headers[i].width)) { - // use headers getDesiredWidth if its there - if (headers[i].getDesiredWidth) { - fullWidth += headers[i].getDesiredWidth(); - // if injected a diff cmp use getWidth - } else { - fullWidth += headers[i].getWidth(); - } - } - } - return fullWidth; - }, - - // invoked internally by a header when not using triStateSorting - clearOtherSortStates: function(activeHeader) { - var headers = this.getGridColumns(), - headersLn = headers.length, - i = 0, - oldSortState; - - for (; i < headersLn; i++) { - if (headers[i] !== activeHeader) { - oldSortState = headers[i].sortState; - // unset the sortstate and dont recurse - headers[i].setSortState(null, true); - //if (!silent && oldSortState !== null) { - // this.fireEvent('sortchange', this, headers[i], null); - //} - } - } - }, - - /** - * Returns an array of the <b>visible<b> columns in the grid. This goes down to the lowest column header - * level, and does not return <i>grouped</i> headers which contain sub headers. - * @param {Boolean} refreshCache If omitted, the cached set of columns will be returned. Pass true to refresh the cache. - * @returns {Array} - */ - getVisibleGridColumns: function(refreshCache) { - return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache)); - }, - - /** - * Returns an array of all columns which map to Store fields. This goes down to the lowest column header - * level, and does not return <i>grouped</i> headers which contain sub headers. - * @param {Boolean} refreshCache If omitted, the cached set of columns will be returned. Pass true to refresh the cache. - * @returns {Array} - */ - getGridColumns: function(refreshCache) { - var me = this, - result = refreshCache ? null : me.gridDataColumns; - - // Not already got the column cache, so collect the base columns - if (!result) { - me.gridDataColumns = result = []; - me.cascade(function(c) { - if ((c !== me) && !c.isGroupHeader) { - result.push(c); - } - }); - } - - return result; - }, - - /** - * Get the index of a leaf level header regardless of what the nesting - * structure is. - */ - getHeaderIndex: function(header) { - var columns = this.getGridColumns(); - return Ext.Array.indexOf(columns, header); - }, + it = this.items.items, + ln = it.length; - /** - * Get a leaf level header by index regardless of what the nesting - * structure is. - */ - getHeaderAtIndex: function(index) { - var columns = this.getGridColumns(); - return columns[index]; - }, - - /** - * Maps the record data to base it on the header id's. - * This correlates to the markup/template generated by - * TableChunker. - */ - prepareData: function(data, rowIdx, record, view, panel) { - var obj = {}, - headers = this.gridDataColumns || this.getGridColumns(), - headersLn = headers.length, - colIdx = 0, - header, - headerId, - renderer, - value, - metaData, - store = panel.store; - - for (; colIdx < headersLn; colIdx++) { - metaData = { - tdCls: '', - style: '' - }; - header = headers[colIdx]; - headerId = header.id; - renderer = header.renderer; - value = data[header.dataIndex]; - - // When specifying a renderer as a string, it always resolves - // to Ext.util.Format - if (typeof renderer === "string") { - header.renderer = renderer = Ext.util.Format[renderer]; - } - - if (typeof renderer === "function") { - value = renderer.call( - header.scope || this.ownerCt, - value, - // metadata per cell passing an obj by reference so that - // it can be manipulated inside the renderer - metaData, - record, - rowIdx, - colIdx, - store, - view - ); + el = Ext.getDom(el); + for (; i < ln; i++) { + item = it[i]; + itemEl = item.getEl(); + if ((itemEl.dom === el) || itemEl.contains(el)) { + return item; } - - // <debug> - if (metaData.css) { - // This warning attribute is used by the compat layer - obj.cssWarning = true; - metaData.tdCls = metaData.css; - delete metaData.css; - } - // </debug> - - obj[headerId+'-modified'] = record.modified[header.dataIndex] ? Ext.baseCSSPrefix + 'grid-dirty-cell' : Ext.baseCSSPrefix + 'grid-clean-cell'; - obj[headerId+'-tdCls'] = metaData.tdCls; - obj[headerId+'-tdAttr'] = metaData.tdAttr; - obj[headerId+'-style'] = metaData.style; - if (value === undefined || value === null || value === '') { - value = ' '; - } - obj[headerId] = value; - } - return obj; - }, - - expandToFit: function(header) { - if (this.view) { - this.view.expandToFit(header); } + return null; } });