-<!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-panel.Table'>/**
-</span> * @class Ext.panel.Table
- * @extends Ext.panel.Panel
- * @xtype tablepanel
- * @private
- * @author Nicolas Ferrero
- * TablePanel is a private class and the basis of both TreePanel and GridPanel.
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>The source code</title>
+ <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
+ <style type="text/css">
+ .highlight { display: block; background-color: #ddd; }
+ </style>
+ <script type="text/javascript">
+ function highlight() {
+ document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+ }
+ </script>
+</head>
+<body onload="prettyPrint(); highlight();">
+ <pre class="prettyprint lang-js"><span id='Ext-panel-Table'>/**
+</span> * @author Nicolas Ferrero
+ *
+ * TablePanel is the basis of both {@link Ext.tree.Panel TreePanel} and {@link Ext.grid.Panel GridPanel}.
*
* TablePanel aggregates:
*
* - a Store
* - Scrollers
* - Ext.grid.header.Container
- *
*/
Ext.define('Ext.panel.Table', {
extend: 'Ext.panel.Panel',
'Ext.grid.Lockable'
],
- cls: Ext.baseCSSPrefix + 'grid',
+ extraBaseCls: Ext.baseCSSPrefix + 'grid',
extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
layout: 'fit',
-<span id='Ext-panel.Table-property-hasView'> /**
-</span> * Boolean to indicate that a view has been injected into the panel.
- * @property hasView
+<span id='Ext-panel-Table-property-hasView'> /**
+</span> * @property {Boolean} hasView
+ * True to indicate that a view has been injected into the panel.
*/
hasView: false,
// each panel should dictate what viewType and selType to use
+<span id='Ext-panel-Table-cfg-viewType'> /**
+</span> * @cfg {String} viewType
+ * An xtype of view to use. This is automatically set to 'gridview' by {@link Ext.grid.Panel Grid}
+ * and to 'treeview' by {@link Ext.tree.Panel Tree}.
+ */
viewType: null,
+
+<span id='Ext-panel-Table-cfg-viewConfig'> /**
+</span> * @cfg {Object} viewConfig
+ * A config object that will be applied to the grid's UI view. Any of the config options available for
+ * {@link Ext.view.Table} can be specified here. This option is ignored if {@link #view} is specified.
+ */
+
+<span id='Ext-panel-Table-cfg-view'> /**
+</span> * @cfg {Ext.view.Table} view
+ * The {@link Ext.view.Table} used by the grid. Use {@link #viewConfig} to just supply some config options to
+ * view (instead of creating an entire View instance).
+ */
+
+<span id='Ext-panel-Table-cfg-selType'> /**
+</span> * @cfg {String} selType
+ * An xtype of selection model to use. Defaults to 'rowmodel'. This is used to create selection model if just
+ * a config object or nothing at all given in {@link #selModel} config.
+ */
selType: 'rowmodel',
-<span id='Ext-panel.Table-cfg-scrollDelta'> /**
+<span id='Ext-panel-Table-cfg-selModel'> /**
+</span> * @cfg {Ext.selection.Model/Object} selModel
+ * A {@link Ext.selection.Model selection model} instance or config object. In latter case the {@link #selType}
+ * config option determines to which type of selection model this config is applied.
+ */
+
+<span id='Ext-panel-Table-cfg-multiSelect'> /**
+</span> * @cfg {Boolean} multiSelect
+ * True to enable 'MULTI' selection mode on selection model. See {@link Ext.selection.Model#mode}.
+ */
+
+<span id='Ext-panel-Table-cfg-simpleSelect'> /**
+</span> * @cfg {Boolean} simpleSelect
+ * True to enable 'SIMPLE' selection mode on selection model. See {@link Ext.selection.Model#mode}.
+ */
+
+<span id='Ext-panel-Table-cfg-store'> /**
+</span> * @cfg {Ext.data.Store} store (required)
+ * The {@link Ext.data.Store Store} the grid should use as its data source.
+ */
+
+<span id='Ext-panel-Table-cfg-scrollDelta'> /**
</span> * @cfg {Number} scrollDelta
* Number of pixels to scroll when scrolling with mousewheel.
- * Defaults to 40.
*/
scrollDelta: 40,
-<span id='Ext-panel.Table-cfg-scroll'> /**
+<span id='Ext-panel-Table-cfg-scroll'> /**
</span> * @cfg {String/Boolean} scroll
- * Valid values are 'both', 'horizontal' or 'vertical'. true implies 'both'. false implies 'none'.
- * Defaults to true.
+ * Scrollers configuration. Valid values are 'both', 'horizontal' or 'vertical'.
+ * True implies 'both'. False implies 'none'.
*/
scroll: true,
-<span id='Ext-panel.Table-cfg-columns'> /**
-</span> * @cfg {Array} columns
- * An array of {@link Ext.grid.column.Column column} definition objects which define all columns that appear in this grid. Each
- * column definition provides the header text for the column, and a definition of where the data for that column comes from.
+<span id='Ext-panel-Table-cfg-columns'> /**
+</span> * @cfg {Ext.grid.column.Column[]} columns
+ * An array of {@link Ext.grid.column.Column column} definition objects which define all columns that appear in this
+ * grid. Each column definition provides the header text for the column, and a definition of where the data for that
+ * column comes from.
*/
-<span id='Ext-panel.Table-cfg-forceFit'> /**
+<span id='Ext-panel-Table-cfg-forceFit'> /**
</span> * @cfg {Boolean} forceFit
- * Specify as <code>true</code> to force the columns to fit into the available width. Headers are first sized according to configuration, whether that be
- * a specific width, or flex. Then they are all proportionally changed in width so that the entire content width is used..
+ * Ttrue to force the columns to fit into the available width. Headers are first sized according to configuration,
+ * whether that be a specific width, or flex. Then they are all proportionally changed in width so that the entire
+ * content width is used.
+ */
+
+<span id='Ext-panel-Table-cfg-features'> /**
+</span> * @cfg {Ext.grid.feature.Feature[]} features
+ * An array of grid Features to be added to this grid. See {@link Ext.grid.feature.Feature} for usage.
*/
-<span id='Ext-panel.Table-cfg-hideHeaders'> /**
-</span> * @cfg {Boolean} hideHeaders
- * Specify as <code>true</code> to hide the headers.
+<span id='Ext-panel-Table-cfg-hideHeaders'> /**
+</span> * @cfg {Boolean} [hideHeaders=false]
+ * True to hide column headers.
*/
-<span id='Ext-panel.Table-cfg-sortableColumns'> /**
+<span id='Ext-panel-Table-cfg-deferRowRender'> /**
+</span> * @cfg {Boolean} deferRowRender
+ * Defaults to true to enable deferred row rendering.
+ *
+ * This allows the View to execute a refresh quickly, with the expensive update of the row structure deferred so
+ * that layouts with GridPanels appear, and lay out more quickly.
+ */
+
+ deferRowRender: true,
+
+<span id='Ext-panel-Table-cfg-sortableColumns'> /**
</span> * @cfg {Boolean} sortableColumns
- * Defaults to true. Set to false to disable column sorting via clicking the
- * header and via the Sorting menu items.
+ * False to disable column sorting via clicking the header and via the Sorting menu items.
*/
sortableColumns: true,
+<span id='Ext-panel-Table-cfg-enableLocking'> /**
+</span> * @cfg {Boolean} [enableLocking=false]
+ * True to enable locking support for this grid. Alternatively, locking will also be automatically
+ * enabled if any of the columns in the column configuration contain the locked config option.
+ */
+ enableLocking: false,
+
verticalScrollDock: 'right',
verticalScrollerType: 'gridscroller',
scrollerOwner: true,
invalidateScrollerOnRefresh: true,
-
+
+<span id='Ext-panel-Table-cfg-enableColumnMove'> /**
+</span> * @cfg {Boolean} enableColumnMove
+ * False to disable column dragging within this grid.
+ */
enableColumnMove: true,
+
+<span id='Ext-panel-Table-cfg-enableColumnResize'> /**
+</span> * @cfg {Boolean} enableColumnResize
+ * False to disable column resizing within this grid.
+ */
enableColumnResize: true,
+<span id='Ext-panel-Table-cfg-enableColumnHide'> /**
+</span> * @cfg {Boolean} enableColumnHide
+ * False to disable column hiding within this grid.
+ */
+ enableColumnHide: true,
initComponent: function() {
//<debug>
if (!this.viewType) {
Ext.Error.raise("You must specify a viewType config.");
}
- if (!this.store) {
- Ext.Error.raise("You must specify a store config");
- }
if (this.headers) {
Ext.Error.raise("The headers config is not supported. Please specify columns instead.");
}
view,
border = me.border;
- // Set our determinScrollbars method to reference a buffered call to determinScrollbars which fires on a 30ms buffer.
- me.determineScrollbars = Ext.Function.createBuffered(me.determineScrollbars, 30);
- me.injectView = Ext.Function.createBuffered(me.injectView, 30);
-
if (me.hideHeaders) {
border = false;
}
+ // Look up the configured Store. If none configured, use the fieldless, empty Store defined in Ext.data.Store.
+ me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
+
// The columns/colModel config may be either a fully instantiated HeaderContainer, or an array of Column definitions, or a config object of a HeaderContainer
// Either way, we extract a columns property referencing an array of Column definitions.
if (headerCtCfg instanceof Ext.grid.header.Container) {
sortable: me.sortableColumns,
enableColumnMove: me.enableColumnMove,
enableColumnResize: me.enableColumnResize,
+ enableColumnHide: me.enableColumnHide,
border: border
});
me.columns = headerCtCfg.items;
// If any of the Column objects contain a locked property, and are not processed, this is a lockable TablePanel, a
// special view will be injected by the Ext.grid.Lockable mixin, so no processing of .
- if (Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
+ if (me.enableLocking || Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
me.self.mixin('lockable', Ext.grid.Lockable);
me.injectLockable();
}
}
- me.store = Ext.data.StoreManager.lookup(me.store);
me.addEvents(
-<span id='Ext-panel.Table-event-scrollerhide'> /**
+<span id='Ext-panel-Table-event-reconfigure'> /**
+</span> * @event reconfigure
+ * Fires after a reconfigure.
+ * @param {Ext.panel.Table} this
+ */
+ 'reconfigure',
+<span id='Ext-panel-Table-event-viewready'> /**
+</span> * @event viewready
+ * Fires when the grid view is available (use this for selecting a default row).
+ * @param {Ext.panel.Table} this
+ */
+ 'viewready',
+<span id='Ext-panel-Table-event-scrollerhide'> /**
</span> * @event scrollerhide
- * Fires when a scroller is hidden
+ * Fires when a scroller is hidden.
* @param {Ext.grid.Scroller} scroller
* @param {String} orientation Orientation, can be 'vertical' or 'horizontal'
*/
'scrollerhide',
-<span id='Ext-panel.Table-event-scrollershow'> /**
+<span id='Ext-panel-Table-event-scrollershow'> /**
</span> * @event scrollershow
- * Fires when a scroller is shown
+ * Fires when a scroller is shown.
* @param {Ext.grid.Scroller} scroller
* @param {String} orientation Orientation, can be 'vertical' or 'horizontal'
*/
me.bodyCls = me.bodyCls || '';
me.bodyCls += (' ' + me.extraBodyCls);
+
+ me.cls = me.cls || '';
+ me.cls += (' ' + me.extraBaseCls);
// autoScroll is not a valid configuration
delete me.autoScroll;
}
if (vertical) {
- me.verticalScroller = me.verticalScroller || {};
- Ext.applyIf(me.verticalScroller, {
- dock: me.verticalScrollDock,
- xtype: me.verticalScrollerType,
- store: me.store
- });
- me.verticalScroller = Ext.ComponentManager.create(me.verticalScroller);
+ me.verticalScroller = Ext.ComponentManager.create(me.initVerticalScroller());
me.mon(me.verticalScroller, {
bodyscroll: me.onVerticalScroll,
scope: me
}
if (horizontal) {
- me.horizontalScroller = Ext.ComponentManager.create({
- xtype: 'gridscroller',
- section: me,
- dock: 'bottom',
- store: me.store
- });
+ me.horizontalScroller = Ext.ComponentManager.create(me.initHorizontalScroller());
me.mon(me.horizontalScroller, {
bodyscroll: me.onHorizontalScroll,
scope: me
});
}
- me.headerCt.on('columnresize', me.onHeaderResize, me);
- me.relayEvents(me.headerCt, ['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange']);
+ me.headerCt.on('resize', me.onHeaderResize, me);
+ me.relayHeaderCtEvents(me.headerCt);
me.features = me.features || [];
+ if (!Ext.isArray(me.features)) {
+ me.features = [me.features];
+ }
me.dockedItems = me.dockedItems || [];
me.dockedItems.unshift(me.headerCt);
me.viewConfig = me.viewConfig || {};
// getView converts viewConfig into a View instance
view = me.getView();
- if (view) {
- me.mon(view.store, {
- load: me.onStoreLoad,
- scope: me
- });
- me.mon(view, {
- refresh: {
- fn: this.onViewRefresh,
- scope: me,
- buffer: 50
- },
- itemupdate: me.onViewItemUpdate,
- scope: me
- });
- this.relayEvents(view, [
-<span id='Ext-panel.Table-event-beforeitemmousedown'> /**
-</span> * @event beforeitemmousedown
- * Fires before the mousedown event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemmousedown',
-<span id='Ext-panel.Table-event-beforeitemmouseup'> /**
-</span> * @event beforeitemmouseup
- * Fires before the mouseup event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemmouseup',
-<span id='Ext-panel.Table-event-beforeitemmouseenter'> /**
-</span> * @event beforeitemmouseenter
- * Fires before the mouseenter event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemmouseenter',
-<span id='Ext-panel.Table-event-beforeitemmouseleave'> /**
-</span> * @event beforeitemmouseleave
- * Fires before the mouseleave event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemmouseleave',
-<span id='Ext-panel.Table-event-beforeitemclick'> /**
-</span> * @event beforeitemclick
- * Fires before the click event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemclick',
-<span id='Ext-panel.Table-event-beforeitemdblclick'> /**
-</span> * @event beforeitemdblclick
- * Fires before the dblclick event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemdblclick',
-<span id='Ext-panel.Table-event-beforeitemcontextmenu'> /**
-</span> * @event beforeitemcontextmenu
- * Fires before the contextmenu event on an item is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforeitemcontextmenu',
-<span id='Ext-panel.Table-event-itemmousedown'> /**
-</span> * @event itemmousedown
- * Fires when there is a mouse down on an item
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemmousedown',
-<span id='Ext-panel.Table-event-itemmouseup'> /**
-</span> * @event itemmouseup
- * Fires when there is a mouse up on an item
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemmouseup',
-<span id='Ext-panel.Table-event-itemmouseenter'> /**
-</span> * @event itemmouseenter
- * Fires when the mouse enters an item.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemmouseenter',
-<span id='Ext-panel.Table-event-itemmouseleave'> /**
-</span> * @event itemmouseleave
- * Fires when the mouse leaves an item.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemmouseleave',
-<span id='Ext-panel.Table-event-itemclick'> /**
-</span> * @event itemclick
- * Fires when an item is clicked.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemclick',
-<span id='Ext-panel.Table-event-itemdblclick'> /**
-</span> * @event itemdblclick
- * Fires when an item is double clicked.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemdblclick',
-<span id='Ext-panel.Table-event-itemcontextmenu'> /**
-</span> * @event itemcontextmenu
- * Fires when an item is right clicked.
- * @param {Ext.view.View} this
- * @param {Ext.data.Model} record The record that belongs to the item
- * @param {HTMLElement} item The item's element
- * @param {Number} index The item's index
- * @param {Ext.EventObject} e The raw event object
- */
- 'itemcontextmenu',
-<span id='Ext-panel.Table-event-beforecontainermousedown'> /**
-</span> * @event beforecontainermousedown
- * Fires before the mousedown event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainermousedown',
-<span id='Ext-panel.Table-event-beforecontainermouseup'> /**
-</span> * @event beforecontainermouseup
- * Fires before the mouseup event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainermouseup',
-<span id='Ext-panel.Table-event-beforecontainermouseover'> /**
-</span> * @event beforecontainermouseover
- * Fires before the mouseover event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainermouseover',
-<span id='Ext-panel.Table-event-beforecontainermouseout'> /**
-</span> * @event beforecontainermouseout
- * Fires before the mouseout event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainermouseout',
-<span id='Ext-panel.Table-event-beforecontainerclick'> /**
-</span> * @event beforecontainerclick
- * Fires before the click event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainerclick',
-<span id='Ext-panel.Table-event-beforecontainerdblclick'> /**
-</span> * @event beforecontainerdblclick
- * Fires before the dblclick event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainerdblclick',
-<span id='Ext-panel.Table-event-beforecontainercontextmenu'> /**
-</span> * @event beforecontainercontextmenu
- * Fires before the contextmenu event on the container is processed. Returns false to cancel the default action.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'beforecontainercontextmenu',
-<span id='Ext-panel.Table-event-containermouseup'> /**
-</span> * @event containermouseup
- * Fires when there is a mouse up on the container
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'containermouseup',
-<span id='Ext-panel.Table-event-containermouseover'> /**
-</span> * @event containermouseover
- * Fires when you move the mouse over the container.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'containermouseover',
-<span id='Ext-panel.Table-event-containermouseout'> /**
-</span> * @event containermouseout
- * Fires when you move the mouse out of the container.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'containermouseout',
-<span id='Ext-panel.Table-event-containerclick'> /**
-</span> * @event containerclick
- * Fires when the container is clicked.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'containerclick',
-<span id='Ext-panel.Table-event-containerdblclick'> /**
-</span> * @event containerdblclick
- * Fires when the container is double clicked.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'containerdblclick',
-<span id='Ext-panel.Table-event-containercontextmenu'> /**
-</span> * @event containercontextmenu
- * Fires when the container is right clicked.
- * @param {Ext.view.View} this
- * @param {Ext.EventObject} e The raw event object
- */
- 'containercontextmenu',
-
-<span id='Ext-panel.Table-event-selectionchange'> /**
-</span> * @event selectionchange
- * Fires when the selected nodes change. Relayed event from the underlying selection model.
- * @param {Ext.view.View} this
- * @param {Array} selections Array of the selected nodes
- */
- 'selectionchange',
-<span id='Ext-panel.Table-event-beforeselect'> /**
-</span> * @event beforeselect
- * Fires before a selection is made. If any handlers return false, the selection is cancelled.
- * @param {Ext.view.View} this
- * @param {HTMLElement} node The node to be selected
- * @param {Array} selections Array of currently selected nodes
- */
- 'beforeselect'
- ]);
- }
+ view.on({
+ afterrender: function () {
+ // hijack the view el's scroll method
+ view.el.scroll = Ext.Function.bind(me.elScroll, me);
+ // We use to listen to document.body wheel events, but that's a
+ // little much. We scope just to the view now.
+ me.mon(view.el, {
+ mousewheel: me.onMouseWheel,
+ scope: me
+ });
+ },
+ single: true
+ });
+ me.items = [view];
+ me.hasView = true;
+
+ me.mon(view.store, {
+ load: me.onStoreLoad,
+ scope: me
+ });
+ me.mon(view, {
+ viewReady: me.onViewReady,
+ resize: me.onViewResize,
+ refresh: {
+ fn: me.onViewRefresh,
+ scope: me,
+ buffer: 50
+ },
+ scope: me
+ });
+ this.relayEvents(view, [
+<span id='Ext-panel-Table-event-beforeitemmousedown'> /**
+</span> * @event beforeitemmousedown
+ * @alias Ext.view.View#beforeitemmousedown
+ */
+ 'beforeitemmousedown',
+<span id='Ext-panel-Table-event-beforeitemmouseup'> /**
+</span> * @event beforeitemmouseup
+ * @alias Ext.view.View#beforeitemmouseup
+ */
+ 'beforeitemmouseup',
+<span id='Ext-panel-Table-event-beforeitemmouseenter'> /**
+</span> * @event beforeitemmouseenter
+ * @alias Ext.view.View#beforeitemmouseenter
+ */
+ 'beforeitemmouseenter',
+<span id='Ext-panel-Table-event-beforeitemmouseleave'> /**
+</span> * @event beforeitemmouseleave
+ * @alias Ext.view.View#beforeitemmouseleave
+ */
+ 'beforeitemmouseleave',
+<span id='Ext-panel-Table-event-beforeitemclick'> /**
+</span> * @event beforeitemclick
+ * @alias Ext.view.View#beforeitemclick
+ */
+ 'beforeitemclick',
+<span id='Ext-panel-Table-event-beforeitemdblclick'> /**
+</span> * @event beforeitemdblclick
+ * @alias Ext.view.View#beforeitemdblclick
+ */
+ 'beforeitemdblclick',
+<span id='Ext-panel-Table-event-beforeitemcontextmenu'> /**
+</span> * @event beforeitemcontextmenu
+ * @alias Ext.view.View#beforeitemcontextmenu
+ */
+ 'beforeitemcontextmenu',
+<span id='Ext-panel-Table-event-itemmousedown'> /**
+</span> * @event itemmousedown
+ * @alias Ext.view.View#itemmousedown
+ */
+ 'itemmousedown',
+<span id='Ext-panel-Table-event-itemmouseup'> /**
+</span> * @event itemmouseup
+ * @alias Ext.view.View#itemmouseup
+ */
+ 'itemmouseup',
+<span id='Ext-panel-Table-event-itemmouseenter'> /**
+</span> * @event itemmouseenter
+ * @alias Ext.view.View#itemmouseenter
+ */
+ 'itemmouseenter',
+<span id='Ext-panel-Table-event-itemmouseleave'> /**
+</span> * @event itemmouseleave
+ * @alias Ext.view.View#itemmouseleave
+ */
+ 'itemmouseleave',
+<span id='Ext-panel-Table-event-itemclick'> /**
+</span> * @event itemclick
+ * @alias Ext.view.View#itemclick
+ */
+ 'itemclick',
+<span id='Ext-panel-Table-event-itemdblclick'> /**
+</span> * @event itemdblclick
+ * @alias Ext.view.View#itemdblclick
+ */
+ 'itemdblclick',
+<span id='Ext-panel-Table-event-itemcontextmenu'> /**
+</span> * @event itemcontextmenu
+ * @alias Ext.view.View#itemcontextmenu
+ */
+ 'itemcontextmenu',
+<span id='Ext-panel-Table-event-beforecontainermousedown'> /**
+</span> * @event beforecontainermousedown
+ * @alias Ext.view.View#beforecontainermousedown
+ */
+ 'beforecontainermousedown',
+<span id='Ext-panel-Table-event-beforecontainermouseup'> /**
+</span> * @event beforecontainermouseup
+ * @alias Ext.view.View#beforecontainermouseup
+ */
+ 'beforecontainermouseup',
+<span id='Ext-panel-Table-event-beforecontainermouseover'> /**
+</span> * @event beforecontainermouseover
+ * @alias Ext.view.View#beforecontainermouseover
+ */
+ 'beforecontainermouseover',
+<span id='Ext-panel-Table-event-beforecontainermouseout'> /**
+</span> * @event beforecontainermouseout
+ * @alias Ext.view.View#beforecontainermouseout
+ */
+ 'beforecontainermouseout',
+<span id='Ext-panel-Table-event-beforecontainerclick'> /**
+</span> * @event beforecontainerclick
+ * @alias Ext.view.View#beforecontainerclick
+ */
+ 'beforecontainerclick',
+<span id='Ext-panel-Table-event-beforecontainerdblclick'> /**
+</span> * @event beforecontainerdblclick
+ * @alias Ext.view.View#beforecontainerdblclick
+ */
+ 'beforecontainerdblclick',
+<span id='Ext-panel-Table-event-beforecontainercontextmenu'> /**
+</span> * @event beforecontainercontextmenu
+ * @alias Ext.view.View#beforecontainercontextmenu
+ */
+ 'beforecontainercontextmenu',
+<span id='Ext-panel-Table-event-containermouseup'> /**
+</span> * @event containermouseup
+ * @alias Ext.view.View#containermouseup
+ */
+ 'containermouseup',
+<span id='Ext-panel-Table-event-containermouseover'> /**
+</span> * @event containermouseover
+ * @alias Ext.view.View#containermouseover
+ */
+ 'containermouseover',
+<span id='Ext-panel-Table-event-containermouseout'> /**
+</span> * @event containermouseout
+ * @alias Ext.view.View#containermouseout
+ */
+ 'containermouseout',
+<span id='Ext-panel-Table-event-containerclick'> /**
+</span> * @event containerclick
+ * @alias Ext.view.View#containerclick
+ */
+ 'containerclick',
+<span id='Ext-panel-Table-event-containerdblclick'> /**
+</span> * @event containerdblclick
+ * @alias Ext.view.View#containerdblclick
+ */
+ 'containerdblclick',
+<span id='Ext-panel-Table-event-containercontextmenu'> /**
+</span> * @event containercontextmenu
+ * @alias Ext.view.View#containercontextmenu
+ */
+ 'containercontextmenu',
+<span id='Ext-panel-Table-event-selectionchange'> /**
+</span> * @event selectionchange
+ * @alias Ext.selection.Model#selectionchange
+ */
+ 'selectionchange',
+<span id='Ext-panel-Table-event-beforeselect'> /**
+</span> * @event beforeselect
+ * @alias Ext.selection.RowModel#beforeselect
+ */
+ 'beforeselect',
+<span id='Ext-panel-Table-event-select'> /**
+</span> * @event select
+ * @alias Ext.selection.RowModel#select
+ */
+ 'select',
+<span id='Ext-panel-Table-event-beforedeselect'> /**
+</span> * @event beforedeselect
+ * @alias Ext.selection.RowModel#beforedeselect
+ */
+ 'beforedeselect',
+<span id='Ext-panel-Table-event-deselect'> /**
+</span> * @event deselect
+ * @alias Ext.selection.RowModel#deselect
+ */
+ 'deselect'
+ ]);
}
+
me.callParent(arguments);
},
+
+ onRender: function(){
+ var vScroll = this.verticalScroller,
+ hScroll = this.horizontalScroller;
+
+ if (vScroll) {
+ vScroll.ensureDimension();
+ }
+ if (hScroll) {
+ hScroll.ensureDimension();
+ }
+ this.callParent(arguments);
+ },
// state management
initStateEvents: function(){
this.callParent();
},
- getState: function(){
- var state = {
- columns: []
- },
- sorter = this.store.sorters.first();
-
- this.headerCt.items.each(function(header){
- state.columns.push({
- id: header.headerId,
- width: header.flex ? undefined : header.width,
- hidden: header.hidden,
- sortable: header.sortable
- });
+<span id='Ext-panel-Table-method-initHorizontalScroller'> /**
+</span> * Returns the horizontal scroller config.
+ */
+ initHorizontalScroller: function () {
+ var me = this,
+ ret = {
+ xtype: 'gridscroller',
+ dock: 'bottom',
+ section: me,
+ store: me.store
+ };
+
+ return ret;
+ },
+
+<span id='Ext-panel-Table-method-initVerticalScroller'> /**
+</span> * Returns the vertical scroller config.
+ */
+ initVerticalScroller: function () {
+ var me = this,
+ ret = me.verticalScroller || {};
+
+ Ext.applyIf(ret, {
+ xtype: me.verticalScrollerType,
+ dock: me.verticalScrollDock,
+ store: me.store
});
+ return ret;
+ },
+
+ relayHeaderCtEvents: function (headerCt) {
+ this.relayEvents(headerCt, [
+<span id='Ext-panel-Table-event-columnresize'> /**
+</span> * @event columnresize
+ * @alias Ext.grid.header.Container#columnresize
+ */
+ 'columnresize',
+<span id='Ext-panel-Table-event-columnmove'> /**
+</span> * @event columnmove
+ * @alias Ext.grid.header.Container#columnmove
+ */
+ 'columnmove',
+<span id='Ext-panel-Table-event-columnhide'> /**
+</span> * @event columnhide
+ * @alias Ext.grid.header.Container#columnhide
+ */
+ 'columnhide',
+<span id='Ext-panel-Table-event-columnshow'> /**
+</span> * @event columnshow
+ * @alias Ext.grid.header.Container#columnshow
+ */
+ 'columnshow',
+<span id='Ext-panel-Table-event-sortchange'> /**
+</span> * @event sortchange
+ * @alias Ext.grid.header.Container#sortchange
+ */
+ 'sortchange'
+ ]);
+ },
+
+ getState: function(){
+ var me = this,
+ state = me.callParent(),
+ sorter = me.store.sorters.first();
+
+ state.columns = (me.headerCt || me).getColumnsState();
+
if (sorter) {
state.sort = {
property: sorter.property,
direction: sorter.direction
};
}
+
return state;
},
applyState: function(state) {
- var headers = state.columns,
- length = headers ? headers.length : 0,
- headerCt = this.headerCt,
- items = headerCt.items,
+ var me = this,
sorter = state.sort,
- store = this.store,
- i = 0,
- index,
- headerState,
- header;
+ store = me.store,
+ columns = state.columns;
- for (; i < length; ++i) {
- headerState = headers[i];
- header = headerCt.down('gridcolumn[headerId=' + headerState.id + ']');
- index = items.indexOf(header);
- if (i !== index) {
- headerCt.moveHeader(index, i);
- }
- header.sortable = headerState.sortable;
- if (Ext.isDefined(headerState.width)) {
- delete header.flex;
- if (header.rendered) {
- header.setWidth(headerState.width);
- } else {
- header.minWidth = header.width = headerState.width;
- }
- }
- header.hidden = headerState.hidden;
+ delete state.columns;
+
+ // Ensure superclass has applied *its* state.
+ // AbstractComponent saves dimensions (and anchor/flex) plus collapsed state.
+ me.callParent(arguments);
+
+ if (columns) {
+ (me.headerCt || me).applyColumnsState(columns);
}
if (sorter) {
}
},
-<span id='Ext-panel.Table-method-getStore'> /**
+<span id='Ext-panel-Table-method-getStore'> /**
</span> * Returns the store associated with this Panel.
* @return {Ext.data.Store} The store
*/
return this.store;
},
-<span id='Ext-panel.Table-method-getView'> /**
+<span id='Ext-panel-Table-method-getView'> /**
</span> * Gets the view for this panel.
* @return {Ext.view.Table}
*/
if (!me.view) {
sm = me.getSelectionModel();
me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
+ deferInitialRefresh: me.deferRowRender,
xtype: me.viewType,
store: me.store,
headerCt: me.headerCt,
return me.view;
},
-<span id='Ext-panel.Table-property-setAutoScroll'> /**
+<span id='Ext-panel-Table-property-setAutoScroll'> /**
</span> * @private
* @override
* autoScroll is never valid for all classes which extend TablePanel.
if (direction === "up" || direction === "left") {
distance = -distance;
}
-
+
if (direction === "down" || direction === "up") {
scroller = me.getVerticalScroller();
- scroller.scrollByDeltaY(distance);
+
+ //if the grid does not currently need a vertical scroller don't try to update it (EXTJSIV-3891)
+ if (scroller) {
+ scroller.scrollByDeltaY(distance);
+ }
} else {
scroller = me.getHorizontalScroller();
- scroller.scrollByDeltaX(distance);
- }
- },
-
- afterLayout: function() {
- this.callParent(arguments);
- this.injectView();
- },
-
-
-<span id='Ext-panel.Table-method-injectView'> /**
-</span> * @private
- * Called after this Component has achieved its correct initial size, after all layouts have done their thing.
- * This is so we can add the View only after the initial size is known. This method is buffered 30ms.
- */
- injectView: function() {
- if (!this.hasView && !this.collapsed) {
- var me = this,
- view = me.getView();
-
- me.hasView = true;
- me.add(view);
-
- // hijack the view el's scroll method
- view.el.scroll = Ext.Function.bind(me.elScroll, me);
- // We use to listen to document.body wheel events, but that's a
- // little much. We scope just to the view now.
- me.mon(view.el, {
- mousewheel: me.onMouseWheel,
- scope: me
- });
- }
- },
-
- afterExpand: function() {
- this.callParent(arguments);
- if (!this.hasView) {
- this.injectView();
+
+ //if the grid does not currently need a horizontal scroller don't try to update it (EXTJSIV-3891)
+ if (scroller) {
+ scroller.scrollByDeltaX(distance);
+ }
}
},
-<span id='Ext-panel.Table-method-processEvent'> /**
+<span id='Ext-panel-Table-method-processEvent'> /**
</span> * @private
- * Process UI events from the view. Propagate them to whatever internal Components need to process them
+ * Processes UI events from the view. Propagates them to whatever internal Components need to process them.
* @param {String} type Event type, eg 'click'
- * @param {TableView} view TableView Component
- * @param {HtmlElement} cell Cell HtmlElement the event took place within
+ * @param {Ext.view.Table} view TableView Component
+ * @param {HTMLElement} cell Cell HtmlElement the event took place within
* @param {Number} recordIndex Index of the associated Store Model (-1 if none)
* @param {Number} cellIndex Cell index within the row
- * @param {EventObject} e Original event
+ * @param {Ext.EventObject} e Original event
*/
processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
var me = this,
}
},
-<span id='Ext-panel.Table-method-determineScrollbars'> /**
-</span> * Request a recalculation of scrollbars and put them in if they are needed.
+<span id='Ext-panel-Table-method-determineScrollbars'> /**
+</span> * Requests a recalculation of scrollbars and puts them in if they are needed.
*/
determineScrollbars: function() {
+ // Set a flag so that afterComponentLayout does not recurse back into here.
+ if (this.determineScrollbarsRunning) {
+ return;
+ }
+ this.determineScrollbarsRunning = true;
var me = this,
- viewElDom,
- centerScrollWidth,
- centerClientWidth,
+ view = me.view,
+ box,
+ tableEl,
+ scrollWidth,
+ clientWidth,
scrollHeight,
- clientHeight;
-
- if (!me.collapsed && me.view && me.view.el) {
- viewElDom = me.view.el.dom;
- //centerScrollWidth = viewElDom.scrollWidth;
- centerScrollWidth = me.headerCt.getFullWidth();
-<span id='Ext-panel.Table-property-centerClientWidth'> /**
-</span> * clientWidth often returns 0 in IE resulting in an
- * infinity result, here we use offsetWidth bc there are
- * no possible scrollbars and we don't care about margins
- */
- centerClientWidth = viewElDom.offsetWidth;
- if (me.verticalScroller && me.verticalScroller.el) {
- scrollHeight = me.verticalScroller.getSizeCalculation().height;
+ clientHeight,
+ verticalScroller = me.verticalScroller,
+ horizontalScroller = me.horizontalScroller,
+ curScrollbars = (verticalScroller && verticalScroller.ownerCt === me ? 1 : 0) |
+ (horizontalScroller && horizontalScroller.ownerCt === me ? 2 : 0),
+ reqScrollbars = 0; // 1 = vertical, 2 = horizontal, 3 = both
+
+ // If we are not collapsed, and the view has been rendered AND filled, then we can determine scrollbars
+ if (!me.collapsed && view && view.viewReady) {
+
+ // Calculate maximum, *scrollbarless* space which the view has available.
+ // It will be the Fit Layout's calculated size, plus the widths of any currently shown scrollbars
+ box = view.el.getSize();
+
+ clientWidth = box.width + ((curScrollbars & 1) ? verticalScroller.width : 0);
+ clientHeight = box.height + ((curScrollbars & 2) ? horizontalScroller.height : 0);
+
+ // Calculate the width of the scrolling block
+ // There will never be a horizontal scrollbar if all columns are flexed.
+
+ scrollWidth = (me.headerCt.query('[flex]').length && !me.headerCt.layout.tooNarrow) ? 0 : me.headerCt.getFullWidth();
+
+ // Calculate the height of the scrolling block
+ if (verticalScroller && verticalScroller.el) {
+ scrollHeight = verticalScroller.getSizeCalculation().height;
} else {
- scrollHeight = viewElDom.scrollHeight;
+ tableEl = view.el.child('table', true);
+ scrollHeight = tableEl ? tableEl.offsetHeight : 0;
}
- clientHeight = viewElDom.clientHeight;
+ // View is too high.
+ // Definitely need a vertical scrollbar
+ if (scrollHeight > clientHeight) {
+ reqScrollbars = 1;
- if (!me.collapsed && scrollHeight > clientHeight) {
- me.showVerticalScroller();
- } else {
- me.hideVerticalScroller();
+ // But if scrollable block width goes into the zone required by the vertical scrollbar, we'll also need a horizontal
+ if (horizontalScroller && ((clientWidth - scrollWidth) < verticalScroller.width)) {
+ reqScrollbars = 3;
+ }
}
- if (!me.collapsed && centerScrollWidth > (centerClientWidth + Ext.getScrollBarWidth() - 2)) {
- me.showHorizontalScroller();
- } else {
- me.hideHorizontalScroller();
+ // View height fits. But we stil may need a horizontal scrollbar, and this might necessitate a vertical one.
+ else {
+ // View is too wide.
+ // Definitely need a horizontal scrollbar
+ if (scrollWidth > clientWidth) {
+ reqScrollbars = 2;
+
+ // But if scrollable block height goes into the zone required by the horizontal scrollbar, we'll also need a vertical
+ if (verticalScroller && ((clientHeight - scrollHeight) < horizontalScroller.height)) {
+ reqScrollbars = 3;
+ }
+ }
+ }
+
+ // If scrollbar requirements have changed, change 'em...
+ if (reqScrollbars !== curScrollbars) {
+
+ // Suspend component layout while we add/remove the docked scrollers
+ me.suspendLayout = true;
+ if (reqScrollbars & 1) {
+ me.showVerticalScroller();
+ } else {
+ me.hideVerticalScroller();
+ }
+ if (reqScrollbars & 2) {
+ me.showHorizontalScroller();
+ } else {
+ me.hideHorizontalScroller();
+ }
+ me.suspendLayout = false;
+
+ // Lay out the Component.
+ me.doComponentLayout();
+ // Lay out me.items
+ me.getLayout().layout();
}
}
+ delete me.determineScrollbarsRunning;
+ },
+
+ onViewResize: function() {
+ this.determineScrollbars();
+ },
+
+ afterComponentLayout: function() {
+ this.callParent(arguments);
+ this.determineScrollbars();
+ this.invalidateScroller();
},
onHeaderResize: function() {
- if (this.view && this.view.rendered) {
+ if (!this.componentLayout.layoutBusy && this.view && this.view.rendered) {
this.determineScrollbars();
this.invalidateScroller();
}
},
-<span id='Ext-panel.Table-method-hideHorizontalScroller'> /**
-</span> * Hide the verticalScroller and remove the horizontalScrollerPresentCls.
+ afterCollapse: function() {
+ var me = this;
+ if (me.verticalScroller) {
+ me.verticalScroller.saveScrollPos();
+ }
+ if (me.horizontalScroller) {
+ me.horizontalScroller.saveScrollPos();
+ }
+ me.callParent(arguments);
+ },
+
+ afterExpand: function() {
+ var me = this;
+ me.callParent(arguments);
+ if (me.verticalScroller) {
+ me.verticalScroller.restoreScrollPos();
+ }
+ if (me.horizontalScroller) {
+ me.horizontalScroller.restoreScrollPos();
+ }
+ },
+
+<span id='Ext-panel-Table-method-hideHorizontalScroller'> /**
+</span> * Hides the verticalScroller and removes the horizontalScrollerPresentCls.
*/
hideHorizontalScroller: function() {
var me = this;
if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
- me.verticalScroller.offsets.bottom = 0;
+ me.verticalScroller.setReservedSpace(0);
me.removeDocked(me.horizontalScroller, false);
me.removeCls(me.horizontalScrollerPresentCls);
me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
},
-<span id='Ext-panel.Table-method-showHorizontalScroller'> /**
-</span> * Show the horizontalScroller and add the horizontalScrollerPresentCls.
+<span id='Ext-panel-Table-method-showHorizontalScroller'> /**
+</span> * Shows the horizontalScroller and add the horizontalScrollerPresentCls.
*/
showHorizontalScroller: function() {
var me = this;
if (me.verticalScroller) {
- me.verticalScroller.offsets.bottom = Ext.getScrollBarWidth() - 2;
+ me.verticalScroller.setReservedSpace(Ext.getScrollbarSize().height - 1);
}
if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
me.addDocked(me.horizontalScroller);
}
},
-<span id='Ext-panel.Table-method-hideVerticalScroller'> /**
-</span> * Hide the verticalScroller and remove the verticalScrollerPresentCls.
+<span id='Ext-panel-Table-method-hideVerticalScroller'> /**
+</span> * Hides the verticalScroller and removes the verticalScrollerPresentCls.
*/
hideVerticalScroller: function() {
- var me = this,
- headerCt = me.headerCt;
+ var me = this;
- // only trigger a layout when reserveOffset is changing
- if (headerCt && headerCt.layout.reserveOffset) {
- headerCt.layout.reserveOffset = false;
- headerCt.doLayout();
- }
+ me.setHeaderReserveOffset(false);
if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
me.removeDocked(me.verticalScroller, false);
me.removeCls(me.verticalScrollerPresentCls);
}
},
-<span id='Ext-panel.Table-method-showVerticalScroller'> /**
-</span> * Show the verticalScroller and add the verticalScrollerPresentCls.
+<span id='Ext-panel-Table-method-showVerticalScroller'> /**
+</span> * Shows the verticalScroller and adds the verticalScrollerPresentCls.
*/
showVerticalScroller: function() {
- var me = this,
- headerCt = me.headerCt;
+ var me = this;
- // only trigger a layout when reserveOffset is changing
- if (headerCt && !headerCt.layout.reserveOffset) {
- headerCt.layout.reserveOffset = true;
- headerCt.doLayout();
- }
+ me.setHeaderReserveOffset(true);
if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
me.addDocked(me.verticalScroller);
me.addCls(me.verticalScrollerPresentCls);
}
},
-<span id='Ext-panel.Table-method-invalidateScroller'> /**
-</span> * Invalides scrollers that are present and forces a recalculation.
- * (Not related to showing/hiding the scrollers)
+ setHeaderReserveOffset: function (reserveOffset) {
+ var headerCt = this.headerCt,
+ layout = headerCt.layout;
+
+ // only trigger a layout when reserveOffset is changing
+ if (layout && layout.reserveOffset !== reserveOffset) {
+ layout.reserveOffset = reserveOffset;
+ if (!this.suspendLayout) {
+ headerCt.doLayout();
+ }
+ }
+ },
+
+<span id='Ext-panel-Table-method-invalidateScroller'> /**
+</span> * Invalides scrollers that are present and forces a recalculation. (Not related to showing/hiding the scrollers)
*/
invalidateScroller: function() {
var me = this,
onMouseWheel: function(e) {
var me = this,
- browserEvent = e.browserEvent,
vertScroller = me.getVerticalScroller(),
horizScroller = me.getHorizontalScroller(),
- scrollDelta = me.scrollDelta,
- deltaY, deltaX,
+ scrollDelta = -me.scrollDelta,
+ deltas = e.getWheelDeltas(),
+ deltaX = scrollDelta * deltas.x,
+ deltaY = scrollDelta * deltas.y,
vertScrollerEl, horizScrollerEl,
- origScrollLeft, origScrollTop,
- newScrollLeft, newScrollTop;
+ vertScrollerElDom, horizScrollerElDom,
+ horizontalCanScrollLeft, horizontalCanScrollRight,
+ verticalCanScrollDown, verticalCanScrollUp;
- // Track original scroll values, so we can see if we've
- // reached the end of our scroll height/width.
+ // calculate whether or not both scrollbars can scroll right/left and up/down
if (horizScroller) {
- horizScrollerEl = horizScroller.el;
+ horizScrollerEl = horizScroller.scrollEl;
if (horizScrollerEl) {
- origScrollLeft = horizScrollerEl.dom.scrollLeft;
+ horizScrollerElDom = horizScrollerEl.dom;
+ horizontalCanScrollRight = horizScrollerElDom.scrollLeft !== horizScrollerElDom.scrollWidth - horizScrollerElDom.clientWidth;
+ horizontalCanScrollLeft = horizScrollerElDom.scrollLeft !== 0;
}
}
if (vertScroller) {
- vertScrollerEl = vertScroller.el;
+ vertScrollerEl = vertScroller.scrollEl;
if (vertScrollerEl) {
- origScrollTop = vertScrollerEl.dom.scrollTop;
+ vertScrollerElDom = vertScrollerEl.dom;
+ verticalCanScrollDown = vertScrollerElDom.scrollTop !== vertScrollerElDom.scrollHeight - vertScrollerElDom.clientHeight;
+ verticalCanScrollUp = vertScrollerElDom.scrollTop !== 0;
}
}
- // Webkit Horizontal Axis
- if (browserEvent.wheelDeltaX || browserEvent.wheelDeltaY) {
- deltaX = -browserEvent.wheelDeltaX / 120 * scrollDelta / 3;
- deltaY = -browserEvent.wheelDeltaY / 120 * scrollDelta / 3;
- if (horizScroller) {
- newScrollLeft = horizScroller.scrollByDeltaX(deltaX);
- }
- if (vertScroller) {
- newScrollTop = vertScroller.scrollByDeltaY(deltaY);
- }
- } else {
- // Gecko Horizontal Axis
- if (browserEvent.axis && browserEvent.axis === 1) {
- if (horizScroller) {
- deltaX = -(scrollDelta * e.getWheelDelta()) / 3;
- newScrollLeft = horizScroller.scrollByDeltaX(deltaX);
- }
- } else {
- if (vertScroller) {
-
- deltaY = -(scrollDelta * e.getWheelDelta() / 3);
- newScrollTop = vertScroller.scrollByDeltaY(deltaY);
- }
+ if (horizScroller) {
+ if ((deltaX < 0 && horizontalCanScrollLeft) || (deltaX > 0 && horizontalCanScrollRight)) {
+ e.stopEvent();
+ horizScroller.scrollByDeltaX(deltaX);
}
}
-
- // If after given our delta, the scroller has not progressed, then we're
- // at the end of our scroll range and shouldn't stop the browser event.
- if ((deltaX !== 0 && newScrollLeft !== origScrollLeft) ||
- (deltaY !== 0 && newScrollTop !== origScrollTop)) {
- e.stopEvent();
+ if (vertScroller) {
+ if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
+ e.stopEvent();
+ vertScroller.scrollByDeltaY(deltaY);
+ }
}
},
-<span id='Ext-panel.Table-method-onViewRefresh'> /**
+<span id='Ext-panel-Table-method-onViewReady'> /**
</span> * @private
- * Determine and invalidate scrollers on view refresh
+ * Fires the TablePanel's viewready event when the view declares that its internal DOM is ready
*/
- onViewRefresh: function() {
- if (Ext.isIE) {
- this.syncCellHeight();
- }
- this.determineScrollbars();
- if (this.invalidateScrollerOnRefresh) {
- this.invalidateScroller();
- }
- },
-
- onViewItemUpdate: function(record, index, tr) {
- if (Ext.isIE) {
- this.syncCellHeight([tr]);
+ onViewReady: function() {
+ var me = this;
+ me.fireEvent('viewready', me);
+ if (me.deferRowRender) {
+ me.determineScrollbars();
+ me.invalidateScroller();
}
},
- // BrowserBug: IE will not stretch the td to fit the height of the entire
- // tr, so manually sync cellheights on refresh and when an item has been
- // updated.
- syncCellHeight: function(trs) {
- var me = this,
- i = 0,
- tds,
- j, tdsLn,
- tr, td,
- trsLn,
- rowHeights = [],
- cellHeights,
- cellClsSelector = ('.' + Ext.baseCSSPrefix + 'grid-cell');
-
- trs = trs || me.view.getNodes();
-
- trsLn = trs.length;
- // Reading loop
- for (; i < trsLn; i++) {
- tr = trs[i];
- tds = Ext.fly(tr).query(cellClsSelector);
- tdsLn = tds.length;
- cellHeights = [];
- for (j = 0; j < tdsLn; j++) {
- td = tds[j];
- cellHeights.push(td.clientHeight);
- }
- rowHeights.push(Ext.Array.max(cellHeights));
- }
+<span id='Ext-panel-Table-method-onViewRefresh'> /**
+</span> * @private
+ * Determines and invalidates scrollers on view refresh
+ */
+ onViewRefresh: function() {
+ var me = this;
- // Setting loop
- for (i = 0; i < trsLn; i++) {
- tr = trs[i];
- tdsLn = tr.childNodes.length;
- for (j = 0; j < tdsLn; j++) {
- td = Ext.fly(tr.childNodes[j]);
- if (rowHeights[i]) {
- if (td.is(cellClsSelector)) {
- td.setHeight(rowHeights[i]);
- } else {
- td.down(cellClsSelector).setHeight(rowHeights[i]);
- }
- }
-
+ // Refresh *during* render must be ignored.
+ if (!me.rendering) {
+ this.determineScrollbars();
+ if (this.invalidateScrollerOnRefresh) {
+ this.invalidateScroller();
}
}
},
-<span id='Ext-panel.Table-method-setScrollTop'> /**
+<span id='Ext-panel-Table-method-setScrollTop'> /**
</span> * Sets the scrollTop of the TablePanel.
- * @param {Number} deltaY
+ * @param {Number} top
*/
setScrollTop: function(top) {
var me = this,
if (verticalScroller) {
verticalScroller.setScrollTop(top);
}
-
},
getScrollerOwner: function() {
return rootCmp;
},
-<span id='Ext-panel.Table-method-scrollByDeltaY'> /**
+<span id='Ext-panel-Table-method-scrollByDeltaY'> /**
</span> * Scrolls the TablePanel by deltaY
* @param {Number} deltaY
*/
scrollByDeltaY: function(deltaY) {
- var rootCmp = this.getScrollerOwner(),
- scrollerRight;
- scrollerRight = rootCmp.down('gridscroller[dock=' + this.verticalScrollDock + ']');
- if (scrollerRight) {
- scrollerRight.scrollByDeltaY(deltaY);
+ var verticalScroller = this.getVerticalScroller();
+
+ if (verticalScroller) {
+ verticalScroller.scrollByDeltaY(deltaY);
}
},
-
-<span id='Ext-panel.Table-method-scrollByDeltaX'> /**
+<span id='Ext-panel-Table-method-scrollByDeltaX'> /**
</span> * Scrolls the TablePanel by deltaX
- * @param {Number} deltaY
+ * @param {Number} deltaX
*/
scrollByDeltaX: function(deltaX) {
- this.horizontalScroller.scrollByDeltaX(deltaX);
+ var horizontalScroller = this.getHorizontalScroller();
+
+ if (horizontalScroller) {
+ horizontalScroller.scrollByDeltaX(deltaX);
+ }
},
-<span id='Ext-panel.Table-method-getLhsMarker'> /**
-</span> * Get left hand side marker for header resizing.
+<span id='Ext-panel-Table-method-getLhsMarker'> /**
+</span> * Gets left hand side marker for header resizing.
* @private
*/
getLhsMarker: function() {
var me = this;
if (!me.lhsMarker) {
- me.lhsMarker = Ext.core.DomHelper.append(me.el, {
+ me.lhsMarker = Ext.DomHelper.append(me.el, {
cls: Ext.baseCSSPrefix + 'grid-resize-marker'
}, true);
}
return me.lhsMarker;
},
-<span id='Ext-panel.Table-method-getRhsMarker'> /**
-</span> * Get right hand side marker for header resizing.
+<span id='Ext-panel-Table-method-getRhsMarker'> /**
+</span> * Gets right hand side marker for header resizing.
* @private
*/
getRhsMarker: function() {
var me = this;
if (!me.rhsMarker) {
- me.rhsMarker = Ext.core.DomHelper.append(me.el, {
+ me.rhsMarker = Ext.DomHelper.append(me.el, {
cls: Ext.baseCSSPrefix + 'grid-resize-marker'
}, true);
}
return me.rhsMarker;
},
-<span id='Ext-panel.Table-method-getSelectionModel'> /**
-</span> * Returns the selection model being used and creates it via the configuration
- * if it has not been created already.
+<span id='Ext-panel-Table-method-getSelectionModel'> /**
+</span> * Returns the selection model being used and creates it via the configuration if it has not been created already.
* @return {Ext.selection.Model} selModel
*/
getSelectionModel: function(){
}
if (!this.selModel.hasRelaySetup) {
- this.relayEvents(this.selModel, ['selectionchange', 'select', 'deselect']);
+ this.relayEvents(this.selModel, [
+ 'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
+ ]);
this.selModel.hasRelaySetup = true;
}
onHorizontalScroll: function(event, target) {
var owner = this.getScrollerOwner(),
items = owner.query('tableview'),
- i = 0,
- len = items.length,
- center,
- centerEl,
- centerScrollWidth,
- centerClientWidth,
- width;
-
- center = items[1] || items[0];
- centerEl = center.el.dom;
- centerScrollWidth = centerEl.scrollWidth;
- centerClientWidth = centerEl.offsetWidth;
- width = this.horizontalScroller.getWidth();
-
- centerEl.scrollLeft = target.scrollLeft;
+ center = items[1] || items[0];
+
+ center.el.dom.scrollLeft = target.scrollLeft;
this.headerCt.el.dom.scrollLeft = target.scrollLeft;
},
me.store = store;
me.getView().bindStore(store);
},
+
+ beforeDestroy: function(){
+ // may be some duplication here since the horizontal and vertical
+ // scroller may be part of the docked items, but we need to clean
+ // them up in case they aren't visible.
+ Ext.destroy(this.horizontalScroller, this.verticalScroller);
+ this.callParent();
+ },
+<span id='Ext-panel-Table-method-reconfigure'> /**
+</span> * Reconfigures the table with a new store/columns. Either the store or the columns can be ommitted if you don't wish
+ * to change them.
+ * @param {Ext.data.Store} store (Optional) The new store.
+ * @param {Object[]} columns (Optional) An array of column configs
+ */
reconfigure: function(store, columns) {
- var me = this;
+ var me = this,
+ headerCt = me.headerCt;
if (me.lockable) {
me.reconfigureLockable(store, columns);
- return;
- }
-
- if (columns) {
- me.headerCt.removeAll();
- me.headerCt.add(columns);
- }
- if (store) {
- store = Ext.StoreManager.lookup(store);
- me.bindStore(store);
} else {
- me.getView().refresh();
+ if (columns) {
+ headerCt.suspendLayout = true;
+ headerCt.removeAll();
+ headerCt.add(columns);
+ }
+ if (store) {
+ store = Ext.StoreManager.lookup(store);
+ me.bindStore(store);
+ } else {
+ me.getView().refresh();
+ }
+ if (columns) {
+ headerCt.suspendLayout = false;
+ me.forceComponentLayout();
+ }
}
- },
-
- afterComponentLayout: function() {
- this.callParent(arguments);
- this.determineScrollbars();
- this.invalidateScroller();
+ me.fireEvent('reconfigure', me);
}
-});</pre></pre></body></html>
\ No newline at end of file
+});</pre>
+</body>
+</html>