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-view-Table'>/**
19 </span> * @class Ext.view.Table
20 * @extends Ext.view.View
22 This class encapsulates the user interface for a tabular data set.
23 It acts as a centralized manager for controlling the various interface
24 elements of the view. This includes handling events, such as row and cell
25 level based DOM events. It also reacts to events from the underlying {@link Ext.selection.Model}
26 to provide visual feedback to the user.
28 This class does not provide ways to manipulate the underlying data of the configured
29 {@link Ext.data.Store}.
31 This is the base class for both {@link Ext.grid.View} and {@link Ext.tree.View} and is not
37 * @author Nicolas Ferrero
39 Ext.define('Ext.view.Table', {
40 extend: 'Ext.view.View',
41 alias: 'widget.tableview',
43 'Ext.view.TableChunker',
44 'Ext.util.DelayedTask',
45 'Ext.util.MixedCollection'
48 cls: Ext.baseCSSPrefix + 'grid-view',
51 itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
53 cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
55 selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
56 selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
57 focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
58 overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
59 altRowCls: Ext.baseCSSPrefix + 'grid-row-alt',
60 rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
61 cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
66 <span id='Ext-view-Table-method-getRowClass'> /**
67 </span> * Override this function to apply custom CSS classes to rows during rendering. You can also supply custom
68 * parameters to the row template for the current row to customize how it is rendered using the <b>rowParams</b>
69 * parameter. This function should return the CSS class name (or empty string '' for none) that will be added
70 * to the row's wrapping div. To apply multiple class names, simply return them space-delimited within the string
71 * (e.g., 'my-class another-class'). Example usage:
72 <pre><code>
75 showPreview: true, // custom property
76 enableRowBody: true, // required to create a second, full-width row to show expanded Record data
77 getRowClass: function(record, rowIndex, rp, ds){ // rp = rowParams
79 rp.body = '&lt;p>'+record.data.excerpt+'&lt;/p>';
80 return 'x-grid3-row-expanded';
82 return 'x-grid3-row-collapsed';
85 </code></pre>
86 * @param {Model} model The {@link Ext.data.Model} corresponding to the current row.
87 * @param {Number} index The row index.
88 * @param {Object} rowParams (DEPRECATED) A config object that is passed to the row template during rendering that allows
89 * customization of various aspects of a grid row.
90 * <p>If {@link #enableRowBody} is configured <b><tt></tt>true</b>, then the following properties may be set
91 * by this function, and will be used to render a full-width expansion row below each grid row:</p>
93 * <li><code>body</code> : String <div class="sub-desc">An HTML fragment to be used as the expansion row's body content (defaults to '').</div></li>
94 * <li><code>bodyStyle</code> : String <div class="sub-desc">A CSS style specification that will be applied to the expansion row's &lt;tr> element. (defaults to '').</div></li>
96 * The following property will be passed in, and may be appended to:
98 * <li><code>tstyle</code> : String <div class="sub-desc">A CSS style specification that willl be applied to the &lt;table> element which encapsulates
99 * both the standard grid row, and any expansion row.</div></li>
101 * @param {Store} store The {@link Ext.data.Store} this grid is bound to
102 * @method getRowClass
103 * @return {String} a CSS class name to add to the row.
107 initComponent: function() {
111 me.selModel.view = me;
112 me.headerCt.view = me;
114 me.tpl = '<div></div>';
117 load: me.onStoreLoad,
124 // * @param {Ext.data.Record} record
125 // * @param {HTMLElement} row
126 // * @param {Number} rowIdx
132 // scroll to top of the grid when store loads
133 onStoreLoad: function(){
136 if (me.invalidateScrollerOnRefresh) {
138 if (!me.scrollToTopTask) {
139 me.scrollToTopTask = Ext.create('Ext.util.DelayedTask', me.scrollToTop, me);
141 me.scrollToTopTask.delay(1);
148 // scroll the view to the top
149 scrollToTop: Ext.emptyFn,
151 <span id='Ext-view-Table-method-addElListener'> /**
152 </span> * Add a listener to the main view element. It will be destroyed with the view.
155 addElListener: function(eventName, fn, scope){
156 this.mon(this, eventName, fn, scope, {
161 <span id='Ext-view-Table-method-getGridColumns'> /**
162 </span> * Get the columns used for generating a template via TableChunker.
163 * See {@link Ext.grid.header.Container#getGridColumns}.
166 getGridColumns: function() {
167 return this.headerCt.getGridColumns();
170 <span id='Ext-view-Table-method-getHeaderAtIndex'> /**
171 </span> * Get a leaf level header by index regardless of what the nesting
174 * @param {Number} index The index
176 getHeaderAtIndex: function(index) {
177 return this.headerCt.getHeaderAtIndex(index);
180 <span id='Ext-view-Table-method-getCell'> /**
181 </span> * Get the cell (td) for a particular record and column.
182 * @param {Ext.data.Model} record
183 * @param {Ext.grid.column.Colunm} column
186 getCell: function(record, column) {
187 var row = this.getNode(record);
188 return Ext.fly(row).down(column.getCellSelector());
191 <span id='Ext-view-Table-method-getFeature'> /**
192 </span> * Get a reference to a feature
193 * @param {String} id The id of the feature
194 * @return {Ext.grid.feature.Feature} The feature. Undefined if not found
196 getFeature: function(id) {
197 var features = this.featuresMC;
199 return features.get(id);
203 <span id='Ext-view-Table-method-initFeatures'> /**
204 </span> * Initializes each feature and bind it to this view.
207 initFeatures: function() {
213 me.features = me.features || [];
214 features = me.features;
215 len = features.length;
217 me.featuresMC = Ext.create('Ext.util.MixedCollection');
218 for (; i < len; i++) {
219 // ensure feature hasnt already been instantiated
220 if (!features[i].isFeature) {
221 features[i] = Ext.create('feature.' + features[i].ftype, features[i]);
223 // inject a reference to view
224 features[i].view = me;
225 me.featuresMC.add(features[i]);
229 <span id='Ext-view-Table-method-attachEventsForFeatures'> /**
230 </span> * Gives features an injection point to attach events to the markup that
231 * has been created for this view.
234 attachEventsForFeatures: function() {
235 var features = this.features,
236 ln = features.length,
239 for (; i < ln; i++) {
240 if (features[i].isFeature) {
241 features[i].attachEvents();
246 afterRender: function() {
251 scroll: me.fireBodyScroll,
254 me.el.unselectable();
255 me.attachEventsForFeatures();
258 fireBodyScroll: function(e, t) {
259 this.fireEvent('bodyscroll', e, t);
262 // TODO: Refactor headerCt dependency here to colModel
263 <span id='Ext-view-Table-method-prepareData'> /**
264 </span> * Uses the headerCt to transform data from dataIndex keys in a record to
265 * headerId keys in each header and then run them through each feature to
266 * get additional data for variables they have injected into the view template.
269 prepareData: function(data, idx, record) {
271 orig = me.headerCt.prepareData(data, idx, record, me, me.ownerCt),
272 features = me.features,
273 ln = features.length,
277 for (; i < ln; i++) {
278 feature = features[i];
279 if (feature.isFeature) {
280 Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, me));
287 // TODO: Refactor headerCt dependency here to colModel
288 collectData: function(records, startIndex) {
289 var preppedRecords = this.callParent(arguments),
290 headerCt = this.headerCt,
291 fullWidth = headerCt.getFullWidth(),
292 features = this.features,
293 ln = features.length,
295 rows: preppedRecords,
304 jln = preppedRecords.length;
305 // process row classes, rowParams has been deprecated and has been moved
306 // to the individual features that implement the behavior.
307 if (this.getRowClass) {
308 for (; j < jln; j++) {
310 preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
313 Ext.Error.raise("The getRowClass alt property is no longer supported.");
315 if (rowParams.tstyle) {
316 Ext.Error.raise("The getRowClass tstyle property is no longer supported.");
318 if (rowParams.cells) {
319 Ext.Error.raise("The getRowClass cells property is no longer supported.");
321 if (rowParams.body) {
322 Ext.Error.raise("The getRowClass body property is no longer supported. Use the getAdditionalData method of the rowbody feature.");
324 if (rowParams.bodyStyle) {
325 Ext.Error.raise("The getRowClass bodyStyle property is no longer supported.");
327 if (rowParams.cols) {
328 Ext.Error.raise("The getRowClass cols property is no longer supported.");
333 // currently only one feature may implement collectData. This is to modify
334 // what's returned to the view before its rendered
335 for (; i < ln; i++) {
336 feature = features[i];
337 if (feature.isFeature && feature.collectData && !feature.disabled) {
338 o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
345 // TODO: Refactor header resizing to column resizing
346 <span id='Ext-view-Table-method-onHeaderResize'> /**
347 </span> * When a header is resized, setWidth on the individual columns resizer class,
348 * the top level table, save/restore scroll state, generate a new template and
349 * restore focus to the grid view's element so that keyboard navigation
353 onHeaderResize: function(header, w, suppressFocus) {
357 me.saveScrollState();
358 // Grab the col and set the width, css
359 // class is generated in TableChunker.
360 // Select composites because there may be several chunks.
361 el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
362 el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(me.headerCt.getFullWidth());
363 me.restoreScrollState();
365 if (!suppressFocus) {
371 <span id='Ext-view-Table-method-onHeaderShow'> /**
372 </span> * When a header is shown restore its oldWidth if it was previously hidden.
375 onHeaderShow: function(headerCt, header, suppressFocus) {
376 // restore headers that were dynamically hidden
377 if (header.oldWidth) {
378 this.onHeaderResize(header, header.oldWidth, suppressFocus);
379 delete header.oldWidth;
380 // flexed headers will have a calculated size set
381 // this additional check has to do with the fact that
382 // defaults: {width: 100} will fight with a flex value
383 } else if (header.width && !header.flex) {
384 this.onHeaderResize(header, header.width, suppressFocus);
386 this.setNewTemplate();
389 <span id='Ext-view-Table-method-onHeaderHide'> /**
390 </span> * When the header hides treat it as a resize to 0.
393 onHeaderHide: function(headerCt, header, suppressFocus) {
394 this.onHeaderResize(header, 0, suppressFocus);
397 <span id='Ext-view-Table-method-setNewTemplate'> /**
398 </span> * Set a new template based on the current columns displayed in the
402 setNewTemplate: function() {
404 columns = me.headerCt.getColumnsForTpl(true);
406 me.tpl = me.getTableChunker().getTableTpl({
408 features: me.features
412 <span id='Ext-view-Table-method-getTableChunker'> /**
413 </span> * Get the configured chunker or default of Ext.view.TableChunker
415 getTableChunker: function() {
416 return this.chunker || Ext.view.TableChunker;
419 <span id='Ext-view-Table-method-addRowCls'> /**
420 </span> * Add a CSS Class to a specific row.
421 * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model representing this row
422 * @param {String} cls
424 addRowCls: function(rowInfo, cls) {
425 var row = this.getNode(rowInfo);
427 Ext.fly(row).addCls(cls);
431 <span id='Ext-view-Table-method-removeRowCls'> /**
432 </span> * Remove a CSS Class from a specific row.
433 * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model representing this row
434 * @param {String} cls
436 removeRowCls: function(rowInfo, cls) {
437 var row = this.getNode(rowInfo);
439 Ext.fly(row).removeCls(cls);
443 // GridSelectionModel invokes onRowSelect as selection changes
444 onRowSelect : function(rowIdx) {
445 this.addRowCls(rowIdx, this.selectedItemCls);
448 // GridSelectionModel invokes onRowDeselect as selection changes
449 onRowDeselect : function(rowIdx) {
452 me.removeRowCls(rowIdx, me.selectedItemCls);
453 me.removeRowCls(rowIdx, me.focusedItemCls);
456 onCellSelect: function(position) {
457 var cell = this.getCellByPosition(position);
459 cell.addCls(this.selectedCellCls);
463 onCellDeselect: function(position) {
464 var cell = this.getCellByPosition(position);
466 cell.removeCls(this.selectedCellCls);
471 onCellFocus: function(position) {
472 //var cell = this.getCellByPosition(position);
473 this.focusCell(position);
476 getCellByPosition: function(position) {
477 var row = position.row,
478 column = position.column,
480 node = this.getNode(row),
481 header = this.headerCt.getHeaderAtIndex(column),
485 if (header && node) {
486 cellSelector = header.getCellSelector();
487 cell = Ext.fly(node).down(cellSelector);
492 // GridSelectionModel invokes onRowFocus to 'highlight'
493 // the last row focused
494 onRowFocus: function(rowIdx, highlight, supressFocus) {
496 row = me.getNode(rowIdx);
499 me.addRowCls(rowIdx, me.focusedItemCls);
503 //this.el.dom.setAttribute('aria-activedescendant', row.id);
505 me.removeRowCls(rowIdx, me.focusedItemCls);
509 <span id='Ext-view-Table-cfg-An'> /**
510 </span> * Focus a particular row and bring it into view. Will fire the rowfocus event.
511 * @cfg {Mixed} An HTMLElement template node, index of a template node, the
512 * id of a template node or the record associated with the node.
514 focusRow: function(rowIdx) {
516 row = me.getNode(rowIdx),
524 if (row && el) {
525 elRegion = el.getRegion();
526 rowRegion = Ext.fly(row).getRegion();
528 if (rowRegion.top < elRegion.top) {
529 adjustment = rowRegion.top - elRegion.top;
531 } else if (rowRegion.bottom > elRegion.bottom) {
532 adjustment = rowRegion.bottom - elRegion.bottom;
534 record = me.getRecord(row);
535 rowIdx = me.store.indexOf(record);
538 // scroll the grid itself, so that all gridview's update.
539 panel.scrollByDeltaY(adjustment);
541 me.fireEvent('rowfocus', record, row, rowIdx);
545 focusCell: function(position) {
547 cell = me.getCellByPosition(position),
551 elRegion = el.getRegion(),
557 cellRegion = cell.getRegion();
559 if (cellRegion.top < elRegion.top) {
560 adjustmentY = cellRegion.top - elRegion.top;
562 } else if (cellRegion.bottom > elRegion.bottom) {
563 adjustmentY = cellRegion.bottom - elRegion.bottom;
567 if (cellRegion.left < elRegion.left) {
568 adjustmentX = cellRegion.left - elRegion.left;
570 } else if (cellRegion.right > elRegion.right) {
571 adjustmentX = cellRegion.right - elRegion.right;
575 // scroll the grid itself, so that all gridview's update.
576 panel.scrollByDeltaY(adjustmentY);
579 panel.scrollByDeltaX(adjustmentX);
582 me.fireEvent('cellfocus', record, cell, position);
586 <span id='Ext-view-Table-method-scrollByDelta'> /**
587 </span> * Scroll by delta. This affects this individual view ONLY and does not
588 * synchronize across views or scrollers.
589 * @param {Number} delta
590 * @param {String} dir (optional) Valid values are scrollTop and scrollLeft. Defaults to scrollTop.
593 scrollByDelta: function(delta, dir) {
594 dir = dir || 'scrollTop';
595 var elDom = this.el.dom;
596 elDom[dir] = (elDom[dir] += delta);
599 onUpdate: function(ds, index) {
600 this.callParent(arguments);
603 <span id='Ext-view-Table-method-saveScrollState'> /**
604 </span> * Save the scrollState in a private variable.
605 * Must be used in conjunction with restoreScrollState
607 saveScrollState: function() {
608 var dom = this.el.dom,
609 state = this.scrollState;
611 state.left = dom.scrollLeft;
612 state.top = dom.scrollTop;
615 <span id='Ext-view-Table-method-restoreScrollState'> /**
616 </span> * Restore the scrollState.
617 * Must be used in conjunction with saveScrollState
620 restoreScrollState: function() {
621 var dom = this.el.dom,
622 state = this.scrollState,
623 headerEl = this.headerCt.el.dom;
625 headerEl.scrollLeft = dom.scrollLeft = state.left;
626 dom.scrollTop = state.top;
629 <span id='Ext-view-Table-method-refresh'> /**
630 </span> * Refresh the grid view.
631 * Saves and restores the scroll state, generates a new template, stripes rows
632 * and invalidates the scrollers.
633 * @param {Boolean} firstPass This is a private flag for internal use only.
635 refresh: function(firstPass) {
639 //this.saveScrollState();
642 me.callParent(arguments);
644 //this.restoreScrollState();
646 if (me.rendered && !firstPass) {
647 // give focus back to gridview
652 processItemEvent: function(record, row, rowIndex, e) {
654 cell = e.getTarget(me.cellSelector, row),
655 cellIndex = cell ? cell.cellIndex : -1,
656 map = me.statics().EventMap,
657 selModel = me.getSelectionModel(),
661 if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
662 // CellModel, otherwise we can't tell which cell to invoke
663 cell = me.getCellByPosition(selModel.getCurrentPosition());
666 cellIndex = cell.cellIndex;
670 result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
672 if (result === false || me.callParent(arguments) === false) {
676 // Don't handle cellmouseenter and cellmouseleave events for now
677 if (type == 'mouseover' || type == 'mouseout') {
682 // We are adding cell and feature events
683 (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
684 (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
685 (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
686 (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
690 processSpecialEvent: function(e) {
692 map = me.statics().EventMap,
693 features = me.features,
694 ln = features.length,
696 i, feature, prefix, featureTarget,
700 me.callParent(arguments);
702 if (type == 'mouseover' || type == 'mouseout') {
706 for (i = 0; i < ln; i++) {
707 feature = features[i];
708 if (feature.hasFeatureEvent) {
709 featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
711 prefix = feature.eventPrefix;
712 // allows features to implement getFireEventArgs to change the
713 // fireEvent signature
714 beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e);
715 args = feature.getFireEventArgs(prefix + type, me, featureTarget, e);
719 (me.fireEvent.apply(me, beforeArgs) === false) ||
721 (panel.fireEvent.apply(panel, beforeArgs) === false) ||
723 (me.fireEvent.apply(me, args) === false) ||
725 (panel.fireEvent.apply(panel, args) === false)
735 onCellMouseDown: Ext.emptyFn,
736 onCellMouseUp: Ext.emptyFn,
737 onCellClick: Ext.emptyFn,
738 onCellDblClick: Ext.emptyFn,
739 onCellContextMenu: Ext.emptyFn,
740 onCellKeyDown: Ext.emptyFn,
741 onBeforeCellMouseDown: Ext.emptyFn,
742 onBeforeCellMouseUp: Ext.emptyFn,
743 onBeforeCellClick: Ext.emptyFn,
744 onBeforeCellDblClick: Ext.emptyFn,
745 onBeforeCellContextMenu: Ext.emptyFn,
746 onBeforeCellKeyDown: Ext.emptyFn,
748 <span id='Ext-view-Table-method-expandToFit'> /**
749 </span> * Expand a particular header to fit the max content width.
750 * This will ONLY expand, not contract.
753 expandToFit: function(header) {
754 var maxWidth = this.getMaxContentWidth(header);
756 header.setWidth(maxWidth);
759 <span id='Ext-view-Table-method-getMaxContentWidth'> /**
760 </span> * Get the max contentWidth of the header's text and all cells
761 * in the grid under this header.
764 getMaxContentWidth: function(header) {
765 var cellSelector = header.getCellInnerSelector(),
766 cells = this.el.query(cellSelector),
769 maxWidth = header.el.dom.scrollWidth,
772 for (; i < ln; i++) {
773 scrollWidth = cells[i].scrollWidth;
774 if (scrollWidth > maxWidth) {
775 maxWidth = scrollWidth;
781 getPositionByEvent: function(e) {
783 cellNode = e.getTarget(me.cellSelector),
784 rowNode = e.getTarget(me.itemSelector),
785 record = me.getRecord(rowNode),
786 header = me.getHeaderByCell(cellNode);
788 return me.getPosition(record, header);
791 getHeaderByCell: function(cell) {
793 var m = cell.className.match(this.cellRe);
794 if (m && m[1]) {
795 return Ext.getCmp(m[1]);
801 <span id='Ext-view-Table-method-walkCells'> /**
802 </span> * @param {Object} position The current row and column: an object containing the following properties:<ul>
803 * <li>row<div class="sub-desc"> The row <b>index</b></div></li>
804 * <li>column<div class="sub-desc">The column <b>index</b></div></li>
806 * @param {String} direction 'up', 'down', 'right' and 'left'
807 * @param {Ext.EventObject} e event
808 * @param {Boolean} preventWrap Set to true to prevent wrap around to the next or previous row.
809 * @param {Function} verifierFn A function to verify the validity of the calculated position. When using this function, you must return true to allow the newPosition to be returned.
810 * @param {Scope} scope Scope to run the verifierFn in
811 * @returns {Object} newPosition An object containing the following properties:<ul>
812 * <li>row<div class="sub-desc"> The row <b>index</b></div></li>
813 * <li>column<div class="sub-desc">The column <b>index</b></div></li>
817 walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
821 rowCount = me.store.getCount(),
822 firstCol = me.getFirstVisibleColumnIndex(),
823 lastCol = me.getLastVisibleColumnIndex(),
824 newPos = {row: row, column: column},
825 activeHeader = me.headerCt.getHeaderAtIndex(column);
827 // no active header or its currently hidden
828 if (!activeHeader || activeHeader.hidden) {
833 direction = direction.toLowerCase();
836 // has the potential to wrap if its last
837 if (column === lastCol) {
838 // if bottom row and last column, deny right
839 if (preventWrap || row === rowCount - 1) {
843 // otherwise wrap to nextRow and firstCol
844 newPos.row = row + 1;
845 newPos.column = firstCol;
850 newPos.column = column + me.getRightGap(activeHeader);
852 newPos.column = lastCol;
858 // has the potential to wrap
859 if (column === firstCol) {
860 // if top row and first column, deny left
861 if (preventWrap || row === 0) {
865 // otherwise wrap to prevRow and lastCol
866 newPos.row = row - 1;
867 newPos.column = lastCol;
872 newPos.column = column + me.getLeftGap(activeHeader);
874 newPos.column = firstCol;
880 // if top row, deny up
886 newPos.row = row - 1;
894 // if bottom row, deny down
895 if (row === rowCount - 1) {
900 newPos.row = row + 1;
902 newPos.row = rowCount - 1;
908 if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
914 getFirstVisibleColumnIndex: function() {
915 var headerCt = this.getHeaderCt(),
916 allColumns = headerCt.getGridColumns(),
917 visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
918 firstHeader = visHeaders[0];
920 return headerCt.getHeaderIndex(firstHeader);
923 getLastVisibleColumnIndex: function() {
924 var headerCt = this.getHeaderCt(),
925 allColumns = headerCt.getGridColumns(),
926 visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
927 lastHeader = visHeaders[visHeaders.length - 1];
929 return headerCt.getHeaderIndex(lastHeader);
932 getHeaderCt: function() {
933 return this.headerCt;
936 getPosition: function(record, header) {
939 gridCols = me.headerCt.getGridColumns();
942 row: store.indexOf(record),
943 column: Ext.Array.indexOf(gridCols, header)
947 <span id='Ext-view-Table-method-getRightGap'> /**
948 </span> * Determines the 'gap' between the closest adjacent header to the right
949 * that is not hidden.
952 getRightGap: function(activeHeader) {
953 var headerCt = this.getHeaderCt(),
954 headers = headerCt.getGridColumns(),
955 activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
956 i = activeHeaderIdx + 1,
959 for (; i <= headers.length; i++) {
960 if (!headers[i].hidden) {
966 return nextIdx - activeHeaderIdx;
969 beforeDestroy: function() {
971 this.el.removeAllListeners();
973 this.callParent(arguments);
976 <span id='Ext-view-Table-method-getLeftGap'> /**
977 </span> * Determines the 'gap' between the closest adjacent header to the left
978 * that is not hidden.
981 getLeftGap: function(activeHeader) {
982 var headerCt = this.getHeaderCt(),
983 headers = headerCt.getGridColumns(),
984 activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
985 i = activeHeaderIdx - 1,
988 for (; i >= 0; i--) {
989 if (!headers[i].hidden) {
995 return prevIdx - activeHeaderIdx;