4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-panel-Table'>/**
19 </span> * @class Ext.panel.Table
20 * @extends Ext.panel.Panel
23 * @author Nicolas Ferrero
24 * TablePanel is a private class and the basis of both TreePanel and GridPanel.
26 * TablePanel aggregates:
32 * - Ext.grid.header.Container
35 Ext.define('Ext.panel.Table', {
36 extend: 'Ext.panel.Panel',
38 alias: 'widget.tablepanel',
41 'Ext.selection.RowModel',
43 'Ext.grid.header.Container',
47 cls: Ext.baseCSSPrefix + 'grid',
48 extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
51 <span id='Ext-panel-Table-property-hasView'> /**
52 </span> * Boolean to indicate that a view has been injected into the panel.
57 // each panel should dictate what viewType and selType to use
61 <span id='Ext-panel-Table-cfg-scrollDelta'> /**
62 </span> * @cfg {Number} scrollDelta
63 * Number of pixels to scroll when scrolling with mousewheel.
68 <span id='Ext-panel-Table-cfg-scroll'> /**
69 </span> * @cfg {String/Boolean} scroll
70 * Valid values are 'both', 'horizontal' or 'vertical'. true implies 'both'. false implies 'none'.
75 <span id='Ext-panel-Table-cfg-columns'> /**
76 </span> * @cfg {Array} columns
77 * An array of {@link Ext.grid.column.Column column} definition objects which define all columns that appear in this grid. Each
78 * column definition provides the header text for the column, and a definition of where the data for that column comes from.
81 <span id='Ext-panel-Table-cfg-forceFit'> /**
82 </span> * @cfg {Boolean} forceFit
83 * 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
84 * a specific width, or flex. Then they are all proportionally changed in width so that the entire content width is used..
87 <span id='Ext-panel-Table-cfg-hideHeaders'> /**
88 </span> * @cfg {Boolean} hideHeaders
89 * Specify as <code>true</code> to hide the headers.
92 <span id='Ext-panel-Table-cfg-sortableColumns'> /**
93 </span> * @cfg {Boolean} sortableColumns
94 * Defaults to true. Set to false to disable column sorting via clicking the
95 * header and via the Sorting menu items.
97 sortableColumns: true,
99 verticalScrollDock: 'right',
100 verticalScrollerType: 'gridscroller',
102 horizontalScrollerPresentCls: Ext.baseCSSPrefix + 'horizontal-scroller-present',
103 verticalScrollerPresentCls: Ext.baseCSSPrefix + 'vertical-scroller-present',
105 // private property used to determine where to go down to find views
106 // this is here to support locking.
109 invalidateScrollerOnRefresh: true,
111 enableColumnMove: true,
112 enableColumnResize: true,
115 initComponent: function() {
117 if (!this.viewType) {
118 Ext.Error.raise("You must specify a viewType config.");
121 Ext.Error.raise("You must specify a store config");
124 Ext.Error.raise("The headers config is not supported. Please specify columns instead.");
132 headerCtCfg = me.columns || me.colModel,
137 // Set our determinScrollbars method to reference a buffered call to determinScrollbars which fires on a 30ms buffer.
138 me.determineScrollbars = Ext.Function.createBuffered(me.determineScrollbars, 30);
139 me.injectView = Ext.Function.createBuffered(me.injectView, 30);
141 if (me.hideHeaders) {
145 // The columns/colModel config may be either a fully instantiated HeaderContainer, or an array of Column definitions, or a config object of a HeaderContainer
146 // Either way, we extract a columns property referencing an array of Column definitions.
147 if (headerCtCfg instanceof Ext.grid.header.Container) {
148 me.headerCt = headerCtCfg;
149 me.headerCt.border = border;
150 me.columns = me.headerCt.items.items;
152 if (Ext.isArray(headerCtCfg)) {
158 Ext.apply(headerCtCfg, {
159 forceFit: me.forceFit,
160 sortable: me.sortableColumns,
161 enableColumnMove: me.enableColumnMove,
162 enableColumnResize: me.enableColumnResize,
165 me.columns = headerCtCfg.items;
167 // If any of the Column objects contain a locked property, and are not processed, this is a lockable TablePanel, a
168 // special view will be injected by the Ext.grid.Lockable mixin, so no processing of .
169 if (Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
170 me.self.mixin('lockable', Ext.grid.Lockable);
175 me.store = Ext.data.StoreManager.lookup(me.store);
177 <span id='Ext-panel-Table-event-scrollerhide'> /**
178 </span> * @event scrollerhide
179 * Fires when a scroller is hidden
180 * @param {Ext.grid.Scroller} scroller
181 * @param {String} orientation Orientation, can be 'vertical' or 'horizontal'
184 <span id='Ext-panel-Table-event-scrollershow'> /**
185 </span> * @event scrollershow
186 * Fires when a scroller is shown
187 * @param {Ext.grid.Scroller} scroller
188 * @param {String} orientation Orientation, can be 'vertical' or 'horizontal'
193 me.bodyCls = me.bodyCls || '';
194 me.bodyCls += (' ' + me.extraBodyCls);
196 // autoScroll is not a valid configuration
197 delete me.autoScroll;
199 // If this TablePanel is lockable (Either configured lockable, or any of the defined columns has a 'locked' property)
200 // than a special lockable view containing 2 side-by-side grids will have been injected so we do not need to set up any UI.
203 // If we were not configured with a ready-made headerCt (either by direct config with a headerCt property, or by passing
204 // a HeaderContainer instance as the 'columns' property, then go ahead and create one from the config object created above.
206 me.headerCt = Ext.create('Ext.grid.header.Container', headerCtCfg);
209 // Extract the array of Column objects
210 me.columns = me.headerCt.items.items;
212 if (me.hideHeaders) {
213 me.headerCt.height = 0;
214 me.headerCt.border = false;
215 me.headerCt.addCls(Ext.baseCSSPrefix + 'grid-header-ct-hidden');
216 me.addCls(Ext.baseCSSPrefix + 'grid-header-hidden');
217 // IE Quirks Mode fix
218 // If hidden configuration option was used, several layout calculations will be bypassed.
219 if (Ext.isIEQuirks) {
220 me.headerCt.style = {
227 if (scroll === true || scroll === 'both') {
228 vertical = horizontal = true;
229 } else if (scroll === 'horizontal') {
231 } else if (scroll === 'vertical') {
233 // All other values become 'none' or false.
235 me.headerCt.availableSpaceOffset = 0;
239 me.verticalScroller = me.verticalScroller || {};
240 Ext.applyIf(me.verticalScroller, {
241 dock: me.verticalScrollDock,
242 xtype: me.verticalScrollerType,
245 me.verticalScroller = Ext.ComponentManager.create(me.verticalScroller);
246 me.mon(me.verticalScroller, {
247 bodyscroll: me.onVerticalScroll,
253 me.horizontalScroller = Ext.ComponentManager.create({
254 xtype: 'gridscroller',
259 me.mon(me.horizontalScroller, {
260 bodyscroll: me.onHorizontalScroll,
265 me.headerCt.on('columnresize', me.onHeaderResize, me);
266 me.relayEvents(me.headerCt, ['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange']);
267 me.features = me.features || [];
268 me.dockedItems = me.dockedItems || [];
269 me.dockedItems.unshift(me.headerCt);
270 me.viewConfig = me.viewConfig || {};
271 me.viewConfig.invalidateScrollerOnRefresh = me.invalidateScrollerOnRefresh;
273 // AbstractDataView will look up a Store configured as an object
274 // getView converts viewConfig into a View instance
279 load: me.onStoreLoad,
284 fn: this.onViewRefresh,
288 itemupdate: me.onViewItemUpdate,
291 this.relayEvents(view, [
292 <span id='Ext-panel-Table-event-beforeitemmousedown'> /**
293 </span> * @event beforeitemmousedown
294 * Fires before the mousedown event on an item is processed. Returns false to cancel the default action.
295 * @param {Ext.view.View} this
296 * @param {Ext.data.Model} record The record that belongs to the item
297 * @param {HTMLElement} item The item's element
298 * @param {Number} index The item's index
299 * @param {Ext.EventObject} e The raw event object
301 'beforeitemmousedown',
302 <span id='Ext-panel-Table-event-beforeitemmouseup'> /**
303 </span> * @event beforeitemmouseup
304 * Fires before the mouseup event on an item is processed. Returns false to cancel the default action.
305 * @param {Ext.view.View} this
306 * @param {Ext.data.Model} record The record that belongs to the item
307 * @param {HTMLElement} item The item's element
308 * @param {Number} index The item's index
309 * @param {Ext.EventObject} e The raw event object
312 <span id='Ext-panel-Table-event-beforeitemmouseenter'> /**
313 </span> * @event beforeitemmouseenter
314 * Fires before the mouseenter event on an item is processed. Returns false to cancel the default action.
315 * @param {Ext.view.View} this
316 * @param {Ext.data.Model} record The record that belongs to the item
317 * @param {HTMLElement} item The item's element
318 * @param {Number} index The item's index
319 * @param {Ext.EventObject} e The raw event object
321 'beforeitemmouseenter',
322 <span id='Ext-panel-Table-event-beforeitemmouseleave'> /**
323 </span> * @event beforeitemmouseleave
324 * Fires before the mouseleave event on an item is processed. Returns false to cancel the default action.
325 * @param {Ext.view.View} this
326 * @param {Ext.data.Model} record The record that belongs to the item
327 * @param {HTMLElement} item The item's element
328 * @param {Number} index The item's index
329 * @param {Ext.EventObject} e The raw event object
331 'beforeitemmouseleave',
332 <span id='Ext-panel-Table-event-beforeitemclick'> /**
333 </span> * @event beforeitemclick
334 * Fires before the click event on an item is processed. Returns false to cancel the default action.
335 * @param {Ext.view.View} this
336 * @param {Ext.data.Model} record The record that belongs to the item
337 * @param {HTMLElement} item The item's element
338 * @param {Number} index The item's index
339 * @param {Ext.EventObject} e The raw event object
342 <span id='Ext-panel-Table-event-beforeitemdblclick'> /**
343 </span> * @event beforeitemdblclick
344 * Fires before the dblclick event on an item is processed. Returns false to cancel the default action.
345 * @param {Ext.view.View} this
346 * @param {Ext.data.Model} record The record that belongs to the item
347 * @param {HTMLElement} item The item's element
348 * @param {Number} index The item's index
349 * @param {Ext.EventObject} e The raw event object
351 'beforeitemdblclick',
352 <span id='Ext-panel-Table-event-beforeitemcontextmenu'> /**
353 </span> * @event beforeitemcontextmenu
354 * Fires before the contextmenu event on an item is processed. Returns false to cancel the default action.
355 * @param {Ext.view.View} this
356 * @param {Ext.data.Model} record The record that belongs to the item
357 * @param {HTMLElement} item The item's element
358 * @param {Number} index The item's index
359 * @param {Ext.EventObject} e The raw event object
361 'beforeitemcontextmenu',
362 <span id='Ext-panel-Table-event-itemmousedown'> /**
363 </span> * @event itemmousedown
364 * Fires when there is a mouse down on an item
365 * @param {Ext.view.View} this
366 * @param {Ext.data.Model} record The record that belongs to the item
367 * @param {HTMLElement} item The item's element
368 * @param {Number} index The item's index
369 * @param {Ext.EventObject} e The raw event object
372 <span id='Ext-panel-Table-event-itemmouseup'> /**
373 </span> * @event itemmouseup
374 * Fires when there is a mouse up on an item
375 * @param {Ext.view.View} this
376 * @param {Ext.data.Model} record The record that belongs to the item
377 * @param {HTMLElement} item The item's element
378 * @param {Number} index The item's index
379 * @param {Ext.EventObject} e The raw event object
382 <span id='Ext-panel-Table-event-itemmouseenter'> /**
383 </span> * @event itemmouseenter
384 * Fires when the mouse enters an item.
385 * @param {Ext.view.View} this
386 * @param {Ext.data.Model} record The record that belongs to the item
387 * @param {HTMLElement} item The item's element
388 * @param {Number} index The item's index
389 * @param {Ext.EventObject} e The raw event object
392 <span id='Ext-panel-Table-event-itemmouseleave'> /**
393 </span> * @event itemmouseleave
394 * Fires when the mouse leaves an item.
395 * @param {Ext.view.View} this
396 * @param {Ext.data.Model} record The record that belongs to the item
397 * @param {HTMLElement} item The item's element
398 * @param {Number} index The item's index
399 * @param {Ext.EventObject} e The raw event object
402 <span id='Ext-panel-Table-event-itemclick'> /**
403 </span> * @event itemclick
404 * Fires when an item is clicked.
405 * @param {Ext.view.View} this
406 * @param {Ext.data.Model} record The record that belongs to the item
407 * @param {HTMLElement} item The item's element
408 * @param {Number} index The item's index
409 * @param {Ext.EventObject} e The raw event object
412 <span id='Ext-panel-Table-event-itemdblclick'> /**
413 </span> * @event itemdblclick
414 * Fires when an item is double clicked.
415 * @param {Ext.view.View} this
416 * @param {Ext.data.Model} record The record that belongs to the item
417 * @param {HTMLElement} item The item's element
418 * @param {Number} index The item's index
419 * @param {Ext.EventObject} e The raw event object
422 <span id='Ext-panel-Table-event-itemcontextmenu'> /**
423 </span> * @event itemcontextmenu
424 * Fires when an item is right clicked.
425 * @param {Ext.view.View} this
426 * @param {Ext.data.Model} record The record that belongs to the item
427 * @param {HTMLElement} item The item's element
428 * @param {Number} index The item's index
429 * @param {Ext.EventObject} e The raw event object
432 <span id='Ext-panel-Table-event-beforecontainermousedown'> /**
433 </span> * @event beforecontainermousedown
434 * Fires before the mousedown event on the container is processed. Returns false to cancel the default action.
435 * @param {Ext.view.View} this
436 * @param {Ext.EventObject} e The raw event object
438 'beforecontainermousedown',
439 <span id='Ext-panel-Table-event-beforecontainermouseup'> /**
440 </span> * @event beforecontainermouseup
441 * Fires before the mouseup event on the container is processed. Returns false to cancel the default action.
442 * @param {Ext.view.View} this
443 * @param {Ext.EventObject} e The raw event object
445 'beforecontainermouseup',
446 <span id='Ext-panel-Table-event-beforecontainermouseover'> /**
447 </span> * @event beforecontainermouseover
448 * Fires before the mouseover event on the container is processed. Returns false to cancel the default action.
449 * @param {Ext.view.View} this
450 * @param {Ext.EventObject} e The raw event object
452 'beforecontainermouseover',
453 <span id='Ext-panel-Table-event-beforecontainermouseout'> /**
454 </span> * @event beforecontainermouseout
455 * Fires before the mouseout event on the container is processed. Returns false to cancel the default action.
456 * @param {Ext.view.View} this
457 * @param {Ext.EventObject} e The raw event object
459 'beforecontainermouseout',
460 <span id='Ext-panel-Table-event-beforecontainerclick'> /**
461 </span> * @event beforecontainerclick
462 * Fires before the click event on the container is processed. Returns false to cancel the default action.
463 * @param {Ext.view.View} this
464 * @param {Ext.EventObject} e The raw event object
466 'beforecontainerclick',
467 <span id='Ext-panel-Table-event-beforecontainerdblclick'> /**
468 </span> * @event beforecontainerdblclick
469 * Fires before the dblclick event on the container is processed. Returns false to cancel the default action.
470 * @param {Ext.view.View} this
471 * @param {Ext.EventObject} e The raw event object
473 'beforecontainerdblclick',
474 <span id='Ext-panel-Table-event-beforecontainercontextmenu'> /**
475 </span> * @event beforecontainercontextmenu
476 * Fires before the contextmenu event on the container is processed. Returns false to cancel the default action.
477 * @param {Ext.view.View} this
478 * @param {Ext.EventObject} e The raw event object
480 'beforecontainercontextmenu',
481 <span id='Ext-panel-Table-event-containermouseup'> /**
482 </span> * @event containermouseup
483 * Fires when there is a mouse up on the container
484 * @param {Ext.view.View} this
485 * @param {Ext.EventObject} e The raw event object
488 <span id='Ext-panel-Table-event-containermouseover'> /**
489 </span> * @event containermouseover
490 * Fires when you move the mouse over the container.
491 * @param {Ext.view.View} this
492 * @param {Ext.EventObject} e The raw event object
494 'containermouseover',
495 <span id='Ext-panel-Table-event-containermouseout'> /**
496 </span> * @event containermouseout
497 * Fires when you move the mouse out of the container.
498 * @param {Ext.view.View} this
499 * @param {Ext.EventObject} e The raw event object
502 <span id='Ext-panel-Table-event-containerclick'> /**
503 </span> * @event containerclick
504 * Fires when the container is clicked.
505 * @param {Ext.view.View} this
506 * @param {Ext.EventObject} e The raw event object
509 <span id='Ext-panel-Table-event-containerdblclick'> /**
510 </span> * @event containerdblclick
511 * Fires when the container is double clicked.
512 * @param {Ext.view.View} this
513 * @param {Ext.EventObject} e The raw event object
516 <span id='Ext-panel-Table-event-containercontextmenu'> /**
517 </span> * @event containercontextmenu
518 * Fires when the container is right clicked.
519 * @param {Ext.view.View} this
520 * @param {Ext.EventObject} e The raw event object
522 'containercontextmenu',
524 <span id='Ext-panel-Table-event-selectionchange'> /**
525 </span> * @event selectionchange
526 * Fires when the selected nodes change. Relayed event from the underlying selection model.
527 * @param {Ext.view.View} this
528 * @param {Array} selections Array of the selected nodes
531 <span id='Ext-panel-Table-event-beforeselect'> /**
532 </span> * @event beforeselect
533 * Fires before a selection is made. If any handlers return false, the selection is cancelled.
534 * @param {Ext.view.View} this
535 * @param {HTMLElement} node The node to be selected
536 * @param {Array} selections Array of currently selected nodes
542 me.callParent(arguments);
546 initStateEvents: function(){
547 var events = this.stateEvents;
548 // push on stateEvents if they don't exist
549 Ext.each(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange'], function(event){
550 if (Ext.Array.indexOf(events, event)) {
557 getState: function(){
561 sorter = this.store.sorters.first();
563 this.headerCt.items.each(function(header){
566 width: header.flex ? undefined : header.width,
567 hidden: header.hidden,
568 sortable: header.sortable
574 property: sorter.property,
575 direction: sorter.direction
581 applyState: function(state) {
582 var headers = state.columns,
583 length = headers ? headers.length : 0,
584 headerCt = this.headerCt,
585 items = headerCt.items,
593 for (; i < length; ++i) {
594 headerState = headers[i];
595 header = headerCt.down('gridcolumn[headerId=' + headerState.id + ']');
596 index = items.indexOf(header);
598 headerCt.moveHeader(index, i);
600 header.sortable = headerState.sortable;
601 if (Ext.isDefined(headerState.width)) {
603 if (header.rendered) {
604 header.setWidth(headerState.width);
606 header.minWidth = header.width = headerState.width;
609 header.hidden = headerState.hidden;
613 if (store.remoteSort) {
614 store.sorters.add(Ext.create('Ext.util.Sorter', {
615 property: sorter.property,
616 direction: sorter.direction
620 store.sort(sorter.property, sorter.direction);
625 <span id='Ext-panel-Table-method-getStore'> /**
626 </span> * Returns the store associated with this Panel.
627 * @return {Ext.data.Store} The store
629 getStore: function(){
633 <span id='Ext-panel-Table-method-getView'> /**
634 </span> * Gets the view for this panel.
635 * @return {Ext.view.Table}
637 getView: function() {
642 sm = me.getSelectionModel();
643 me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
646 headerCt: me.headerCt,
648 features: me.features,
652 uievent: me.processEvent,
656 me.headerCt.view = me.view;
657 me.relayEvents(me.view, ['cellclick', 'celldblclick']);
662 <span id='Ext-panel-Table-property-setAutoScroll'> /**
665 * autoScroll is never valid for all classes which extend TablePanel.
667 setAutoScroll: Ext.emptyFn,
669 // This method hijacks Ext.view.Table's el scroll method.
670 // This enables us to keep the virtualized scrollbars in sync
671 // with the view. It currently does NOT support animation.
672 elScroll: function(direction, distance, animate) {
676 if (direction === "up" || direction === "left") {
677 distance = -distance;
680 if (direction === "down" || direction === "up") {
681 scroller = me.getVerticalScroller();
682 scroller.scrollByDeltaY(distance);
684 scroller = me.getHorizontalScroller();
685 scroller.scrollByDeltaX(distance);
689 afterLayout: function() {
690 this.callParent(arguments);
695 <span id='Ext-panel-Table-method-injectView'> /**
697 * Called after this Component has achieved its correct initial size, after all layouts have done their thing.
698 * This is so we can add the View only after the initial size is known. This method is buffered 30ms.
700 injectView: function() {
701 if (!this.hasView && !this.collapsed) {
708 // hijack the view el's scroll method
709 view.el.scroll = Ext.Function.bind(me.elScroll, me);
710 // We use to listen to document.body wheel events, but that's a
711 // little much. We scope just to the view now.
713 mousewheel: me.onMouseWheel,
719 afterExpand: function() {
720 this.callParent(arguments);
726 <span id='Ext-panel-Table-method-processEvent'> /**
728 * Process UI events from the view. Propagate them to whatever internal Components need to process them
729 * @param {String} type Event type, eg 'click'
730 * @param {TableView} view TableView Component
731 * @param {HtmlElement} cell Cell HtmlElement the event took place within
732 * @param {Number} recordIndex Index of the associated Store Model (-1 if none)
733 * @param {Number} cellIndex Cell index within the row
734 * @param {EventObject} e Original event
736 processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
740 if (cellIndex !== -1) {
741 header = me.headerCt.getGridColumns()[cellIndex];
742 return header.processEvent.apply(header, arguments);
746 <span id='Ext-panel-Table-method-determineScrollbars'> /**
747 </span> * Request a recalculation of scrollbars and put them in if they are needed.
749 determineScrollbars: function() {
757 if (!me.collapsed && me.view && me.view.el) {
758 viewElDom = me.view.el.dom;
759 //centerScrollWidth = viewElDom.scrollWidth;
760 centerScrollWidth = me.headerCt.getFullWidth();
761 <span id='Ext-panel-Table-property-centerClientWidth'> /**
762 </span> * clientWidth often returns 0 in IE resulting in an
763 * infinity result, here we use offsetWidth bc there are
764 * no possible scrollbars and we don't care about margins
766 centerClientWidth = viewElDom.offsetWidth;
767 if (me.verticalScroller && me.verticalScroller.el) {
768 scrollHeight = me.verticalScroller.getSizeCalculation().height;
770 scrollHeight = viewElDom.scrollHeight;
773 clientHeight = viewElDom.clientHeight;
775 me.suspendLayout = true;
776 me.scrollbarChanged = false;
777 if (!me.collapsed && scrollHeight > clientHeight) {
778 me.showVerticalScroller();
780 me.hideVerticalScroller();
783 if (!me.collapsed && centerScrollWidth > (centerClientWidth + Ext.getScrollBarWidth() - 2)) {
784 me.showHorizontalScroller();
786 me.hideHorizontalScroller();
788 me.suspendLayout = false;
789 if (me.scrollbarChanged) {
790 me.doComponentLayout();
795 onHeaderResize: function() {
796 if (this.view && this.view.rendered) {
797 this.determineScrollbars();
798 this.invalidateScroller();
802 <span id='Ext-panel-Table-method-hideHorizontalScroller'> /**
803 </span> * Hide the verticalScroller and remove the horizontalScrollerPresentCls.
805 hideHorizontalScroller: function() {
808 if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
809 me.scrollbarChanged = true;
810 me.verticalScroller.offsets.bottom = 0;
811 me.removeDocked(me.horizontalScroller, false);
812 me.removeCls(me.horizontalScrollerPresentCls);
813 me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
818 <span id='Ext-panel-Table-method-showHorizontalScroller'> /**
819 </span> * Show the horizontalScroller and add the horizontalScrollerPresentCls.
821 showHorizontalScroller: function() {
824 if (me.verticalScroller) {
825 me.verticalScroller.offsets.bottom = Ext.getScrollBarWidth() - 2;
827 if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
828 me.scrollbarChanged = true;
829 me.addDocked(me.horizontalScroller);
830 me.addCls(me.horizontalScrollerPresentCls);
831 me.fireEvent('scrollershow', me.horizontalScroller, 'horizontal');
835 <span id='Ext-panel-Table-method-hideVerticalScroller'> /**
836 </span> * Hide the verticalScroller and remove the verticalScrollerPresentCls.
838 hideVerticalScroller: function() {
840 headerCt = me.headerCt;
842 // only trigger a layout when reserveOffset is changing
843 if (headerCt && headerCt.layout.reserveOffset) {
844 headerCt.layout.reserveOffset = false;
847 if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
848 me.scrollbarChanged = true;
849 me.removeDocked(me.verticalScroller, false);
850 me.removeCls(me.verticalScrollerPresentCls);
851 me.fireEvent('scrollerhide', me.verticalScroller, 'vertical');
855 <span id='Ext-panel-Table-method-showVerticalScroller'> /**
856 </span> * Show the verticalScroller and add the verticalScrollerPresentCls.
858 showVerticalScroller: function() {
860 headerCt = me.headerCt;
862 // only trigger a layout when reserveOffset is changing
863 if (headerCt && !headerCt.layout.reserveOffset) {
864 headerCt.layout.reserveOffset = true;
867 if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
868 me.scrollbarChanged = true;
869 me.addDocked(me.verticalScroller);
870 me.addCls(me.verticalScrollerPresentCls);
871 me.fireEvent('scrollershow', me.verticalScroller, 'vertical');
875 <span id='Ext-panel-Table-method-invalidateScroller'> /**
876 </span> * Invalides scrollers that are present and forces a recalculation.
877 * (Not related to showing/hiding the scrollers)
879 invalidateScroller: function() {
881 vScroll = me.verticalScroller,
882 hScroll = me.horizontalScroller;
885 vScroll.invalidate();
888 hScroll.invalidate();
892 // refresh the view when a header moves
893 onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
897 // Section onHeaderHide is invoked after view.
898 onHeaderHide: function(headerCt, header) {
899 this.invalidateScroller();
902 onHeaderShow: function(headerCt, header) {
903 this.invalidateScroller();
906 getVerticalScroller: function() {
907 return this.getScrollerOwner().down('gridscroller[dock=' + this.verticalScrollDock + ']');
910 getHorizontalScroller: function() {
911 return this.getScrollerOwner().down('gridscroller[dock=bottom]');
914 onMouseWheel: function(e) {
916 browserEvent = e.browserEvent,
917 vertScroller = me.getVerticalScroller(),
918 horizScroller = me.getHorizontalScroller(),
919 scrollDelta = me.scrollDelta,
921 vertScrollerEl, horizScrollerEl,
922 vertScrollerElDom, horizScrollerElDom,
923 horizontalCanScrollLeft, horizontalCanScrollRight,
924 verticalCanScrollDown, verticalCanScrollUp;
926 // calculate whether or not both scrollbars can scroll right/left and up/down
928 horizScrollerEl = horizScroller.el;
929 if (horizScrollerEl) {
930 horizScrollerElDom = horizScrollerEl.dom;
931 horizontalCanScrollRight = horizScrollerElDom.scrollLeft !== horizScrollerElDom.scrollWidth - horizScrollerElDom.clientWidth;
932 horizontalCanScrollLeft = horizScrollerElDom.scrollLeft !== 0;
936 vertScrollerEl = vertScroller.el;
937 if (vertScrollerEl) {
938 vertScrollerElDom = vertScrollerEl.dom;
939 verticalCanScrollDown = vertScrollerElDom.scrollTop !== vertScrollerElDom.scrollHeight - vertScrollerElDom.clientHeight;
940 verticalCanScrollUp = vertScrollerElDom.scrollTop !== 0;
944 // Webkit Horizontal Axis
945 if (browserEvent.wheelDeltaX || browserEvent.wheelDeltaY) {
946 deltaX = -browserEvent.wheelDeltaX / 120 * scrollDelta / 3;
947 deltaY = -browserEvent.wheelDeltaY / 120 * scrollDelta / 3;
949 // Gecko Horizontal Axis
950 if (browserEvent.axis && browserEvent.axis === 1) {
951 deltaX = -(scrollDelta * e.getWheelDelta()) / 3;
953 deltaY = -(scrollDelta * e.getWheelDelta() / 3);
958 if ((deltaX < 0 && horizontalCanScrollLeft) || (deltaX > 0 && horizontalCanScrollRight)) {
960 horizScroller.scrollByDeltaX(deltaX);
964 if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
966 vertScroller.scrollByDeltaY(deltaY);
971 <span id='Ext-panel-Table-method-onViewRefresh'> /**
973 * Determine and invalidate scrollers on view refresh
975 onViewRefresh: function() {
977 this.syncCellHeight();
979 this.determineScrollbars();
980 if (this.invalidateScrollerOnRefresh) {
981 this.invalidateScroller();
985 onViewItemUpdate: function(record, index, tr) {
987 this.syncCellHeight([tr]);
991 // BrowserBug: IE will not stretch the td to fit the height of the entire
992 // tr, so manually sync cellheights on refresh and when an item has been
994 syncCellHeight: function(trs) {
1003 cellClsSelector = ('.' + Ext.baseCSSPrefix + 'grid-cell');
1005 trs = trs || me.view.getNodes();
1009 for (; i < trsLn; i++) {
1011 tds = Ext.fly(tr).query(cellClsSelector);
1014 for (j = 0; j < tdsLn; j++) {
1016 cellHeights.push(td.clientHeight);
1018 rowHeights.push(Ext.Array.max(cellHeights));
1022 for (i = 0; i < trsLn; i++) {
1024 tdsLn = tr.childNodes.length;
1025 for (j = 0; j < tdsLn; j++) {
1026 td = Ext.fly(tr.childNodes[j]);
1027 if (rowHeights[i]) {
1028 if (td.is(cellClsSelector)) {
1029 td.setHeight(rowHeights[i]);
1031 td.down(cellClsSelector).setHeight(rowHeights[i]);
1039 <span id='Ext-panel-Table-method-setScrollTop'> /**
1040 </span> * Sets the scrollTop of the TablePanel.
1041 * @param {Number} deltaY
1043 setScrollTop: function(top) {
1045 rootCmp = me.getScrollerOwner(),
1046 verticalScroller = me.getVerticalScroller();
1048 rootCmp.virtualScrollTop = top;
1049 if (verticalScroller) {
1050 verticalScroller.setScrollTop(top);
1055 getScrollerOwner: function() {
1057 if (!this.scrollerOwner) {
1058 rootCmp = this.up('[scrollerOwner]');
1063 <span id='Ext-panel-Table-method-scrollByDeltaY'> /**
1064 </span> * Scrolls the TablePanel by deltaY
1065 * @param {Number} deltaY
1067 scrollByDeltaY: function(deltaY) {
1068 var rootCmp = this.getScrollerOwner(),
1070 scrollerRight = rootCmp.down('gridscroller[dock=' + this.verticalScrollDock + ']');
1071 if (scrollerRight) {
1072 scrollerRight.scrollByDeltaY(deltaY);
1077 <span id='Ext-panel-Table-method-scrollByDeltaX'> /**
1078 </span> * Scrolls the TablePanel by deltaX
1079 * @param {Number} deltaY
1081 scrollByDeltaX: function(deltaX) {
1082 this.horizontalScroller.scrollByDeltaX(deltaX);
1085 <span id='Ext-panel-Table-method-getLhsMarker'> /**
1086 </span> * Get left hand side marker for header resizing.
1089 getLhsMarker: function() {
1092 if (!me.lhsMarker) {
1093 me.lhsMarker = Ext.core.DomHelper.append(me.el, {
1094 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
1097 return me.lhsMarker;
1100 <span id='Ext-panel-Table-method-getRhsMarker'> /**
1101 </span> * Get right hand side marker for header resizing.
1104 getRhsMarker: function() {
1107 if (!me.rhsMarker) {
1108 me.rhsMarker = Ext.core.DomHelper.append(me.el, {
1109 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
1112 return me.rhsMarker;
1115 <span id='Ext-panel-Table-method-getSelectionModel'> /**
1116 </span> * Returns the selection model being used and creates it via the configuration
1117 * if it has not been created already.
1118 * @return {Ext.selection.Model} selModel
1120 getSelectionModel: function(){
1121 if (!this.selModel) {
1125 var mode = 'SINGLE',
1127 if (this.simpleSelect) {
1129 } else if (this.multiSelect) {
1133 Ext.applyIf(this.selModel, {
1134 allowDeselect: this.allowDeselect,
1138 if (!this.selModel.events) {
1139 type = this.selModel.selType || this.selType;
1140 this.selModel = Ext.create('selection.' + type, this.selModel);
1143 if (!this.selModel.hasRelaySetup) {
1144 this.relayEvents(this.selModel, ['selectionchange', 'select', 'deselect']);
1145 this.selModel.hasRelaySetup = true;
1148 // lock the selection model if user
1149 // has disabled selection
1150 if (this.disableSelection) {
1151 this.selModel.locked = true;
1153 return this.selModel;
1156 onVerticalScroll: function(event, target) {
1157 var owner = this.getScrollerOwner(),
1158 items = owner.query('tableview'),
1162 for (; i < len; i++) {
1163 items[i].el.dom.scrollTop = target.scrollTop;
1167 onHorizontalScroll: function(event, target) {
1168 var owner = this.getScrollerOwner(),
1169 items = owner.query('tableview'),
1178 center = items[1] || items[0];
1179 centerEl = center.el.dom;
1180 centerScrollWidth = centerEl.scrollWidth;
1181 centerClientWidth = centerEl.offsetWidth;
1182 width = this.horizontalScroller.getWidth();
1184 centerEl.scrollLeft = target.scrollLeft;
1185 this.headerCt.el.dom.scrollLeft = target.scrollLeft;
1188 // template method meant to be overriden
1189 onStoreLoad: Ext.emptyFn,
1191 getEditorParent: function() {
1195 bindStore: function(store) {
1198 me.getView().bindStore(store);
1201 reconfigure: function(store, columns) {
1205 me.reconfigureLockable(store, columns);
1210 me.headerCt.removeAll();
1211 me.headerCt.add(columns);
1214 store = Ext.StoreManager.lookup(store);
1215 me.bindStore(store);
1217 me.getView().refresh();