Column2.html 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-grid-column-Column'>/**
  19. </span> * This class specifies the definition for a column inside a {@link Ext.grid.Panel}. It encompasses
  20. * both the grid header configuration as well as displaying data within the grid itself. If the
  21. * {@link #columns} configuration is specified, this column will become a column group and can
  22. * contain other columns inside. In general, this class will not be created directly, rather
  23. * an array of column configurations will be passed to the grid:
  24. *
  25. * @example
  26. * Ext.create('Ext.data.Store', {
  27. * storeId:'employeeStore',
  28. * fields:['firstname', 'lastname', 'seniority', 'dep', 'hired'],
  29. * data:[
  30. * {firstname:&quot;Michael&quot;, lastname:&quot;Scott&quot;, seniority:7, dep:&quot;Management&quot;, hired:&quot;01/10/2004&quot;},
  31. * {firstname:&quot;Dwight&quot;, lastname:&quot;Schrute&quot;, seniority:2, dep:&quot;Sales&quot;, hired:&quot;04/01/2004&quot;},
  32. * {firstname:&quot;Jim&quot;, lastname:&quot;Halpert&quot;, seniority:3, dep:&quot;Sales&quot;, hired:&quot;02/22/2006&quot;},
  33. * {firstname:&quot;Kevin&quot;, lastname:&quot;Malone&quot;, seniority:4, dep:&quot;Accounting&quot;, hired:&quot;06/10/2007&quot;},
  34. * {firstname:&quot;Angela&quot;, lastname:&quot;Martin&quot;, seniority:5, dep:&quot;Accounting&quot;, hired:&quot;10/21/2008&quot;}
  35. * ]
  36. * });
  37. *
  38. * Ext.create('Ext.grid.Panel', {
  39. * title: 'Column Demo',
  40. * store: Ext.data.StoreManager.lookup('employeeStore'),
  41. * columns: [
  42. * {text: 'First Name', dataIndex:'firstname'},
  43. * {text: 'Last Name', dataIndex:'lastname'},
  44. * {text: 'Hired Month', dataIndex:'hired', xtype:'datecolumn', format:'M'},
  45. * {text: 'Department (Yrs)', xtype:'templatecolumn', tpl:'{dep} ({seniority})'}
  46. * ],
  47. * width: 400,
  48. * forceFit: true,
  49. * renderTo: Ext.getBody()
  50. * });
  51. *
  52. * # Convenience Subclasses
  53. *
  54. * There are several column subclasses that provide default rendering for various data types
  55. *
  56. * - {@link Ext.grid.column.Action}: Renders icons that can respond to click events inline
  57. * - {@link Ext.grid.column.Boolean}: Renders for boolean values
  58. * - {@link Ext.grid.column.Date}: Renders for date values
  59. * - {@link Ext.grid.column.Number}: Renders for numeric values
  60. * - {@link Ext.grid.column.Template}: Renders a value using an {@link Ext.XTemplate} using the record data
  61. *
  62. * # Setting Sizes
  63. *
  64. * The columns are laid out by a {@link Ext.layout.container.HBox} layout, so a column can either
  65. * be given an explicit width value or a flex configuration. If no width is specified the grid will
  66. * automatically the size the column to 100px. For column groups, the size is calculated by measuring
  67. * the width of the child columns, so a width option should not be specified in that case.
  68. *
  69. * # Header Options
  70. *
  71. * - {@link #text}: Sets the header text for the column
  72. * - {@link #sortable}: Specifies whether the column can be sorted by clicking the header or using the column menu
  73. * - {@link #hideable}: Specifies whether the column can be hidden using the column menu
  74. * - {@link #menuDisabled}: Disables the column header menu
  75. * - {@link #cfg-draggable}: Specifies whether the column header can be reordered by dragging
  76. * - {@link #groupable}: Specifies whether the grid can be grouped by the column dataIndex. See also {@link Ext.grid.feature.Grouping}
  77. *
  78. * # Data Options
  79. *
  80. * - {@link #dataIndex}: The dataIndex is the field in the underlying {@link Ext.data.Store} to use as the value for the column.
  81. * - {@link #renderer}: Allows the underlying store value to be transformed before being displayed in the grid
  82. */
  83. Ext.define('Ext.grid.column.Column', {
  84. extend: 'Ext.grid.header.Container',
  85. alias: 'widget.gridcolumn',
  86. requires: ['Ext.util.KeyNav', 'Ext.grid.ColumnComponentLayout', 'Ext.grid.ColumnLayout'],
  87. alternateClassName: 'Ext.grid.Column',
  88. baseCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable',
  89. // Not the standard, automatically applied overCls because we must filter out overs of child headers.
  90. hoverCls: Ext.baseCSSPrefix + 'column-header-over',
  91. handleWidth: 5,
  92. sortState: null,
  93. possibleSortStates: ['ASC', 'DESC'],
  94. childEls: [
  95. 'titleEl', 'triggerEl', 'textEl'
  96. ],
  97. renderTpl:
  98. '&lt;div id=&quot;{id}-titleEl&quot; {tipMarkup}class=&quot;' + Ext.baseCSSPrefix + 'column-header-inner&quot;&gt;' +
  99. '&lt;span id=&quot;{id}-textEl&quot; class=&quot;' + Ext.baseCSSPrefix + 'column-header-text&quot;&gt;' +
  100. '{text}' +
  101. '&lt;/span&gt;' +
  102. '&lt;tpl if=&quot;!menuDisabled&quot;&gt;'+
  103. '&lt;div id=&quot;{id}-triggerEl&quot; class=&quot;' + Ext.baseCSSPrefix + 'column-header-trigger&quot;&gt;&lt;/div&gt;'+
  104. '&lt;/tpl&gt;' +
  105. '&lt;/div&gt;' +
  106. '{%this.renderContainer(out,values)%}',
  107. <span id='Ext-grid-column-Column-cfg-columns'> /**
  108. </span> * @cfg {Object[]} columns
  109. * An optional array of sub-column definitions. This column becomes a group, and houses the columns defined in the
  110. * `columns` config.
  111. *
  112. * Group columns may not be sortable. But they may be hideable and moveable. And you may move headers into and out
  113. * of a group. Note that if all sub columns are dragged out of a group, the group is destroyed.
  114. */
  115. <span id='Ext-grid-column-Column-cfg-stateId'> /**
  116. </span> * @override
  117. * @cfg {String} stateId
  118. * An identifier which identifies this column uniquely within the owning grid's {@link #stateful state}.
  119. *
  120. * This does not have to be *globally* unique. A column's state is not saved standalone. It is encapsulated within
  121. * the owning grid's state.
  122. */
  123. <span id='Ext-grid-column-Column-cfg-dataIndex'> /**
  124. </span> * @cfg {String} dataIndex
  125. * The name of the field in the grid's {@link Ext.data.Store}'s {@link Ext.data.Model} definition from
  126. * which to draw the column's value. **Required.**
  127. */
  128. dataIndex: null,
  129. <span id='Ext-grid-column-Column-cfg-text'> /**
  130. </span> * @cfg {String} text
  131. * The header text to be used as innerHTML (html tags are accepted) to display in the Grid.
  132. * **Note**: to have a clickable header with no text displayed you can use the default of `&amp;#160;` aka `&amp;nbsp;`.
  133. */
  134. text: '&amp;#160;',
  135. <span id='Ext-grid-column-Column-cfg-header'> /**
  136. </span> * @cfg {String} header
  137. * The header text.
  138. * @deprecated 4.0 Use {@link #text} instead.
  139. */
  140. <span id='Ext-grid-column-Column-cfg-menuText'> /**
  141. </span> * @cfg {String} menuText
  142. * The text to render in the column visibility selection menu for this column. If not
  143. * specified, will default to the text value.
  144. */
  145. menuText: null,
  146. <span id='Ext-grid-column-Column-cfg-emptyCellText'> /**
  147. </span> * @cfg {String} [emptyCellText=undefined]
  148. * The text to diplay in empty cells (cells with a value of `undefined`, `null`, or `''`).
  149. *
  150. * Defaults to `&amp;#160;` aka `&amp;nbsp;`.
  151. */
  152. emptyCellText: '&amp;#160;',
  153. <span id='Ext-grid-column-Column-cfg-sortable'> /**
  154. </span> * @cfg {Boolean} sortable
  155. * False to disable sorting of this column. Whether local/remote sorting is used is specified in
  156. * `{@link Ext.data.Store#remoteSort}`.
  157. */
  158. sortable: true,
  159. <span id='Ext-grid-column-Column-cfg-groupable'> /**
  160. </span> * @cfg {Boolean} groupable
  161. * If the grid uses a {@link Ext.grid.feature.Grouping}, this option may be used to disable the header menu
  162. * item to group by the column selected. By default, the header menu group option is enabled. Set to false to
  163. * disable (but still show) the group option in the header menu for the column.
  164. */
  165. <span id='Ext-grid-column-Column-cfg-fixed'> /**
  166. </span> * @cfg {Boolean} fixed
  167. * True to prevent the column from being resizable.
  168. * @deprecated 4.0 Use {@link #resizable} instead.
  169. */
  170. <span id='Ext-grid-column-Column-cfg-locked'> /**
  171. </span> * @cfg {Boolean} [locked=false]
  172. * True to lock this column in place. Implicitly enables locking on the grid.
  173. * See also {@link Ext.grid.Panel#enableLocking}.
  174. */
  175. <span id='Ext-grid-column-Column-cfg-resizable'> /**
  176. </span> * @cfg {Boolean} resizable
  177. * False to prevent the column from being resizable.
  178. */
  179. resizable: true,
  180. <span id='Ext-grid-column-Column-cfg-hideable'> /**
  181. </span> * @cfg {Boolean} hideable
  182. * False to prevent the user from hiding this column.
  183. */
  184. hideable: true,
  185. <span id='Ext-grid-column-Column-cfg-menuDisabled'> /**
  186. </span> * @cfg {Boolean} menuDisabled
  187. * True to disable the column header menu containing sort/hide options.
  188. */
  189. menuDisabled: false,
  190. <span id='Ext-grid-column-Column-cfg-renderer'> /**
  191. </span> * @cfg {Function/String} renderer
  192. * A renderer is an 'interceptor' method which can be used to transform data (value, appearance, etc.)
  193. * before it is rendered. Example:
  194. *
  195. * {
  196. * renderer: function(value){
  197. * if (value === 1) {
  198. * return '1 person';
  199. * }
  200. * return value + ' people';
  201. * }
  202. * }
  203. *
  204. * Additionally a string naming an {@link Ext.util.Format} method can be passed:
  205. *
  206. * {
  207. * renderer: 'uppercase'
  208. * }
  209. *
  210. * @cfg {Object} renderer.value The data value for the current cell
  211. * @cfg {Object} renderer.metaData A collection of metadata about the current cell; can be used or modified
  212. * by the renderer. Recognized properties are: tdCls, tdAttr, and style.
  213. * @cfg {Ext.data.Model} renderer.record The record for the current row
  214. * @cfg {Number} renderer.rowIndex The index of the current row
  215. * @cfg {Number} renderer.colIndex The index of the current column
  216. * @cfg {Ext.data.Store} renderer.store The data store
  217. * @cfg {Ext.view.View} renderer.view The current view
  218. * @cfg {String} renderer.return The HTML string to be rendered.
  219. */
  220. renderer: false,
  221. <span id='Ext-grid-column-Column-cfg-scope'> /**
  222. </span> * @cfg {Object} scope
  223. * The scope to use when calling the {@link #renderer} function.
  224. */
  225. <span id='Ext-grid-column-Column-method-defaultRenderer'> /**
  226. </span> * @method defaultRenderer
  227. * When defined this will take precedence over the {@link Ext.grid.column.Column#renderer renderer} config.
  228. * This is meant to be defined in subclasses that wish to supply their own renderer.
  229. * @protected
  230. * @template
  231. */
  232. <span id='Ext-grid-column-Column-cfg-editRenderer'> /**
  233. </span> * @cfg {Function} editRenderer
  234. * A renderer to be used in conjunction with {@link Ext.grid.plugin.RowEditing RowEditing}. This renderer is used to
  235. * display a custom value for non-editable fields.
  236. */
  237. editRenderer: false,
  238. <span id='Ext-grid-column-Column-cfg-align'> /**
  239. </span> * @cfg {String} align
  240. * Sets the alignment of the header and rendered columns.
  241. * Possible values are: `'left'`, `'center'`, and `'right'`.
  242. */
  243. align: 'left',
  244. <span id='Ext-grid-column-Column-cfg-draggable'> /**
  245. </span> * @cfg {Boolean} draggable
  246. * False to disable drag-drop reordering of this column.
  247. */
  248. draggable: true,
  249. <span id='Ext-grid-column-Column-cfg-tooltip'> /**
  250. </span> * @cfg {String} tooltip
  251. * A tooltip to display for this column header
  252. */
  253. <span id='Ext-grid-column-Column-cfg-tooltipType'> /**
  254. </span> * @cfg {String} [tooltipType=&quot;qtip&quot;]
  255. * The type of {@link #tooltip} to use. Either 'qtip' for QuickTips or 'title' for title attribute.
  256. */
  257. tooltipType: 'qtip',
  258. // Header does not use the typical ComponentDraggable class and therefore we
  259. // override this with an emptyFn. It is controlled at the HeaderDragZone.
  260. initDraggable: Ext.emptyFn,
  261. <span id='Ext-grid-column-Column-cfg-tdCls'> /**
  262. </span> * @cfg {String} tdCls
  263. * A CSS class names to apply to the table cells for this column.
  264. */
  265. <span id='Ext-grid-column-Column-cfg-editor'> /**
  266. </span> * @cfg {Object/String} editor
  267. * An optional xtype or config object for a {@link Ext.form.field.Field Field} to use for editing.
  268. * Only applicable if the grid is using an {@link Ext.grid.plugin.Editing Editing} plugin.
  269. */
  270. <span id='Ext-grid-column-Column-cfg-field'> /**
  271. </span> * @cfg {Object/String} field
  272. * Alias for {@link #editor}.
  273. * @deprecated 4.0.5 Use {@link #editor} instead.
  274. */
  275. <span id='Ext-grid-column-Column-property-triggerEl'> /**
  276. </span> * @property {Ext.Element} triggerEl
  277. * Element that acts as button for column header dropdown menu.
  278. */
  279. <span id='Ext-grid-column-Column-property-textEl'> /**
  280. </span> * @property {Ext.Element} textEl
  281. * Element that contains the text in column header.
  282. */
  283. <span id='Ext-grid-column-Column-property-isHeader'> /**
  284. </span> * @property {Boolean} isHeader
  285. * Set in this class to identify, at runtime, instances which are not instances of the
  286. * HeaderContainer base class, but are in fact, the subclass: Header.
  287. */
  288. isHeader: true,
  289. componentLayout: 'columncomponent',
  290. // We need to override the default component resizable behaviour here
  291. initResizable: Ext.emptyFn,
  292. initComponent: function() {
  293. var me = this,
  294. renderer;
  295. if (Ext.isDefined(me.header)) {
  296. me.text = me.header;
  297. delete me.header;
  298. }
  299. if (!me.triStateSort) {
  300. me.possibleSortStates.length = 2;
  301. }
  302. // A group header; It contains items which are themselves Headers
  303. if (Ext.isDefined(me.columns)) {
  304. me.isGroupHeader = true;
  305. //&lt;debug&gt;
  306. if (me.dataIndex) {
  307. Ext.Error.raise('Ext.grid.column.Column: Group header may not accept a dataIndex');
  308. }
  309. if ((me.width &amp;&amp; me.width !== Ext.grid.header.Container.prototype.defaultWidth) || me.flex) {
  310. Ext.Error.raise('Ext.grid.column.Column: Group header does not support setting explicit widths or flexs. The group header width is calculated by the sum of its children.');
  311. }
  312. //&lt;/debug&gt;
  313. // The headers become child items
  314. me.items = me.columns;
  315. delete me.columns;
  316. delete me.flex;
  317. delete me.width;
  318. me.cls = (me.cls||'') + ' ' + Ext.baseCSSPrefix + 'group-header';
  319. me.sortable = false;
  320. me.resizable = false;
  321. me.align = 'center';
  322. } else {
  323. // If we are not a group header, then this is not to be used as a container, and must not have a container layout executed, and it must
  324. // acquire layout height from DOM content, not from child items.
  325. me.isContainer = false;
  326. // Flexed Headers need to have a minWidth defined so that they can never be squeezed out of existence by the
  327. // HeaderContainer's specialized Box layout, the ColumnLayout. The ColumnLayout's overridden calculateChildboxes
  328. // method extends the available layout space to accommodate the &quot;desiredWidth&quot; of all the columns.
  329. if (me.flex) {
  330. me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
  331. }
  332. }
  333. me.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align);
  334. renderer = me.renderer;
  335. if (renderer) {
  336. // When specifying a renderer as a string, it always resolves
  337. // to Ext.util.Format
  338. if (typeof renderer == 'string') {
  339. me.renderer = Ext.util.Format[renderer];
  340. }
  341. me.hasCustomRenderer = true;
  342. } else if (me.defaultRenderer) {
  343. me.scope = me;
  344. me.renderer = me.defaultRenderer;
  345. }
  346. // Initialize as a HeaderContainer
  347. me.callParent(arguments);
  348. me.on({
  349. element: 'el',
  350. click: me.onElClick,
  351. dblclick: me.onElDblClick,
  352. scope: me
  353. });
  354. me.on({
  355. element: 'titleEl',
  356. mouseenter: me.onTitleMouseOver,
  357. mouseleave: me.onTitleMouseOut,
  358. scope: me
  359. });
  360. },
  361. onAdd: function(childHeader) {
  362. childHeader.isSubHeader = true;
  363. childHeader.addCls(Ext.baseCSSPrefix + 'group-sub-header');
  364. this.callParent(arguments);
  365. },
  366. onRemove: function(childHeader) {
  367. childHeader.isSubHeader = false;
  368. childHeader.removeCls(Ext.baseCSSPrefix + 'group-sub-header');
  369. this.callParent(arguments);
  370. },
  371. initRenderData: function() {
  372. var me = this,
  373. tipMarkup = '',
  374. tip = me.tooltip,
  375. attr = me.tooltipType == 'qtip' ? 'data-qtip' : 'title';
  376. if (!Ext.isEmpty(tip)) {
  377. tipMarkup = attr + '=&quot;' + tip + '&quot; ';
  378. }
  379. return Ext.applyIf(me.callParent(arguments), {
  380. text: me.text,
  381. menuDisabled: me.menuDisabled,
  382. tipMarkup: tipMarkup
  383. });
  384. },
  385. applyColumnState: function (state) {
  386. var me = this,
  387. defined = Ext.isDefined;
  388. // apply any columns
  389. me.applyColumnsState(state.columns);
  390. // Only state properties which were saved should be restored.
  391. // (Only user-changed properties were saved by getState)
  392. if (defined(state.hidden)) {
  393. me.hidden = state.hidden;
  394. }
  395. if (defined(state.locked)) {
  396. me.locked = state.locked;
  397. }
  398. if (defined(state.sortable)) {
  399. me.sortable = state.sortable;
  400. }
  401. if (defined(state.width)) {
  402. delete me.flex;
  403. me.width = state.width;
  404. } else if (defined(state.flex)) {
  405. delete me.width;
  406. me.flex = state.flex;
  407. }
  408. },
  409. getColumnState: function () {
  410. var me = this,
  411. items = me.items.items,
  412. // Check for the existence of items, since column.Action won't have them
  413. iLen = items ? items.length : 0,
  414. i,
  415. columns = [],
  416. state = {
  417. id: me.getStateId()
  418. };
  419. me.savePropsToState(['hidden', 'sortable', 'locked', 'flex', 'width'], state);
  420. if (me.isGroupHeader) {
  421. for (i = 0; i &lt; iLen; i++) {
  422. columns.push(items[i].getColumnState());
  423. }
  424. if (columns.length) {
  425. state.columns = columns;
  426. }
  427. } else if (me.isSubHeader &amp;&amp; me.ownerCt.hidden) {
  428. // don't set hidden on the children so they can auto height
  429. delete me.hidden;
  430. }
  431. if ('width' in state) {
  432. delete state.flex; // width wins
  433. }
  434. return state;
  435. },
  436. getStateId: function () {
  437. return this.stateId || this.headerId;
  438. },
  439. <span id='Ext-grid-column-Column-method-setText'> /**
  440. </span> * Sets the header text for this Column.
  441. * @param {String} text The header to display on this Column.
  442. */
  443. setText: function(text) {
  444. this.text = text;
  445. if (this.rendered) {
  446. this.textEl.update(text);
  447. }
  448. },
  449. // Find the topmost HeaderContainer: An ancestor which is NOT a Header.
  450. // Group Headers are themselves HeaderContainers
  451. getOwnerHeaderCt: function() {
  452. return this.up(':not([isHeader])');
  453. },
  454. <span id='Ext-grid-column-Column-method-getIndex'> /**
  455. </span> * Returns the index of this column only if this column is a base level Column. If it
  456. * is a group column, it returns `false`.
  457. * @return {Number}
  458. */
  459. getIndex: function() {
  460. return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this);
  461. },
  462. <span id='Ext-grid-column-Column-method-getVisibleIndex'> /**
  463. </span> * Returns the index of this column in the list of *visible* columns only if this column is a base level Column. If it
  464. * is a group column, it returns `false`.
  465. * @return {Number}
  466. */
  467. getVisibleIndex: function() {
  468. return this.isGroupColumn ? false : Ext.Array.indexOf(this.getOwnerHeaderCt().getVisibleGridColumns(), this);
  469. },
  470. beforeRender: function() {
  471. var me = this,
  472. grid = me.up('tablepanel');
  473. me.callParent();
  474. // Disable the menu if there's nothing to show in the menu, ie:
  475. // Column cannot be sorted, grouped or locked, and there are no grid columns which may be hidden
  476. if (grid &amp;&amp; (!me.sortable || grid.sortableColumns === false) &amp;&amp; !me.groupable &amp;&amp;
  477. !me.lockable &amp;&amp; (grid.enableColumnHide === false ||
  478. !me.getOwnerHeaderCt().getHideableColumns().length)) {
  479. me.menuDisabled = true;
  480. }
  481. },
  482. afterRender: function() {
  483. var me = this,
  484. el = me.el;
  485. me.callParent(arguments);
  486. if (me.overCls) {
  487. el.addClsOnOver(me.overCls);
  488. }
  489. // BrowserBug: Ie8 Strict Mode, this will break the focus for this browser,
  490. // must be fixed when focus management will be implemented.
  491. if (!Ext.isIE8 || !Ext.isStrict) {
  492. me.mon(me.getFocusEl(), {
  493. focus: me.onTitleMouseOver,
  494. blur: me.onTitleMouseOut,
  495. scope: me
  496. });
  497. }
  498. me.keyNav = new Ext.util.KeyNav(el, {
  499. enter: me.onEnterKey,
  500. down: me.onDownKey,
  501. scope: me
  502. });
  503. },
  504. // private
  505. // Inform the header container about the resize
  506. afterComponentLayout: function(width, height, oldWidth, oldHeight) {
  507. var me = this,
  508. ownerHeaderCt = me.getOwnerHeaderCt();
  509. me.callParent(arguments);
  510. if (ownerHeaderCt &amp;&amp; (oldWidth != null || me.flex) &amp;&amp; width !== oldWidth) {
  511. ownerHeaderCt.onHeaderResize(me, width, true);
  512. }
  513. },
  514. // private
  515. // After the container has laid out and stretched, it calls this to correctly pad the inner to center the text vertically
  516. // Total available header height must be passed to enable padding for inner elements to be calculated.
  517. setPadding: function(headerHeight) {
  518. var me = this,
  519. lineHeight = parseInt(me.textEl.getStyle('line-height'), 10),
  520. textHeight = me.textEl.dom.offsetHeight,
  521. titleEl = me.titleEl,
  522. availableHeight = headerHeight - me.el.getBorderWidth('tb'),
  523. titleElHeight;
  524. // Top title containing element must stretch to match height of sibling group headers
  525. if (!me.isGroupHeader) {
  526. if (titleEl.getHeight() &lt; availableHeight) {
  527. titleEl.setHeight(availableHeight);
  528. // the column el's parent element (the 'innerCt') may have an incorrect height
  529. // at this point because it may have been shrink wrapped prior to the titleEl's
  530. // height being set, so we need to sync it up here
  531. me.ownerCt.layout.innerCt.setHeight(headerHeight);
  532. }
  533. }
  534. titleElHeight = titleEl.getViewSize().height;
  535. // Vertically center the header text in potentially vertically stretched header
  536. if (textHeight) {
  537. if(lineHeight) {
  538. textHeight = Math.ceil(textHeight / lineHeight) * lineHeight;
  539. }
  540. titleEl.setStyle({
  541. paddingTop: Math.floor(Math.max(((titleElHeight - textHeight) / 2), 0)) + 'px'
  542. });
  543. }
  544. // Only IE needs this
  545. if (Ext.isIE &amp;&amp; me.triggerEl) {
  546. me.triggerEl.setHeight(titleElHeight);
  547. }
  548. },
  549. onDestroy: function() {
  550. var me = this;
  551. // force destroy on the textEl, IE reports a leak
  552. Ext.destroy(me.textEl, me.keyNav, me.field);
  553. delete me.keyNav;
  554. me.callParent(arguments);
  555. },
  556. onTitleMouseOver: function() {
  557. this.titleEl.addCls(this.hoverCls);
  558. },
  559. onTitleMouseOut: function() {
  560. this.titleEl.removeCls(this.hoverCls);
  561. },
  562. onDownKey: function(e) {
  563. if (this.triggerEl) {
  564. this.onElClick(e, this.triggerEl.dom || this.el.dom);
  565. }
  566. },
  567. onEnterKey: function(e) {
  568. this.onElClick(e, this.el.dom);
  569. },
  570. <span id='Ext-grid-column-Column-method-onElDblClick'> /**
  571. </span> * @private
  572. * Double click
  573. * @param e
  574. * @param t
  575. */
  576. onElDblClick: function(e, t) {
  577. var me = this,
  578. ownerCt = me.ownerCt;
  579. if (ownerCt &amp;&amp; Ext.Array.indexOf(ownerCt.items, me) !== 0 &amp;&amp; me.isOnLeftEdge(e) ) {
  580. ownerCt.expandToFit(me.previousSibling('gridcolumn'));
  581. }
  582. },
  583. onElClick: function(e, t) {
  584. // The grid's docked HeaderContainer.
  585. var me = this,
  586. ownerHeaderCt = me.getOwnerHeaderCt();
  587. if (ownerHeaderCt &amp;&amp; !ownerHeaderCt.ddLock) {
  588. // Firefox doesn't check the current target in a within check.
  589. // Therefore we check the target directly and then within (ancestors)
  590. if (me.triggerEl &amp;&amp; (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) {
  591. ownerHeaderCt.onHeaderTriggerClick(me, e, t);
  592. // if its not on the left hand edge, sort
  593. } else if (e.getKey() || (!me.isOnLeftEdge(e) &amp;&amp; !me.isOnRightEdge(e))) {
  594. me.toggleSortState();
  595. ownerHeaderCt.onHeaderClick(me, e, t);
  596. }
  597. }
  598. },
  599. <span id='Ext-grid-column-Column-method-processEvent'> /**
  600. </span> * @private
  601. * Process UI events from the view. The owning TablePanel calls this method, relaying events from the TableView
  602. * @param {String} type Event type, eg 'click'
  603. * @param {Ext.view.Table} view TableView Component
  604. * @param {HTMLElement} cell Cell HtmlElement the event took place within
  605. * @param {Number} recordIndex Index of the associated Store Model (-1 if none)
  606. * @param {Number} cellIndex Cell index within the row
  607. * @param {Ext.EventObject} e Original event
  608. */
  609. processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
  610. return this.fireEvent.apply(this, arguments);
  611. },
  612. toggleSortState: function() {
  613. var me = this,
  614. idx,
  615. nextIdx;
  616. if (me.sortable) {
  617. idx = Ext.Array.indexOf(me.possibleSortStates, me.sortState);
  618. nextIdx = (idx + 1) % me.possibleSortStates.length;
  619. me.setSortState(me.possibleSortStates[nextIdx]);
  620. }
  621. },
  622. doSort: function(state) {
  623. var ds = this.up('tablepanel').store;
  624. ds.sort({
  625. property: this.getSortParam(),
  626. direction: state
  627. });
  628. },
  629. <span id='Ext-grid-column-Column-method-getSortParam'> /**
  630. </span> * Returns the parameter to sort upon when sorting this header. By default this returns the dataIndex and will not
  631. * need to be overriden in most cases.
  632. * @return {String}
  633. */
  634. getSortParam: function() {
  635. return this.dataIndex;
  636. },
  637. //setSortState: function(state, updateUI) {
  638. //setSortState: function(state, doSort) {
  639. setSortState: function(state, skipClear, initial) {
  640. var me = this,
  641. colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-',
  642. ascCls = colSortClsPrefix + 'ASC',
  643. descCls = colSortClsPrefix + 'DESC',
  644. nullCls = colSortClsPrefix + 'null',
  645. ownerHeaderCt = me.getOwnerHeaderCt(),
  646. oldSortState = me.sortState;
  647. if (oldSortState !== state &amp;&amp; me.getSortParam()) {
  648. me.addCls(colSortClsPrefix + state);
  649. // don't trigger a sort on the first time, we just want to update the UI
  650. if (state &amp;&amp; !initial) {
  651. me.doSort(state);
  652. }
  653. switch (state) {
  654. case 'DESC':
  655. me.removeCls([ascCls, nullCls]);
  656. break;
  657. case 'ASC':
  658. me.removeCls([descCls, nullCls]);
  659. break;
  660. case null:
  661. me.removeCls([ascCls, descCls]);
  662. break;
  663. }
  664. if (ownerHeaderCt &amp;&amp; !me.triStateSort &amp;&amp; !skipClear) {
  665. ownerHeaderCt.clearOtherSortStates(me);
  666. }
  667. me.sortState = state;
  668. // we only want to fire the event if we have a null state when using triStateSort
  669. if (me.triStateSort || state != null) {
  670. ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state);
  671. }
  672. }
  673. },
  674. hide: function(fromOwner) {
  675. var me = this,
  676. ownerHeaderCt = me.getOwnerHeaderCt(),
  677. owner = me.ownerCt,
  678. ownerIsGroup = owner.isGroupHeader,
  679. item, items, len, i;
  680. // owner is a group, hide call didn't come from the owner
  681. if (ownerIsGroup &amp;&amp; !fromOwner) {
  682. items = owner.query('&gt;:not([hidden])');
  683. // only have one item that isn't hidden, this is it.
  684. if (items.length === 1 &amp;&amp; items[0] == me) {
  685. me.ownerCt.hide();
  686. return;
  687. }
  688. }
  689. Ext.suspendLayouts();
  690. if (me.isGroupHeader) {
  691. items = me.items.items;
  692. for (i = 0, len = items.length; i &lt; len; i++) {
  693. item = items[i];
  694. if (!item.hidden) {
  695. item.hide(true);
  696. }
  697. }
  698. }
  699. me.callParent();
  700. // Notify owning HeaderContainer
  701. ownerHeaderCt.onHeaderHide(me);
  702. Ext.resumeLayouts(true);
  703. },
  704. show: function(fromOwner, fromChild) {
  705. var me = this,
  706. ownerCt = me.ownerCt,
  707. items,
  708. len, i,
  709. item;
  710. Ext.suspendLayouts();
  711. // If a sub header, ensure that the group header is visible
  712. if (me.isSubHeader &amp;&amp; ownerCt.hidden) {
  713. ownerCt.show(false, true);
  714. }
  715. me.callParent(arguments);
  716. // If we've just shown a group with all its sub headers hidden, then show all its sub headers
  717. if (me.isGroupHeader &amp;&amp; fromChild !== true &amp;&amp; !me.query(':not([hidden])').length) {
  718. items = me.query('&gt;*');
  719. for (i = 0, len = items.length; i &lt; len; i++) {
  720. item = items[i];
  721. if (item.hidden) {
  722. item.show(true);
  723. }
  724. }
  725. }
  726. Ext.resumeLayouts(true);
  727. // Notify owning HeaderContainer AFTER layout has been flushed so that header and headerCt widths are all correct
  728. ownerCt = me.getOwnerHeaderCt();
  729. if (ownerCt) {
  730. ownerCt.onHeaderShow(me);
  731. }
  732. },
  733. getDesiredWidth: function() {
  734. var me = this;
  735. if (me.rendered &amp;&amp; me.componentLayout &amp;&amp; me.componentLayout.lastComponentSize) {
  736. // headers always have either a width or a flex
  737. // because HeaderContainer sets a defaults width
  738. // therefore we can ignore the natural width
  739. // we use the componentLayout's tracked width so that
  740. // we can calculate the desired width when rendered
  741. // but not visible because its being obscured by a layout
  742. return me.componentLayout.lastComponentSize.width;
  743. // Flexed but yet to be rendered this could be the case
  744. // where a HeaderContainer and Headers are simply used as data
  745. // structures and not rendered.
  746. }
  747. else if (me.flex) {
  748. // this is going to be wrong, the defaultWidth
  749. return me.width;
  750. }
  751. else {
  752. return me.width;
  753. }
  754. },
  755. getCellSelector: function() {
  756. return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.getItemId();
  757. },
  758. getCellInnerSelector: function() {
  759. return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner';
  760. },
  761. isOnLeftEdge: function(e) {
  762. return (e.getXY()[0] - this.el.getLeft() &lt;= this.handleWidth);
  763. },
  764. isOnRightEdge: function(e) {
  765. return (this.el.getRight() - e.getXY()[0] &lt;= this.handleWidth);
  766. }
  767. // intentionally omit getEditor and setEditor definitions bc we applyIf into columns
  768. // when the editing plugin is injected
  769. <span id='Ext-grid-column-Column-method-getEditor'> /**
  770. </span> * @method getEditor
  771. * Retrieves the editing field for editing associated with this header. Returns false if there is no field
  772. * associated with the Header the method will return false. If the field has not been instantiated it will be
  773. * created. Note: These methods only has an implementation if a Editing plugin has been enabled on the grid.
  774. * @param {Object} record The {@link Ext.data.Model Model} instance being edited.
  775. * @param {Object} defaultField An object representing a default field to be created
  776. * @return {Ext.form.field.Field} field
  777. */
  778. <span id='Ext-grid-column-Column-method-setEditor'> /**
  779. </span> * @method setEditor
  780. * Sets the form field to be used for editing. Note: This method only has an implementation if an Editing plugin has
  781. * been enabled on the grid.
  782. * @param {Object} field An object representing a field to be created. If no xtype is specified a 'textfield' is
  783. * assumed.
  784. */
  785. });
  786. </pre>
  787. </body>
  788. </html>