/** * @class Ext.grid.Section * @extends Ext.panel.Panel * * Section of a Grid. Headers are docked in this area and this class * synchronizes the viewable area and headers. * * Locked Sections * - cannot flex headers. * - must have a fixed width * * Virtualized (non locked) or Scrollable Sections must be synchronized vertically. * * Sections can resize based off of header size/visibility changes. * * Templates can become dirty based off of visibility changes. */ Ext.define('Ext.grid.Section', { extend: 'Ext.panel.Panel', requires: [ 'Ext.grid.View', 'Ext.grid.HeaderContainer' ], alias: 'widget.gridsection', layout: 'fit', cls: Ext.baseCSSPrefix + 'grid-section', isGridSection: true, scroll: true, border: false, verticalScrollDock: 'right', extraBodyCls: Ext.baseCSSPrefix + 'grid-body', scrollDelta: 40,
/** * Boolean to indicate that GridView has been injected into this Grid Section. * @property hasGridView */ hasGridView: false, // TODO: Rename headers -> columns initComponent: function() { // TODO: Remove in the future. if (!this.locked) { this.flex = 1; } this.bodyCls = this.bodyCls || ''; this.bodyCls += (' ' + this.extraBodyCls); this.dockedItems = this.dockedItems || []; var scroll = this.scroll, vertical = false, horizontal = false; // turn both on. if (scroll === true || scroll === 'both') { vertical = horizontal = true; } else if (scroll === 'horizontal') { horizontal = true; } else if (scroll === 'vertical') { vertical = true; } // All other values become 'none' or false. if (vertical) { this.verticalScroller = Ext.ComponentMgr.create({ dock: this.verticalScrollDock, xtype: 'gridscroller' }); } if (horizontal) { this.horizontalScroller = Ext.ComponentMgr.create({ xtype: 'gridscroller', section: this, dock: 'bottom' }); }
/** * @property headerCt -> colModel? */ this.headerCt = new Ext.grid.HeaderContainer({ items: this.headers }); this.headerCt.on('headerresize', this.onHeaderResize, this); this.features = this.features || []; this.dockedItems = this.dockedItems || []; this.dockedItems.unshift(this.headerCt); Ext.grid.Section.superclass.initComponent.call(this); }, determineScrollbars: function() { if (!this.dtScrollTask) { this.dtScrollTask = new Ext.util.DelayedTask(this.doDetermineScrollbars, this); } this.dtScrollTask.delay(30); }, doDetermineScrollbars: function() { if (this.view) { var viewElDom = this.view.el.dom, centerScrollWidth = viewElDom.scrollWidth, // clientWidth often returns 0 in IE resulting in an // infinity result, here we use offsetWidth bc there are // no possible scrollbars and we dont care about margins centerClientWidth = viewElDom.offsetWidth, scrollHeight = viewElDom.scrollHeight, clientHeight = viewElDom.clientHeight; if (scrollHeight > clientHeight) { this.showVerticalScroller(); } else { this.hideVerticalScroller(); } if (centerScrollWidth > (centerClientWidth + Ext.getScrollBarWidth() - 2)) { this.showHorizontalScroller(); } else { this.hideHorizontalScroller(); } } }, onHeaderResize: function() { if (this.view) { this.determineScrollbars(); this.up('gridpanel').invalidateScroller(); } }, afterLayout: function() { Ext.grid.Section.superclass.afterLayout.call(this); if (!this.hasGridView) { this.hasGridView = true; this.viewConfig = this.viewConfig || {}; Ext.applyIf(this.viewConfig, { xtype: 'gridview', store: this.store, headerCt: this.headerCt, selModel: this.selModel, features: this.features, listeners: { bodyscroll: this.onGridViewScroll, scope: this } }); this.view = this.add(this.viewConfig); this.headerCt.view = this.view; Ext.Function.defer(this.determineScrollbars, 50, this); Ext.getBody().on('mousewheel', this.onMouseWheel, this); } }, hideHorizontalScroller: function() { if (this.horizontalScroller.ownerCt === this) { this.verticalScroller.offsets.bottom = 0; this.removeDocked(this.horizontalScroller, false); } }, showHorizontalScroller: function() { this.verticalScroller.offsets.bottom = Ext.getScrollBarWidth() - 2; if (this.horizontalScroller.ownerCt !== this) { this.addDocked(this.horizontalScroller); } }, hideVerticalScroller: function() { if (this.verticalScroller.ownerCt === this) { this.removeDocked(this.verticalScroller, false); } }, showVerticalScroller: function() { if (this.verticalScroller.ownerCt !== this) { this.addDocked(this.verticalScroller); } }, invalidateScroller: function() { this.up('gridpanel').invalidateScroller(); }, onGridViewScroll: function(e, t) { this.headerCt.el.dom.scrollLeft = t.scrollLeft; }, onHeaderMove: function(headerCt, header, fromIdx, toIdx) { this.view.refresh(); //this.up('gridpanel').invalidateScroller(); }, // Section onHeaderHide is invoked after view. onHeaderHide: function(headerCt, header, idx) { this.invalidateScroller(); }, onHeaderShow: function(headerCt, header, idx) { this.invalidateScroller(); }, getLhsMarker: function() { if (!this.lhsMarker) { this.lhsMarker = Ext.core.DomHelper.append(this.el, { cls: Ext.baseCSSPrefix + 'grid-resize-marker' }, true); } return this.lhsMarker; }, getRhsMarker: function() { if (!this.rhsMarker) { this.rhsMarker = Ext.core.DomHelper.append(this.el, { cls: Ext.baseCSSPrefix + 'grid-resize-marker' }, true); } return this.rhsMarker; }, onMouseWheel: function(e) { var dock = this.dock, browserEvent = e.browserEvent, vertDock = this.verticalScrollDock; if (e.within(this.el)) { e.stopEvent(); // Webkit Horizontal Axis if (browserEvent.wheelDeltaX || browserEvent.wheelDeltaY) { this.horizontalScroller.scrollByDeltaX(-browserEvent.wheelDeltaX / 120 * this.scrollDelta / 6); this.verticalScroller.scrollByDeltaY(-browserEvent.wheelDeltaY / 120 * this.scrollDelta / 6); } else { // Gecko Horizontal Axis if (browserEvent.axis && browserEvent.axis === 1) { this.horizontalScroller.scrollByDeltaX(-(this.scrollDelta * e.getWheelDelta()) / 6); } else { this.verticalScroller.scrollByDeltaY(-(this.scrollDelta * e.getWheelDelta() / 6)); } } } } });