/** * @class Ext.grid.Header * @extends Ext.Component * * Clicking on a header will toggle sort by the bound dataIndex. * * Opening a menu will allow you to turn on/off Headers found in a particular * section. * * Allows a user to freeze columns */ Ext.define('Ext.grid.Header', { extend: 'Ext.Component', alias: 'widget.gridheader', headerCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable', overCls: Ext.baseCSSPrefix + 'column-header-over', height: 23, sortState: null, possibleSortStates: ['ASC', 'DESC'], renderTpl: [ '{text}', '', // TODO: Use an additional CSS class because // this does not allow a user to dynamically re-enable a menu. '
' ],
/** * @cfg {String} dataIndex

Required. The name of the field in the * grid's {@link Ext.data.Store}'s {@link Ext.data.Record} definition from * which to draw the column's value.

*/ dataIndex: null,
/** * @cfg {String} text Optional. The header text to be used as innerHTML * (html tags are accepted) to display in the Grid. Note: to * have a clickable header with no text displayed you can use the * default of ' '. */ text: ' ',
/** * @cfg {Boolean} sortable Optional. true if sorting is to be allowed on this column. * Defaults to the value of the {@link Ext.grid.ColumnModel#defaultSortable} property. * Whether local/remote sorting is used is specified in {@link Ext.data.Store#remoteSort}. */ sortable: true,
/** * @cfg {Boolean} hideable Optional. Specify as false to prevent the user from hiding this column * (defaults to true). */ hideable: true,
/** * @cfg {Boolean} menuDisabled * Defaults to false. */ menuDisabled: false,
/** * @cfg {Function} renderer * Defaults to false. */ renderer: false,
/** * @cfg {String} align Sets the alignment of the header and renderered columns. * Defaults to 'left'. */ align: 'left',
/** * @cfg {Boolean} draggable Indicates whether or not the header can be drag and drop re-ordered. * Defaults to true. */ draggable: true, // Header does not use the typical ComponentDraggable class and therefore we // override this with an emptyFn. It is controlled at the HeaderDragZone. initDraggable: Ext.emptyFn,
/** * @property {Ext.core.Element} triggerEl */
/** * @property {Ext.core.Element} textEl */ initComponent: function() { this.cls = this.headerCls + ' ' + (this.cls ? this.cls : ''); if (Ext.isDefined(this.header)) { console.warn("Header is now using text instead of header."); this.text = this.header; delete this.header; } if (!this.triStateSort) { this.possibleSortStates.length = 2; } Ext.applyIf(this.renderSelectors, { triggerEl: '.' + Ext.baseCSSPrefix + 'column-header-trigger', textEl: 'span' }); Ext.grid.Header.superclass.initComponent.call(this); }, initRenderData: function() { Ext.applyIf(this.renderData, { text: this.text, menuDisabled: this.menuDisabled }); return Ext.grid.Header.superclass.initRenderData.call(this); }, // note that this should invalidate the menu cache setText: function(text) { this.text = text; if (this.rendered) { this.textEl.update(text); } }, afterRender: function() { Ext.grid.Header.superclass.afterRender.call(this); var el = this.el; el.addCls(Ext.baseCSSPrefix + 'column-header-align-' + this.align); el.addClsOnOver(this.overCls); el.on('click', this.onElClick, this); }, onElClick: function(e, t) { var ownerCt = this.ownerCt; if (ownerCt && !ownerCt.locked) { // Firefox doesn't check the current target in a within check. // Therefore we check the target directly and then within (ancestors) if (this.triggerEl && (e.target === this.triggerEl.dom || e.within(this.triggerEl))) { ownerCt.onHeaderTriggerClick(this, e, t); } else { this.toggleSortState(); ownerCt.onHeaderClick(this, e, t); } } }, toggleSortState: function() { if (this.sortable) { var idx = Ext.Array.indexOf(this.possibleSortStates, this.sortState), nextIdx; nextIdx = (idx + 1) % this.possibleSortStates.length; this.setSortState(this.possibleSortStates[nextIdx]); } }, //setSortState: function(state, updateUI) { //setSortState: function(state, doSort) { setSortState: function(state, skipClear) { var colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-', ascCls = colSortClsPrefix + 'ASC', descCls = colSortClsPrefix + 'DESC', nullCls = colSortClsPrefix + 'null', ds = this.up('gridpanel').store; this.addCls(colSortClsPrefix + state); if (state) { ds.sort(this.dataIndex, state); } switch (state) { case 'DESC': this.removeCls(ascCls, nullCls); break; case 'ASC': this.removeCls(descCls, nullCls); break; case null: this.removeCls(ascCls, descCls); break; } if (!this.triStateSort && !skipClear) { this.ownerCt.clearOtherSortStates(this); } this.sortState = state; }, hide: function() { this.oldWidth = this.getWidth(); Ext.grid.Header.superclass.hide.apply(this, arguments); var ownerCt = this.ownerCt; // Notify owning HeaderContainer if (ownerCt) { ownerCt.onHeaderHide(this); } }, show: function() { Ext.grid.Header.superclass.show.apply(this, arguments); var ownerCt = this.ownerCt; // Notify owning HeaderContainer if (ownerCt) { ownerCt.onHeaderShow(this); } }, onResize: function() { }, setSize: function(w, h) { Ext.grid.Header.superclass.setSize.call(this, w, h); var ownerCt = this.ownerCt; if (ownerCt) { ownerCt.onHeaderResize(this, w); } }, // invoked when dynamically calculating a flex'd value setCalculatedSize: function(w, h) { Ext.grid.Header.superclass.setCalculatedSize.call(this, w, h); //this.width = w; //delete this.flex; var ownerCt = this.ownerCt; if (ownerCt) { ownerCt.onHeaderResize(this, w); } }, getDesiredWidth: function() { if (this.rendered) { return this.getWidth(); } else { return this.width; } }, getCellSelector: function() { return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.id; } });