]>
git.proxmox.com Git - extjs.git/blob - extjs/classic/classic/src/panel/Table.js
2 * This class is the base class for both {@link Ext.tree.Panel TreePanel} and
3 * {@link Ext.grid.Panel GridPanel}.
5 * TablePanel aggregates:
10 * - Ext.grid.header.Container
12 * @mixins Ext.grid.locking.Lockable
14 Ext
. define ( 'Ext.panel.Table' , {
15 extend
: 'Ext.panel.Panel' ,
17 alias
: 'widget.tablepanel' ,
20 'Ext.layout.container.Fit'
24 'Ext.selection.RowModel' ,
25 'Ext.selection.CellModel' ,
26 'Ext.selection.CheckboxModel' ,
27 'Ext.grid.plugin.BufferedRenderer' ,
28 'Ext.grid.header.Container' ,
29 'Ext.grid.locking.Lockable' ,
30 'Ext.grid.NavigationModel'
33 extraBaseCls
: Ext
. baseCSSPrefix
+ 'grid' ,
34 extraBodyCls
: Ext
. baseCSSPrefix
+ 'grid-body' ,
35 actionableModeCls
: Ext
. baseCSSPrefix
+ 'grid-actionable' ,
36 noHeaderBordersCls
: Ext
. baseCSSPrefix
+ 'no-header-borders' ,
38 defaultBindProperty
: 'store' ,
46 * @cfg {Ext.data.Model} selection
47 * The selected model. Typically used with {@link #bind binding}.
52 * @cfg {Boolean} [headerBorders=`true`]
53 * To show no borders around grid headers, configure this as `false`.
58 publishes
: [ 'selection' ],
59 twoWayBindable
: [ 'selection' ],
62 * @cfg {Boolean} [autoLoad=false]
63 * Use `true` to load the store as soon as this component is fully constructed. It is
64 * best to initiate the store load this way to allow this component and potentially
65 * its plugins (such as `{@link Ext.grid.filters.Filters}`) to be ready to load.
70 * @cfg {Boolean} [variableRowHeight=false]
71 * @deprecated 5.0.0 Use {@link Ext.grid.column.Column#variableRowHeight} instead.
72 * Configure as `true` if the row heights are not all the same height as the first row.
74 variableRowHeight
: false ,
77 * @cfg {Number} [numFromEdge]
78 * This configures the zone which causes new rows to be appended to the view. As soon as the edge
79 * of the rendered grid is this number of rows from the edge of the viewport, the view is moved.
84 * @cfg {Number} [trailingBufferZone]
85 * TableViews are buffer rendered in 5.x and above which means that only the visible subset of data rows
86 * are rendered into the DOM. These are removed and added as scrolling demands.
88 * This configures the number of extra rows to render on the trailing side of scrolling
89 * **outside the {@link #numFromEdge}** buffer as scrolling proceeds.
91 trailingBufferZone
: 10 ,
94 * @cfg {Number} [leadingBufferZone]
95 * TableViews are buffer rendered in 5.x and above which means that only the visible subset of data rows
96 * are rendered into the DOM. These are removed and added as scrolling demands.
98 * This configures the number of extra rows to render on the leading side of scrolling
99 * **outside the {@link #numFromEdge}** buffer as scrolling proceeds.
101 leadingBufferZone
: 20 ,
104 * @property {Boolean} hasView
105 * True to indicate that a view has been injected into the panel.
115 * @cfg {String} viewType
116 * An xtype of view to use. This is automatically set to 'tableview' by {@link Ext.grid.Panel Grid}
117 * and to 'treeview' by {@link Ext.tree.Panel Tree}.
123 * @cfg {Object} viewConfig
124 * A config object that will be applied to the grid's UI view. Any of the config options available for
125 * {@link Ext.view.Table} can be specified here. This option is ignored if {@link #view} is specified.
129 * @cfg {Ext.view.Table} view
130 * The {@link Ext.view.Table} used by the grid. Use {@link #viewConfig} to just supply some config options to
131 * view (instead of creating an entire View instance).
135 * @cfg {String} [selType]
136 * An xtype of selection model to use. This is used to create selection model if just
137 * a config object or nothing at all given in {@link #selModel} config.
139 * @deprecated 5.1.0 Use the {@link #selModel}'s `type` property. Or, if no other
140 * configs are required, use the string form of selModel.
144 * @cfg {Ext.selection.Model/Object/String} [selModel=rowmodel]
145 * A {@link Ext.selection.Model selection model} instance or config object, or the selection model class's alias string.
147 * In latter case its `type` property determines to which type of selection model this config is applied.
151 * @cfg {Boolean} [multiSelect=false]
152 * True to enable 'MULTI' selection mode on selection model.
153 * @deprecated 4.1.1 Use {@link Ext.selection.Model#mode} 'MULTI' instead.
157 * @cfg {Boolean} [simpleSelect=false]
158 * True to enable 'SIMPLE' selection mode on selection model.
159 * @deprecated 4.1.1 Use {@link Ext.selection.Model#mode} 'SIMPLE' instead.
163 * @cfg {Ext.data.Store/String/Object} store (required)
164 * The data source to which the grid / tree is bound. Acceptable values for this
167 * - **any {@link Ext.data.Store Store} class / subclass**
168 * - **an {@link Ext.data.Store#storeId ID of a store}**
169 * - **a {@link Ext.data.Store Store} config object**. When passing a config you can
170 * specify the store type by alias. Passing a config object with a store type will
171 * dynamically create a new store of that type when the grid / tree is instantiated.
175 * Ext.define('MyApp.store.Customers', {
176 * extend: 'Ext.data.Store',
177 * alias: 'store.customerstore',
182 * xtype: 'gridpanel',
183 * renderTo: document.body,
185 * type: 'customerstore',
198 * @cfg {String/Boolean} scroll
199 * Scrollers configuration. Valid values are 'both', 'horizontal' or 'vertical'.
200 * True implies 'both'. False implies 'none'.
201 * @deprecated 5.1.0 Use {@link #scrollable} instead
205 * @cfg {Boolean} [reserveScrollbar=false]
206 * Set this to true to **always** leave a scrollbar sized space at the end of the grid content when
207 * fitting content into the width of the grid.
209 * If the grid's record count fluctuates enough to hide and show the scrollbar regularly, this setting
210 * avoids the multiple layouts associated with switching from scrollbar present to scrollbar not present.
214 * @cfg {Ext.grid.column.Column[]/Object} columns
215 * An array of {@link Ext.grid.column.Column column} definition objects which define all columns that appear in this
216 * grid. Each column definition provides the header text for the column, and a definition of where the data for that
219 * This can also be a configuration object for a {@link Ext.grid.header.Container HeaderContainer} which may override
220 * certain default configurations if necessary. For example, the special layout may be overridden to use a simpler
221 * layout, or one can set default values shared by all columns:
227 * dataIndex: "field_A"
230 * dataIndex: "field_B"
241 * @cfg {Boolean} forceFit
242 * True to force the columns to fit into the available width. Headers are first sized according to configuration,
243 * whether that be a specific width, or flex. Then they are all proportionally changed in width so that the entire
244 * content width is used. For more accurate control, it is more optimal to specify a flex setting on the columns
245 * that are to be stretched & explicit widths on columns that are not.
249 * @cfg {Ext.grid.feature.Feature[]/Object[]/Ext.enums.Feature[]} features
250 * An array of grid Features to be added to this grid. Can also be just a single feature instead of array.
252 * Features config behaves much like {@link #plugins}.
253 * A feature can be added by either directly referencing the instance:
255 * features: [Ext.create('Ext.grid.feature.GroupingSummary', {groupHeaderTpl: 'Subject: {name}'})],
257 * By using config object with ftype:
259 * features: [{ftype: 'groupingsummary', groupHeaderTpl: 'Subject: {name}'}],
261 * Or with just a ftype:
263 * features: ['grouping', 'groupingsummary'],
265 * See {@link Ext.enums.Feature} for list of all ftypes.
269 * @cfg {Boolean} [hideHeaders=false]
270 * True to hide column headers.
274 * @cfg {Boolean} [deferRowRender=false]
275 * Configure as `true` to enable deferred row rendering.
277 * This allows the View to execute a refresh quickly, with the update of the row structure deferred so
278 * that layouts with GridPanels appear, and lay out more quickly.
280 deferRowRender
: false ,
283 * @cfg {Boolean} [sortableColumns=true]
284 * False to disable column sorting via clicking the header and via the Sorting menu items.
286 sortableColumns
: true ,
289 * @cfg {Boolean} [multiColumnSort=false]
290 * Configure as `true` to have columns remember their sorted state after other columns have been clicked upon to sort.
292 * As subsequent columns are clicked upon, they become the new primary sort key.
294 * The maximum number of sorters allowed in a Store is configurable via its underlying data collection. See {@link Ext.util.Collection#multiSortLimit}
296 multiColumnSort
: false ,
299 * @cfg {Boolean} [enableLocking=false]
300 * Configure as `true` to enable locking support for this grid. Alternatively, locking will also be automatically
301 * enabled if any of the columns in the {@link #columns columns} configuration contain a {@link Ext.grid.column.Column#locked locked} config option.
303 * A locking grid is processed in a special way. The configuration options are cloned and *two* grids are created to be the locked (left) side
304 * and the normal (right) side. This Panel becomes merely a {@link Ext.container.Container container} which arranges both in an {@link Ext.layout.container.HBox HBox} layout.
306 * {@link #plugins Plugins} may be targeted at either locked, or unlocked grid, or, both, in which case the plugin is cloned and used on both sides.
308 * Plugins may also be targeted at the containing locking Panel.
310 * This is configured by specifying a `lockableScope` property in your plugin which may have the following values:
312 * * `"both"` (the default) - The plugin is added to both grids
313 * * `"top"` - The plugin is added to the containing Panel
314 * * `"locked"` - The plugin is added to the locked (left) grid
315 * * `"normal"` - The plugin is added to the normal (right) grid
317 * If `both` is specified, then each copy of the plugin gains a property `lockingPartner` which references its sibling on the other side so that they
318 * can synchronize operations is necessary.
320 * {@link #features Features} may also be configured with `lockableScope` and may target the locked grid, the normal grid or both grids. Features
321 * also get a `lockingPartner` reference injected.
323 enableLocking
: false ,
327 * Used to determine where to go down to find views
328 * this is here to support locking.
333 * @cfg {Boolean} [enableColumnMove=true]
334 * False to disable column dragging within this grid.
336 enableColumnMove
: true ,
339 * @cfg {Boolean} [sealedColumns=false]
340 * True to constrain column dragging so that a column cannot be dragged in or out of it's
341 * current group. Only relevant while {@link #enableColumnMove} is enabled.
343 sealedColumns
: false ,
346 * @cfg {Boolean} [enableColumnResize=true]
347 * False to disable column resizing within this grid.
349 enableColumnResize
: true ,
352 * @cfg {Boolean} [enableColumnHide=true]
353 * False to disable column hiding within this grid.
357 * @cfg {Boolean} columnLines Adds column line styling
361 * @cfg {Boolean} [rowLines=true] Adds row line styling
366 * @cfg {Boolean} [disableSelection=false]
367 * True to disable selection model.
371 * @cfg {String} emptyText Default text (HTML tags are accepted) to display in the
372 * Panel body when the Store is empty. When specified, and the Store is empty, the
373 * text will be rendered inside a DIV with the CSS class "x-grid-empty". The emptyText
374 * will not display until the first load of the associated store by default. If you
375 * want the text to be displayed prior to the first store load use the
376 * {@link Ext.view.Table#deferEmptyText deferEmptyText} config in the {@link #viewConfig} config.
380 * @cfg {Boolean} [allowDeselect=false]
381 * True to allow deselecting a record. This config is forwarded to {@link Ext.selection.Model#allowDeselect}.
385 * @cfg {Boolean} [bufferedRenderer=true]
386 * Buffered rendering is enabled by default.
388 * Configure as `false` to disable buffered rendering. See {@link Ext.grid.plugin.BufferedRenderer}.
392 bufferedRenderer
: true ,
396 * @inheritdoc Ext.state.Stateful#cfg-stateEvents
397 * @localdoc By default the following stateEvents are added:
399 * - {@link #event-resize} - _(added by Ext.Component)_
400 * - {@link #event-collapse} - _(added by Ext.panel.Panel)_
401 * - {@link #event-expand} - _(added by Ext.panel.Panel)_
402 * - {@link #event-columnresize}
403 * - {@link #event-columnmove}
404 * - {@link #event-columnhide}
405 * - {@link #event-columnshow}
406 * - {@link #event-sortchange}
407 * - {@link #event-filterchange}
408 * - {@link #event-groupchange}
412 * @property {Boolean} optimizedColumnMove
413 * If you are writing a grid plugin or a {Ext.grid.feature.Feature Feature} which creates a column-based structure which
414 * needs a view refresh when columns are moved, then set this property in the grid.
416 * An example is the built in {@link Ext.grid.feature.AbstractSummary Summary} Feature. This creates summary rows, and the
417 * summary columns must be in the same order as the data columns. This plugin sets the `optimizedColumnMove` to `false.
421 * @property {Ext.panel.Table} ownerGrid
422 * A reference to the top-level owning grid component.
424 * This is a reference to this GridPanel if this GridPanel is not part of a locked grid arrangement.
431 colLinesCls
: Ext
. baseCSSPrefix
+ 'grid-with-col-lines' ,
432 rowLinesCls
: Ext
. baseCSSPrefix
+ 'grid-with-row-lines' ,
433 noRowLinesCls
: Ext
. baseCSSPrefix
+ 'grid-no-row-lines' ,
434 hiddenHeaderCtCls
: Ext
. baseCSSPrefix
+ 'grid-header-ct-hidden' ,
435 hiddenHeaderCls
: Ext
. baseCSSPrefix
+ 'grid-header-hidden' ,
436 resizeMarkerCls
: Ext
. baseCSSPrefix
+ 'grid-resize-marker' ,
437 emptyCls
: Ext
. baseCSSPrefix
+ 'grid-empty' ,
439 // The TablePanel claims to be focusable, but it does not place a tabIndex
440 // on any of its elements.
441 // Its focus implementation delegates to its view. TableViews are focusable.
446 * Fires when the grid view is available (use this for selecting a default row).
447 * @param {Ext.panel.Table} this
450 constructor : function ( config
) {
452 topGrid
= config
&& config
. ownerGrid
,
455 me
. ownerGrid
= topGrid
|| me
;
458 * @property {Array} actionables An array of objects which register themselves with a grid panel using
459 * {@link #registerActionable} which are consulted upon entry into actionable mode.
461 * These must implement the following methods:
463 * - activateCell Called when actionable mode is requested upon a cell. A {@link Ext.grid.CellContext CellContext}
464 * object is passed. If that cell is actionable by the terms of the callee, the callee should return `true` if it
465 * ascertains that the cell is actionable, and that it now contains focusable elements which may be tabbed to.
466 * - activateRow Called when the user enters actionable mode in a row. The row DOM is passed. Actionables
467 * should take any action they need to prime the row for cell activation which happens as users TAB from cell to cell.
470 me
. actionables
= topGrid
? topGrid
. actionables
: []; // One shared array when there's a lockable at the top
472 me
. callParent ([ config
]);
476 // Any further changes become stateful.
477 store
. trackStateChanges
= true ;
480 // Note: if there is a store bound by a VM, we (might) do the load in #setStore.
481 if (! store
. isEmptyStore
) {
489 * @param {Object} actionable An object which has an interest in the implementation of actionable mode in
492 * An actionable object may be a Plugin which upon activation injects tabbable elements or Components into
495 registerActionable : function ( actionable
) {
496 // If a lockableScope: 'both' plugin/feature registers on each side, only include it in the actionables once.
497 Ext
. Array
. include ( this . actionables
, actionable
);
500 initComponent : function () {
502 if ( this . verticalScroller
) {
503 Ext
. raise ( "The verticalScroller config is not supported." );
505 if (! this . viewType
) {
506 Ext
. raise ( "You must specify a viewType config." );
509 Ext
. raise ( "The headers config is not supported. Please specify columns instead." );
514 headerCtCfg
= me
. columns
|| me
. colModel
|| [],
515 store
, view
, i
, len
, bufferedRenderer
, columns
, viewScroller
, headerCt
;
517 // Look up the configured Store. If none configured, use the fieldless, empty Store
518 // defined in Ext.data.Store.
519 store
= me
. store
= Ext
. data
. StoreManager
. lookup ( me
. store
|| 'ext-empty-store' );
521 me
. enableLocking
= me
. enableLocking
|| me
. hasLockedColumns ( headerCtCfg
);
523 // Construct the plugins now rather than in the constructor of AbstractComponent because the component may have a subclass
524 // that has overridden initComponent and defined plugins in it. For plugins like RowExpander that rely upon a grid feature,
525 // this is a problem because the view needs to know about all its features before it's constructed. Constructing the plugins
526 // now ensures that plugins defined in the instance config or in initComponent are all constructed before the view.
527 // See EXTJSIV-11927.
529 // Note that any components that do not inherit from this class will still have their plugins constructed in
530 // AbstractComponent:initComponent.
532 me
. plugins
= me
. constructPlugins ();
535 // Add the row/column line classes to the body element so that the settings are not inherited by docked grids (https://sencha.jira.com/browse/EXTJSIV-9263).
536 if ( me
. columnLines
) {
537 me
. addBodyCls ( me
. colLinesCls
);
540 me
. addBodyCls ( me
. rowLines
? me
. rowLinesCls
: me
. noRowLinesCls
);
541 me
. addBodyCls ( me
. extraBodyCls
);
544 // If any of the Column objects contain a locked property, and are not processed, this is a lockable TablePanel, a
545 // special view will be injected by the Ext.grid.locking.Lockable mixin, so no processing of .
546 if ( me
. enableLocking
) {
547 me
. self
. mixin ( 'lockable' , Ext
. grid
. locking
. Lockable
);
549 headerCt
= me
. headerCt
;
551 // Not lockable - create the HeaderContainer
553 // It's a fully instantiated HeaderContainer
554 if ( headerCtCfg
. isRootHeader
) {
555 if ( me
. hideHeaders
) {
556 headerCtCfg
. setHeight ( 0 );
557 // don't set the hidden property, we still need these to layout
558 headerCtCfg
. hiddenHeaders
= true ;
560 // the header container is not user scrollable, but it has a scroller instance
561 // so that we can sync its scroll position with that of the grid view
562 headerCtCfg
. setScrollable ({
568 me
. headerCt
= headerCt
= headerCtCfg
;
571 headerCt
. forceFit
= !! me
. forceFit
;
572 headerCt
.$ initParent
= me
;
574 // If it's an instance then the column managers were already created and bound to the headerCt.
575 me
. columnManager
= headerCtCfg
. columnManager
;
576 me
. visibleColumnManager
= headerCtCfg
. visibleColumnManager
;
578 // It's an array of Column definitions, or a config object of a HeaderContainer
580 if ( Ext
. isArray ( headerCtCfg
)) {
585 Ext
. apply ( headerCtCfg
, {
588 forceFit
: me
. forceFit
,
589 sortable
: me
. sortableColumns
,
590 enableColumnMove
: me
. enableColumnMove
,
591 enableColumnResize
: me
. enableColumnResize
,
592 columnLines
: me
. columnLines
,
593 sealed
: me
. sealedColumns
,
594 // the header container is not user scrollable, but if it is visible,
595 // it has a scroller instance so that we can sync its scroll position with that of the grid view
596 scrollable
: me
. hideHeaders
? undefined : {
601 if ( me
. hideHeaders
) {
602 headerCtCfg
. height
= 0 ;
603 // don't set the hidden property, we still need these to layout
604 headerCtCfg
. hiddenHeaders
= true ;
607 if ( Ext
. isDefined ( me
. enableColumnHide
)) {
608 headerCtCfg
. enableColumnHide
= me
. enableColumnHide
;
610 me
. headerCt
= headerCt
= new Ext
. grid
. header
. Container ( headerCtCfg
);
614 // Maintain backward compatibiliy by providing the initial leaf column set as a property.
615 me
. columns
= columns
= headerCt
. getGridColumns ();
617 me
. scrollTask
= new Ext
. util
. DelayedTask ( me
. syncHorizontalScroll
, me
);
619 me
. cls
= ( me
. cls
|| '' ) + ( ' ' + me
. extraBaseCls
);
621 // autoScroll is not a valid configuration
622 delete me
. autoScroll
;
624 bufferedRenderer
= me
. plugins
&& Ext
. Array
. findBy ( me
. plugins
, function ( p
) {
625 return p
. isBufferedRenderer
;
628 // If we find one in the plugins, just use that.
629 if ( bufferedRenderer
) {
630 me
. bufferedRenderer
= bufferedRenderer
;
633 // If this TablePanel is lockable (Either configured lockable, or any of the defined columns has a 'locked' property)
634 // then a special lockable view containing 2 side-by-side grids will have been injected so we do not need to set up any UI.
637 // If the Store is paging blocks of the dataset in, then it can only be sorted remotely.
638 if ( store
. isBufferedStore
&& ! store
. getRemoteSort ()) {
639 for ( i
= 0 , len
= columns
. length
; i
< len
; i
++) {
640 columns
[ i
]. sortable
= false ;
644 if ( me
. hideHeaders
) {
645 me
. headerCt
. addCls ( me
. hiddenHeaderCtCls
);
646 me
. addCls ( me
. hiddenHeaderCls
);
649 me
. relayHeaderCtEvents ( headerCt
);
650 me
. features
= me
. features
|| [];
651 if (! Ext
. isArray ( me
. features
)) {
652 me
. features
= [ me
. features
];
654 me
. dockedItems
= []. concat ( me
. dockedItems
|| []);
655 me
. dockedItems
. unshift ( headerCt
);
656 me
. viewConfig
= me
. viewConfig
|| {};
658 // AbstractDataView will look up a Store configured as an object
659 // getView converts viewConfig into a View instance
665 // Add a listener to synchronize the horizontal scroll position of the headers
666 // with the table view's element... Unless we are not showing headers!
667 if (! me
. hideHeaders
) {
668 // sync the horizontal scroll position of the headerCt as the view is scrolled.
669 viewScroller
= view
. getScrollable ();
671 headerCt
. getScrollable (). addPartner ( viewScroller
, 'x' );
675 // Attach this Panel to the Store
676 me
. bindStore ( store
, true );
679 viewready
: me
. onViewReady
,
680 refresh
: me
. onRestoreHorzScroll
,
685 // Whatever kind of View we have, be it a TableView, or a LockingView, we are interested in the selection model
686 me
. selModel
= me
. view
. getSelectionModel ();
687 if ( me
. selModel
. isRowModel
) {
690 lastselectedchanged
: me
. updateBindSelection
,
691 selectionchange
: me
. updateBindSelection
695 // Relay events from the View whether it be a LockingView, or a regular GridView
696 me
. relayEvents ( me
. view
, [
698 * @event beforeitemmousedown
699 * @inheritdoc Ext.view.View#beforeitemmousedown
701 'beforeitemmousedown' ,
703 * @event beforeitemmouseup
704 * @inheritdoc Ext.view.View#beforeitemmouseup
708 * @event beforeitemmouseenter
709 * @inheritdoc Ext.view.View#beforeitemmouseenter
711 'beforeitemmouseenter' ,
713 * @event beforeitemmouseleave
714 * @inheritdoc Ext.view.View#beforeitemmouseleave
716 'beforeitemmouseleave' ,
718 * @event beforeitemclick
719 * @inheritdoc Ext.view.View#beforeitemclick
723 * @event beforeitemdblclick
724 * @inheritdoc Ext.view.View#beforeitemdblclick
726 'beforeitemdblclick' ,
728 * @event beforeitemcontextmenu
729 * @inheritdoc Ext.view.View#beforeitemcontextmenu
731 'beforeitemcontextmenu' ,
733 * @event itemmousedown
734 * @inheritdoc Ext.view.View#itemmousedown
739 * @inheritdoc Ext.view.View#itemmouseup
743 * @event itemmouseenter
744 * @inheritdoc Ext.view.View#itemmouseenter
748 * @event itemmouseleave
749 * @inheritdoc Ext.view.View#itemmouseleave
754 * @inheritdoc Ext.view.View#itemclick
758 * @event itemdblclick
759 * @inheritdoc Ext.view.View#itemdblclick
763 * @event itemcontextmenu
764 * @inheritdoc Ext.view.View#itemcontextmenu
768 * @event beforecellclick
769 * @inheritdoc Ext.view.Table#beforecellclick
774 * @inheritdoc Ext.view.Table#cellclick
778 * @event beforecelldblclick
779 * @inheritdoc Ext.view.Table#beforecelldblclick
781 'beforecelldblclick' ,
783 * @event celldblclick
784 * @inheritdoc Ext.view.Table#celldblclick
788 * @event beforecellcontextmenu
789 * @inheritdoc Ext.view.Table#beforecellcontextmenu
791 'beforecellcontextmenu' ,
793 * @event cellcontextmenu
794 * @inheritdoc Ext.view.Table#cellcontextmenu
798 * @event beforecellmousedown
799 * @inheritdoc Ext.view.Table#beforecellmousedown
801 'beforecellmousedown' ,
803 * @event cellmousedown
804 * @inheritdoc Ext.view.Table#cellmousedown
808 * @event beforecellmouseup
809 * @inheritdoc Ext.view.Table#beforecellmouseup
814 * @inheritdoc Ext.view.Table#cellmouseup
818 * @event beforecellkeydown
819 * @inheritdoc Ext.view.Table#beforecellkeydown
824 * @inheritdoc Ext.view.Table#cellkeydown
829 * @inheritdoc Ext.view.Table#rowclick
834 * @inheritdoc Ext.view.Table#rowdblclick
838 * @event rowcontextmenu
839 * @inheritdoc Ext.view.Table#rowcontextmenu
843 * @event rowmousedown
844 * @inheritdoc Ext.view.Table#rowmousedown
849 * @inheritdoc Ext.view.Table#rowmouseup
854 * @inheritdoc Ext.view.Table#rowkeydown
858 * @event beforeitemkeydown
859 * @inheritdoc Ext.view.Table#beforeitemkeydown
864 * @inheritdoc Ext.view.Table#itemkeydown
868 * @event beforeitemkeyup
869 * @inheritdoc Ext.view.Table#beforeitemkeyup
874 * @inheritdoc Ext.view.Table#itemkeyup
878 * @event beforeitemkeypress
879 * @inheritdoc Ext.view.Table#beforeitemkeypress
881 'beforeitemkeypress' ,
883 * @event itemkeypress
884 * @inheritdoc Ext.view.Table#itemkeypress
888 * @event beforecontainermousedown
889 * @inheritdoc Ext.view.View#beforecontainermousedown
891 'beforecontainermousedown' ,
893 * @event beforecontainermouseup
894 * @inheritdoc Ext.view.View#beforecontainermouseup
896 'beforecontainermouseup' ,
898 * @event beforecontainermouseover
899 * @inheritdoc Ext.view.View#beforecontainermouseover
901 'beforecontainermouseover' ,
903 * @event beforecontainermouseout
904 * @inheritdoc Ext.view.View#beforecontainermouseout
906 'beforecontainermouseout' ,
908 * @event beforecontainerclick
909 * @inheritdoc Ext.view.View#beforecontainerclick
911 'beforecontainerclick' ,
913 * @event beforecontainerdblclick
914 * @inheritdoc Ext.view.View#beforecontainerdblclick
916 'beforecontainerdblclick' ,
918 * @event beforecontainercontextmenu
919 * @inheritdoc Ext.view.View#beforecontainercontextmenu
921 'beforecontainercontextmenu' ,
923 * @event beforecontainerkeydown
924 * @inheritdoc Ext.view.View#beforecontainerkeydown
926 'beforecontainerkeydown' ,
928 * @event beforecontainerkeyup
929 * @inheritdoc Ext.view.View#beforecontainerkeyup
931 'beforecontainerkeyup' ,
933 * @event beforecontainerkeypress
934 * @inheritdoc Ext.view.View#beforecontainerkeypress
936 'beforecontainerkeypress' ,
938 * @event containermouseup
939 * @inheritdoc Ext.view.View#containermouseup
943 * @event containermousedown
944 * @inheritdoc Ext.view.View#containermousedown
946 'containermousedown' ,
948 * @event containermouseover
949 * @inheritdoc Ext.view.View#containermouseover
951 'containermouseover' ,
953 * @event containermouseout
954 * @inheritdoc Ext.view.View#containermouseout
958 * @event containerclick
959 * @inheritdoc Ext.view.View#containerclick
963 * @event containerdblclick
964 * @inheritdoc Ext.view.View#containerdblclick
968 * @event containercontextmenu
969 * @inheritdoc Ext.view.View#containercontextmenu
971 'containercontextmenu' ,
973 * @event containerkeydown
974 * @inheritdoc Ext.view.View#containerkeydown
978 * @event containerkeyup
979 * @inheritdoc Ext.view.View#containerkeyup
983 * @event containerkeypress
984 * @inheritdoc Ext.view.View#containerkeypress
988 * @event selectionchange
989 * @inheritdoc Ext.selection.Model#selectionchange
993 * @event beforeselect
994 * @inheritdoc Ext.selection.RowModel#beforeselect
999 * @inheritdoc Ext.selection.RowModel#select
1003 * @event beforedeselect
1004 * @inheritdoc Ext.selection.RowModel#beforedeselect
1009 * @inheritdoc Ext.selection.RowModel#deselect
1015 if ( me
. enableLocking
) {
1016 me
. afterInjectLockable ();
1018 delete headerCt
.$ initParent
;
1020 me
. addStateEvents ([ 'columnresize' , 'columnmove' , 'columnhide' , 'columnshow' , 'sortchange' , 'filterchange' , 'groupchange' ]);
1022 // rowBody feature events
1024 * @event beforerowbodymousedown
1026 * @inheritdoc Ext.view.Table#event-beforerowbodymousedown
1030 * @event beforerowbodymouseup
1032 * @inheritdoc Ext.view.Table#event-beforerowbodymouseup
1036 * @event beforerowbodyclick
1038 * @inheritdoc Ext.view.Table#event-beforerowbodyclick
1042 * @event beforerowbodydblclick
1044 * @inheritdoc Ext.view.Table#event-beforerowbodydblclick
1048 * @event beforerowbodycontextmenu
1050 * @inheritdoc Ext.view.Table#event-beforerowbodycontextmenu
1054 * @event beforerowbodylongpress
1056 * @inheritdoc Ext.view.Table#event-beforerowbodylongpress
1060 * @event beforerowbodykeydown
1062 * @inheritdoc Ext.view.Table#event-beforerowbodykeydown
1066 * @event beforerowbodykeyup
1068 * @inheritdoc Ext.view.Table#event-beforerowbodykeyup
1072 * @event beforerowbodykeypress
1074 * @inheritdoc Ext.view.Table#event-beforerowbodykeypress
1078 * @event rowbodymousedown
1079 * @inheritdoc Ext.view.Table#event-rowbodymousedown
1083 * @event rowbodymouseup
1084 * @inheritdoc Ext.view.Table#event-rowbodymouseup
1088 * @event rowbodyclick
1089 * @inheritdoc Ext.view.Table#event-rowbodyclick
1093 * @event rowbodydblclick
1094 * @inheritdoc Ext.view.Table#event-rowbodydblclick
1098 * @event rowbodycontextmenu
1099 * @inheritdoc Ext.view.Table#event-rowbodycontextmenu
1103 * @event rowbodylongpress
1104 * @inheritdoc Ext.view.Table#event-rowbodylongpress
1108 * @event rowbodykeydown
1109 * @inheritdoc Ext.view.Table#event-rowbodykeydown
1113 * @event rowbodykeyup
1114 * @inheritdoc Ext.view.Table#event-rowbodykeyup
1118 * @event rowbodykeypress
1119 * @inheritdoc Ext.view.Table#event-rowbodykeypress
1123 beforeRender : function () {
1125 bufferedRenderer
= me
. bufferedRenderer
,
1128 // If this is the topmost container of a lockable assembly, add the special class body
1130 me
. getProtoBody (). addCls ( me
. lockingBodyCls
);
1133 // Don't create a buffered renderer for a locked grid.
1135 // If we're auto heighting, we can't buffered render, so don't create it
1136 if ( bufferedRenderer
&& me
. getSizeModel (). height
. auto
) {
1138 if ( bufferedRenderer
. isBufferedRenderer
) {
1139 Ext
. raise ( 'Cannot use buffered rendering with auto height' );
1142 me
. bufferedRenderer
= bufferedRenderer
= false ;
1145 if ( bufferedRenderer
&& ! bufferedRenderer
. isBufferedRenderer
) {
1146 // Create a BufferedRenderer as a plugin if we have not already configured with one.
1147 bufferedRenderer
= {
1148 xclass
: 'Ext.grid.plugin.BufferedRenderer'
1150 Ext
. copy ( bufferedRenderer
, me
, 'variableRowHeight,numFromEdge,trailingBufferZone,leadingBufferZone,scrollToLoadBuffer' );
1151 me
. bufferedRenderer
= me
. addPlugin ( bufferedRenderer
);
1154 ariaAttr
= me
. ariaRenderAttributes
|| ( me
. ariaRenderAttributes
= {});
1155 ariaAttr
[ 'aria-readonly' ] = ! me
. isEditable
;
1156 ariaAttr
[ 'aria-multiselectable' ] = me
. selModel
. selectionMode
!== 'SINGLE' ;
1159 me
. callParent ( arguments
);
1162 onRender : function () {
1164 gridPanelBorderWidth
,
1167 // If this is the locked side, include border width in calculated locked grid width.
1168 // TODO: Use shrinkWrapDock on the locked grid's headerCt when it works.
1169 if ( me
. isLocked
&& me
. getSizeModel (). width
. shrinkWrap
) {
1170 me
. shrinkWrapColumns
= true ;
1171 totalColumnWidth
= me
. headerCt
. getTableWidth ();
1173 if ( isNaN ( totalColumnWidth
)) {
1174 Ext
. raise ( "Locked columns in an unsized locked side do NOT support a flex width." );
1177 gridPanelBorderWidth
= me
. gridPanelBorderWidth
|| ( me
. gridPanelBorderWidth
= me
. el
. getBorderWidth ( 'lr' ));
1178 me
. width
= totalColumnWidth
+ gridPanelBorderWidth
;
1184 * Gets the {@link Ext.grid.header.Container headercontainer} for this grid / tree.
1185 * @return {Ext.grid.header.Container} headercontainer
1187 * **Note:** While a locked grid / tree will return an instance of
1188 * {@link Ext.grid.locking.HeaderContainer} you will code to the
1189 * {@link Ext.grid.header.Container} API.
1191 getHeaderContainer : function () {
1192 return this . getView (). getHeaderCt ();
1196 * @inheritdoc Ext.grid.header.Container#getGridColumns
1198 getColumns : function () {
1199 return this . getColumnManager (). getColumns ();
1203 * @inheritdoc Ext.grid.header.Container#getVisibleGridColumns
1205 getVisibleColumns : function () {
1206 return this . getVisibleColumnManager (). getColumns ();
1210 // TablePanel is not focusable, but allow a call to delegate into the view
1211 this . getView (). focus ();
1215 * Disables interaction with, and masks this grid's column headers.
1217 disableColumnHeaders : function () {
1218 this . headerCt
. disable ();
1222 * Enables interaction with, and unmasks this grid's column headers after a call to {#disableColumnHeaders}.
1224 enableColumnHeaders : function () {
1225 this . headerCt
. enable ();
1230 * Determine if there are any columns with a locked configuration option.
1232 hasLockedColumns : function ( columns
) {
1237 // Fully instantiated HeaderContainer
1238 if ( columns
. isRootHeader
) {
1239 columns
= columns
. items
. items
;
1241 // Config object with items
1242 else if ( Ext
. isObject ( columns
)) {
1243 columns
= columns
. items
;
1245 for ( i
= 0 , len
= columns
. length
; i
< len
; i
++) {
1246 column
= columns
[ i
];
1247 if (! column
. processed
&& column
. locked
) {
1253 relayHeaderCtEvents : function ( headerCt
) {
1254 this . relayEvents ( headerCt
, [
1256 * @event columnresize
1257 * @inheritdoc Ext.grid.header.Container#columnresize
1262 * @inheritdoc Ext.grid.header.Container#columnmove
1267 * @inheritdoc Ext.grid.header.Container#columnhide
1272 * @inheritdoc Ext.grid.header.Container#columnshow
1276 * @event columnschanged
1277 * @inheritdoc Ext.grid.header.Container#columnschanged
1282 * @inheritdoc Ext.grid.header.Container#sortchange
1286 * @event headerclick
1287 * @inheritdoc Ext.grid.header.Container#headerclick
1291 * @event headercontextmenu
1292 * @inheritdoc Ext.grid.header.Container#headercontextmenu
1294 'headercontextmenu' ,
1296 * @event headertriggerclick
1297 * @inheritdoc Ext.grid.header.Container#headertriggerclick
1299 'headertriggerclick'
1303 getState : function (){
1305 state
= me
. callParent (),
1306 storeState
= me
. store
. getState ();
1308 state
= me
. addPropertyToState ( state
, 'columns' , me
. headerCt
. getColumnsState ());
1311 state
. storeState
= storeState
;
1316 applyState : function ( state
) {
1318 sorter
= state
. sort
,
1319 storeState
= state
. storeState
,
1321 columns
= state
. columns
;
1323 delete state
. columns
;
1325 // Ensure superclass has applied *its* state.
1326 // Component saves dimensions (and anchor/flex) plus collapsed state.
1327 me
. callParent ( arguments
);
1330 // Column state restoration needs to examine store state
1331 me
. headerCt
. applyColumnsState ( columns
, storeState
);
1334 // Old stored sort state. Deprecated and will die out.
1336 if ( store
. getRemoteSort ()) {
1337 // Pass false to prevent a sort from occurring.
1339 property
: sorter
. property
,
1340 direction
: sorter
. direction
,
1344 store
. sort ( sorter
. property
, sorter
. direction
);
1347 // New storeState which encapsulates groupers, sorters and filters.
1348 else if ( storeState
) {
1349 store
. applyState ( storeState
);
1354 * Returns the store associated with this Panel.
1355 * @return {Ext.data.Store} The store
1357 getStore : function (){
1362 * Gets the view for this panel.
1363 * @return {Ext.view.Table}
1365 getView : function () {
1367 scroll
, scrollable
, viewConfig
;
1370 viewConfig
= me
. viewConfig
;
1371 scroll
= viewConfig
. scroll
|| me
. scroll
;
1372 scrollable
= me
. scrollable
;
1374 if ( scrollable
== null && viewConfig
. scrollable
== null && scroll
!== null ) {
1375 // transform deprecated scroll config into scrollable config
1376 if ( scroll
=== true || scroll
=== 'both' ) {
1378 } else if ( scroll
=== false || scroll
=== 'none' ) {
1380 } else if ( scroll
=== 'vertical' ) {
1385 } else if ( scroll
=== 'horizontal' ) {
1393 viewConfig
= Ext
. apply ({
1394 // TableView injects the view reference into this grid so that we have a reference as early as possible
1395 // and Features need a reference to the grid.
1396 // For these reasons, we configure a reference to this grid into the View
1398 ownerGrid
: me
. ownerGrid
,
1399 deferInitialRefresh
: me
. deferRowRender
,
1400 variableRowHeight
: me
. variableRowHeight
,
1401 preserveScrollOnRefresh
: true ,
1402 trackOver
: me
. trackMouseOver
!== false ,
1403 throttledUpdate
: me
. throttledUpdate
=== true ,
1406 headerCt
: me
. headerCt
,
1407 columnLines
: me
. columnLines
,
1408 rowLines
: me
. rowLines
,
1409 navigationModel
: 'grid' ,
1410 features
: me
. features
,
1412 emptyText
: me
. emptyText
|| ''
1415 if ( scrollable
!= null ) {
1416 viewConfig
. scrollable
= scrollable
;
1417 me
. scrollable
= null ;
1420 Ext
. create ( viewConfig
);
1422 // Normalize the application of the markup wrapping the emptyText config.
1423 // `emptyText` can now be defined on the grid as well as on its viewConfig, and this led to the emptyText not
1424 // having the wrapping markup when it was defined in the viewConfig. It should be backwards compatible.
1425 // Note that in the unlikely event that emptyText is defined on both the grid config and the viewConfig that the viewConfig wins.
1426 if ( me
. view
. emptyText
) {
1427 me
. view
. emptyText
= '<div class="' + me
. emptyCls
+ '">' + me
. view
. emptyText
+ '</div>' ;
1430 // TableView's custom component layout, Ext.view.TableLayout requires a reference to the headerCt because it depends on the headerCt doing its work.
1431 me
. view
. getComponentLayout (). headerCt
= me
. headerCt
;
1434 uievent
: me
. processEvent
,
1437 me
. headerCt
. view
= me
. view
;
1439 // Plugins and features may need to access the view as soon as it is created.
1440 if ( me
. hasListeners
. viewcreated
) {
1441 me
. fireEvent ( 'viewcreated' , me
, me
. view
);
1447 getColumnManager : function () {
1448 return this . columnManager
;
1451 getVisibleColumnManager : function () {
1452 return this . visibleColumnManager
;
1455 getTopLevelColumnManager : function () {
1456 return this . ownerGrid
. getColumnManager ();
1459 getTopLevelVisibleColumnManager : function () {
1460 return this . ownerGrid
. getVisibleColumnManager ();
1465 * autoScroll is never valid for all classes which extend TablePanel.
1467 setAutoScroll
: Ext
. emptyFn
,
1469 applyScrollable : function ( scrollable
) {
1471 this . view
. setScrollable ( scrollable
);
1477 getScrollable : function () {
1483 * Processes UI events from the view. Propagates them to whatever internal Components need to process them.
1484 * @param {String} type Event type, eg 'click'
1485 * @param {Ext.view.Table} view TableView Component
1486 * @param {HTMLElement} cell Cell HTMLElement the event took place within
1487 * @param {Number} recordIndex Index of the associated Store Model (-1 if none)
1488 * @param {Number} cellIndex Cell index within the row
1489 * @param {Ext.event.Event} e Original event
1491 processEvent : function ( type
, view
, cell
, recordIndex
, cellIndex
, e
, record
, row
) {
1492 var header
= e
. position
. column
;
1495 return header
. processEvent
. apply ( header
, arguments
);
1500 * Scrolls the specified record into view.
1501 * @param {Number/String/Ext.data.Model} record The record, record id, or the zero-based position in the dataset to scroll to.
1502 * @param {Object} [options] An object containing options to modify the operation.
1503 * @param {Boolean} [options.animate] Pass `true` to animate the row into view.
1504 * @param {Boolean} [options.highlight] Pass `true` to highlight the row with a glow animation when it is in view.
1505 * @param {Boolean} [options.select] Pass as `true` to select the specified row.
1506 * @param {Boolean} [options.focus] Pass as `true` to focus the specified row.
1507 * @param {Function} [options.callback] A function to execute when the record is in view. This may be necessary if the
1508 * first parameter is a record index and the view is backed by a {@link Ext.data.BufferedStore buffered store}
1509 * which does not contain that record.
1510 * @param {Boolean} options.callback.success `true` if acquiring the record's view node was successful.
1511 * @param {Ext.data.Model} options.callback.record If successful, the target record.
1512 * @param {HTMLElement} options.callback.node If successful, the record's view node.
1513 * @param {Object} [options.scope] The scope (`this` reference) in which the callback function is executed.
1515 ensureVisible : function ( record
, options
) {
1516 this . doEnsureVisible ( record
, options
);
1519 scrollByDeltaY : function ( yDelta
, animate
) {
1520 this . getView (). scrollBy ( 0 , yDelta
, animate
);
1523 scrollByDeltaX : function ( xDelta
, animate
) {
1524 this . getView (). scrollBy ( xDelta
, 0 , animate
);
1527 afterCollapse : function () {
1528 this . saveScrollPos ();
1529 this . callParent ( arguments
);
1532 afterExpand : function () {
1533 this . callParent ( arguments
);
1534 this . restoreScrollPos ();
1537 saveScrollPos
: Ext
. emptyFn
,
1539 restoreScrollPos
: Ext
. emptyFn
,
1541 onHeaderResize : function () {
1542 var scroller
= this . view
. getScrollable (),
1545 if ( scroller
&& scroller
. isTouchScroller
) {
1546 size
= scroller
. getSize ();
1549 x
: this . headerCt
. getTableWidth (),
1556 // Update the view when a header moves
1557 onHeaderMove : function ( headerCt
, header
, colsToMove
, fromIdx
, toIdx
) {
1560 // If there are Features or Plugins which create DOM which must match column order, they set the optimizedColumnMove flag to false.
1561 // In this case we must refresh the view on column move.
1562 if ( me
. optimizedColumnMove
=== false ) {
1563 me
. view
. refreshView ();
1566 // Simplest case for default DOM structure is just to swap the columns round in the view.
1568 me
. view
. moveColumn ( fromIdx
, toIdx
, colsToMove
);
1573 // Section onHeaderHide is invoked after view.
1574 onHeaderHide : function ( headerCt
, header
) {
1575 var view
= this . view
;
1576 // The headerCt may be hiding multiple children if a leaf level column
1577 // causes a parent (and possibly other parents) to be hidden. Only run the refresh
1579 if (! headerCt
. childHideCount
&& view
. refreshCounter
) {
1584 onHeaderShow : function ( headerCt
, header
) {
1585 var view
= this . view
;
1586 if ( view
. refreshCounter
) {
1591 // To be triggered on add/remove/move for a leaf header
1592 onHeadersChanged : function ( headerCt
, header
) {
1594 if ( me
. rendered
&& ! me
. reconfiguring
) {
1595 me
. view
. refreshView ();
1600 delayScroll : function (){
1601 var target
= this . view
;
1603 // Do not cause a layout by reading scrollX now.
1604 // It must be read from the target when the task finally executes.
1605 this . scrollTask
. delay ( 10 , null , null , [ target
]);
1611 * Fires the TablePanel's viewready event when the view declares that its internal DOM is ready
1613 onViewReady : function () {
1614 this . fireEvent ( 'viewready' , this );
1619 * Tracks when things happen to the view and preserves the horizontal scroll position.
1621 onRestoreHorzScroll : function () {
1626 // We need to restore the body scroll position here
1627 me
. syncHorizontalScroll ( me
, true );
1631 getScrollerOwner : function () {
1633 if (! this . scrollerOwner
) {
1634 rootCmp
= this . up ( '[scrollerOwner]' );
1640 * Gets left hand side marker for header resizing.
1643 getLhsMarker : function () {
1645 return me
. lhsMarker
|| ( me
. lhsMarker
= Ext
. DomHelper
. append ( me
. el
, {
1646 role
: 'presentation' ,
1647 cls
: me
. resizeMarkerCls
1652 * Gets right hand side marker for header resizing.
1655 getRhsMarker : function () {
1658 return me
. rhsMarker
|| ( me
. rhsMarker
= Ext
. DomHelper
. append ( me
. el
, {
1659 role
: 'presentation' ,
1660 cls
: me
. resizeMarkerCls
1665 * Returns the grid's selection. See `{@link Ext.selection.Model#getSelection}`.
1666 * @inheritdoc Ext.selection.Model#getSelection
1668 getSelection : function () {
1669 return this . getSelectionModel (). getSelection ();
1672 updateSelection : function ( selection
) {
1676 if (! me
. ignoreNextSelection
) {
1677 me
. ignoreNextSelection
= true ;
1678 sm
= me
. getSelectionModel ();
1680 sm
. select ( selection
);
1684 me
. ignoreNextSelection
= false ;
1688 updateBindSelection : function ( selModel
, selection
) {
1692 if (! me
. ignoreNextSelection
) {
1693 me
. ignoreNextSelection
= true ;
1694 if ( selection
. length
) {
1695 selected
= selModel
. getLastSelected ();
1696 me
. hasHadSelection
= true ;
1698 if ( me
. hasHadSelection
) {
1699 me
. setSelection ( selected
);
1701 me
. ignoreNextSelection
= false ;
1705 updateHeaderBorders : function ( headerBorders
) {
1706 this [ headerBorders
? 'removeCls' : 'addCls' ]( this . noHeaderBordersCls
);
1709 getNavigationModel : function () {
1710 return this . getView (). getNavigationModel ();
1714 * Returns the selection model being used by this grid's {@link Ext.view.Table view}.
1715 * @return {Ext.selection.Model} The selection model being used by this grid's {@link Ext.view.Table view}.
1717 getSelectionModel : function () {
1718 return this . getView (). getSelectionModel ();
1721 getScrollTarget : function (){
1722 var items
= this . getScrollerOwner (). query ( 'tableview' );
1724 // Last view has the scroller
1725 return items
[ items
. length
- 1 ];
1728 syncHorizontalScroll : function ( target
, setBody
) {
1730 x
= me
. view
. getScrollX (),
1733 setBody
= setBody
=== true ;
1734 // Only set the horizontal scroll if we've changed position,
1735 // so that we don't set this on vertical scrolls
1736 if ( me
. rendered
&& ( setBody
|| x
!== me
. scrollXPos
)) {
1737 // Only set the body position if we're reacting to a refresh, otherwise
1738 // we just need to set the header.
1740 scrollTarget
= me
. getScrollTarget ();
1741 scrollTarget
. setScrollX ( x
);
1743 me
. headerCt
. setScrollX ( x
);
1748 // template method meant to be overriden
1749 onStoreLoad
: Ext
. emptyFn
,
1751 getEditorParent : function () {
1755 bindStore : function ( store
, initial
) {
1757 view
= me
. getView ();
1759 // Normally, this method will always be called with a valid store (because there is a symmetric
1760 // .unbindStore method), but there are cases where this method will be called and passed a null
1761 // value, i.e., a panel is used as a pickerfield. See EXTJS-13089.
1763 // Bind to store immediately because subsequent processing looks for grid's store property
1766 if ( view
. store
!== store
) {
1767 // If coming from a reconfigure, we need to set the actual store property on the view. Setting the
1768 // store will then also set the dataSource.
1770 // Note that if it's a grid feature then this is sorted out in view.bindStore(), and it's own
1771 // implementation of .bindStore() will be called.
1772 view
. bindStore ( store
, false );
1776 load
: me
. onStoreLoad
,
1779 me
. storeRelayers
= me
. relayEvents ( store
, [
1781 * @event filterchange
1782 * @inheritdoc Ext.data.Store#filterchange
1786 * @event groupchange
1787 * @inheritdoc Ext.data.Store#groupchange
1796 unbindStore : function () {
1802 store
. trackStateChanges
= false ;
1807 load
: me
. onStoreLoad
,
1811 Ext
. destroy ( me
. storeRelayers
);
1815 view
. bindStore ( null );
1820 setColumns : function ( columns
) {
1821 // If being reconfigured from zero columns to zero columns, skip operation.
1822 // This can happen if columns are being set from a binding and the initial value
1823 // of the bound data in the ViewModel is []
1824 if ( columns
. length
|| this . getColumnManager (). getColumns (). length
) {
1825 this . reconfigure ( undefined , columns
);
1830 * A convenience method that fires {@link #reconfigure} with the store param. To set the store AND change columns,
1831 * use the {@link #reconfigure reconfigure method}.
1833 * @param {Ext.data.Store} [store] The new store.
1835 setStore : function ( store
) {
1836 this . reconfigure ( store
);
1838 if ( this . autoLoad
&& ! store
. isEmptyStore
&& !( store
. loading
|| store
. isLoaded ())) {
1844 * Reconfigures the grid or tree with a new store and/or columns. Stores and columns
1845 * may also be passed as params.
1847 * grid.reconfigure(store, columns);
1849 * Additionally, you can pass just a store or columns.
1851 * tree.reconfigure(store);
1853 * grid.reconfigure(columns);
1855 * tree.reconfigure(null, columns);
1857 * If you're using locked columns, the {@link #enableLocking} config should be set
1858 * to `true` before the reconfigure method is executed.
1860 * @param {Ext.data.Store/Object} [store] The new store instance or store config. You can
1861 * pass `null` if no new store.
1862 * @param {Object[]} [columns] An array of column configs
1864 reconfigure : function ( store
, columns
) {
1866 oldStore
= me
. store
,
1867 headerCt
= me
. headerCt
,
1868 lockable
= me
. lockable
,
1869 oldColumns
= headerCt
? headerCt
. items
. getRange () : me
. columns
,
1870 view
= me
. getView (),
1871 block
, refreshCounter
;
1873 // Allow optional store argument to be fully omitted, and the columns argument to be solo
1874 if ( arguments
. length
=== 1 && Ext
. isArray ( store
)) {
1879 // Make copy in case the beforereconfigure listener mutates it.
1881 columns
= Ext
. Array
. slice ( columns
);
1884 me
. reconfiguring
= true ;
1886 store
= Ext
. StoreManager
. lookup ( store
);
1888 me
. fireEvent ( 'beforereconfigure' , me
, store
, columns
, oldStore
, oldColumns
);
1890 Ext
. suspendLayouts ();
1893 me
. reconfigureLockable ( store
, columns
);
1895 // Prevent the view from refreshing until we have resumed layouts and any columns are rendered
1896 block
= view
. blockRefresh
;
1897 view
. blockRefresh
= true ;
1899 // The following test compares the result of an assignment of the store var with the oldStore var.
1900 // This saves a large amount of code.
1902 // Note that we need to process the store first in case one or more passed columns (if there are any)
1903 // have active gridfilters with values which would filter the currently-bound store.
1904 if ( store
&& store
!== oldStore
) {
1906 me
. bindStore ( store
);
1910 // new columns, delete scroll pos
1911 delete me
. scrollXPos
;
1912 headerCt
. removeAll ();
1913 headerCt
. add ( columns
);
1916 view
. blockRefresh
= block
;
1917 refreshCounter
= view
. refreshCounter
;
1920 Ext
. resumeLayouts ( true );
1922 me
. afterReconfigureLockable ();
1923 } else if ( view
. refreshCounter
=== refreshCounter
) {
1924 // If the layout resumption didn't trigger the view to refresh, do it here
1928 me
. fireEvent ( 'reconfigure' , me
, store
, columns
, oldStore
, oldColumns
);
1929 delete me
. reconfiguring
;
1932 beforeDestroy : function (){
1934 task
= me
. scrollTask
;
1938 me
. scrollTask
= null ;
1940 Ext
. destroy ( me
. focusEnterLeaveListeners
);
1944 onDestroy : function (){
1947 me
. destroyLockable ();
1951 me
. columns
= me
. storeRelayers
= me
. columnManager
= me
. visibleColumnManager
= null ;
1954 destroy : function () {
1955 // Clear out references here because other things (plugins/features) may need to know about them during destruction
1959 me
. view
= me
. selModel
= me
. headerCt
= null ;
1964 // The focusable flag is set, but there is no focusable element.
1965 // Focus is delegated to the view by the focus implementation.
1966 initFocusableElement : function () {},
1968 doEnsureVisible : function ( record
, options
) {
1969 // Handle the case where this is a lockable assembly
1970 if ( this . lockable
) {
1971 return this . ensureLockedVisible ( record
, options
);
1974 // Allow them to pass the record id.
1975 if ( typeof record
!== 'number' && ! record
. isEntity
) {
1976 record
= this . store
. getById ( record
);
1979 view
= me
. getView (),
1980 domNode
= view
. getNode ( record
),
1981 callback
, scope
, animate
,
1982 highlight
, select
, doFocus
, scrollable
, column
, cell
;
1985 callback
= options
. callback
;
1986 scope
= options
. scope
;
1987 animate
= options
. animate
;
1988 highlight
= options
. highlight
;
1989 select
= options
. select
;
1990 doFocus
= options
. focus
;
1991 column
= options
. column
;
1994 // Always supercede any prior deferred request
1995 if ( me
. deferredEnsureVisible
) {
1996 me
. deferredEnsureVisible
. destroy ();
1999 // We have not yet run the layout.
2000 // Add this to the end of the first sizing process.
2001 // By using the resize event, we will come in AFTER any Component's onResize and onBoxReady handling.
2002 if (! view
. componentLayoutCounter
) {
2003 me
. deferredEnsureVisible
= view
. on ({
2004 resize
: me
. doEnsureVisible
,
2005 args
: Ext
. Array
. slice ( arguments
),
2013 if ( typeof column
=== 'number' ) {
2014 column
= me
. ownerGrid
. getVisibleColumnManager (). getColumns ()[ column
];
2017 // We found the DOM node associated with the record
2019 scrollable
= view
. getScrollable ();
2021 cell
= Ext
. fly ( domNode
). selectNode ( column
. getCellSelector ());
2024 scrollable
. scrollIntoView ( cell
|| domNode
, !! column
, animate
, highlight
);
2026 if (! record
. isEntity
) {
2027 record
= view
. getRecord ( domNode
);
2030 view
. getSelectionModel (). select ( record
);
2033 view
. getNavigationModel (). setPosition ( record
, 0 );
2035 Ext
. callback ( callback
, scope
|| me
, [ true , record
, domNode
]);
2037 // If we didn't find it, it's probably because of buffered rendering
2038 else if ( view
. bufferedRenderer
) {
2039 view
. bufferedRenderer
. scrollTo ( record
, {
2041 highlight
: highlight
,
2045 callback : function ( recordIdx
, record
, domNode
) {
2046 Ext
. callback ( callback
, scope
|| me
, [ true , record
, domNode
]);
2050 Ext
. callback ( callback
, scope
|| me
, [ false , null ]);
2054 getFocusEl : function () {
2055 return this . getView (). getFocusEl ();
2059 * Toggles ARIA actionable mode on/off
2060 * @param {Boolean} enabled
2061 * @return {Boolean} `true` if actionable mode was entered
2064 setActionableMode : function ( enabled
, position
) {
2065 // Always set the topmost grid in a lockable assembly
2066 var me
= this . ownerGrid
;
2068 // Can be called to exit actionable mode upon a focusLeave caused by destruction
2069 if (! me
. destroying
&& me
. view
. setActionableMode ( enabled
, position
) !== false ) {
2070 me
. fireEvent ( 'actionablemodechange' , enabled
);
2071 me
[ enabled
? 'addCls' : 'removeCls' ]( me
. actionableModeCls
);