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
36 * @author Nicolas Ferrero
38 Ext.define('Ext.view.Table', {
39 extend: 'Ext.view.View',
40 alias: 'widget.tableview',
42 'Ext.view.TableChunker',
43 'Ext.util.DelayedTask',
44 'Ext.util.MixedCollection'
47 cls: Ext.baseCSSPrefix + 'grid-view',
50 itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
52 cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
54 selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
55 selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
56 focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
57 overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
58 altRowCls: Ext.baseCSSPrefix + 'grid-row-alt',
59 rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
60 cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
65 <span id='Ext-view-Table-method-getRowClass'> /**
66 </span> * Override this function to apply custom CSS classes to rows during rendering. You can also supply custom
67 * parameters to the row template for the current row to customize how it is rendered using the <b>rowParams</b>
68 * parameter. This function should return the CSS class name (or empty string '' for none) that will be added
69 * to the row's wrapping div. To apply multiple class names, simply return them space-delimited within the string
70 * (e.g., 'my-class another-class'). Example usage:
71 <pre><code>
74 showPreview: true, // custom property
75 enableRowBody: true, // required to create a second, full-width row to show expanded Record data
76 getRowClass: function(record, rowIndex, rp, ds){ // rp = rowParams
78 rp.body = '&lt;p>'+record.data.excerpt+'&lt;/p>';
79 return 'x-grid3-row-expanded';
81 return 'x-grid3-row-collapsed';
84 </code></pre>
85 * @param {Model} model The {@link Ext.data.Model} corresponding to the current row.
86 * @param {Number} index The row index.
87 * @param {Object} rowParams (DEPRECATED) A config object that is passed to the row template during rendering that allows
88 * customization of various aspects of a grid row.
89 * <p>If {@link #enableRowBody} is configured <b><tt></tt>true</b>, then the following properties may be set
90 * by this function, and will be used to render a full-width expansion row below each grid row:</p>
92 * <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>
93 * <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>
95 * The following property will be passed in, and may be appended to:
97 * <li><code>tstyle</code> : String <div class="sub-desc">A CSS style specification that willl be applied to the &lt;table> element which encapsulates
98 * both the standard grid row, and any expansion row.</div></li>
100 * @param {Store} store The {@link Ext.data.Store} this grid is bound to
101 * @method getRowClass
102 * @return {String} a CSS class name to add to the row.
106 initComponent: function() {
109 if (me.deferRowRender !== false) {
110 me.refresh = function() {
112 setTimeout(function() {
119 me.selModel.view = me;
120 me.headerCt.view = me;
122 me.tpl = '<div></div>';
125 load: me.onStoreLoad,
132 // * @param {Ext.data.Record} record
133 // * @param {HTMLElement} row
134 // * @param {Number} rowIdx
140 // scroll to top of the grid when store loads
141 onStoreLoad: function(){
144 if (me.invalidateScrollerOnRefresh) {
146 if (!me.scrollToTopTask) {
147 me.scrollToTopTask = Ext.create('Ext.util.DelayedTask', me.scrollToTop, me);
149 me.scrollToTopTask.delay(1);
156 // scroll the view to the top
157 scrollToTop: Ext.emptyFn,
159 <span id='Ext-view-Table-method-addElListener'> /**
160 </span> * Add a listener to the main view element. It will be destroyed with the view.
163 addElListener: function(eventName, fn, scope){
164 this.mon(this, eventName, fn, scope, {
169 <span id='Ext-view-Table-method-getGridColumns'> /**
170 </span> * Get the columns used for generating a template via TableChunker.
171 * See {@link Ext.grid.header.Container#getGridColumns}.
174 getGridColumns: function() {
175 return this.headerCt.getGridColumns();
178 <span id='Ext-view-Table-method-getHeaderAtIndex'> /**
179 </span> * Get a leaf level header by index regardless of what the nesting
182 * @param {Number} index The index
184 getHeaderAtIndex: function(index) {
185 return this.headerCt.getHeaderAtIndex(index);
188 <span id='Ext-view-Table-method-getCell'> /**
189 </span> * Get the cell (td) for a particular record and column.
190 * @param {Ext.data.Model} record
191 * @param {Ext.grid.column.Colunm} column
194 getCell: function(record, column) {
195 var row = this.getNode(record);
196 return Ext.fly(row).down(column.getCellSelector());
199 <span id='Ext-view-Table-method-getFeature'> /**
200 </span> * Get a reference to a feature
201 * @param {String} id The id of the feature
202 * @return {Ext.grid.feature.Feature} The feature. Undefined if not found
204 getFeature: function(id) {
205 var features = this.featuresMC;
207 return features.get(id);
211 <span id='Ext-view-Table-method-initFeatures'> /**
212 </span> * Initializes each feature and bind it to this view.
215 initFeatures: function() {
221 me.features = me.features || [];
222 features = me.features;
223 len = features.length;
225 me.featuresMC = Ext.create('Ext.util.MixedCollection');
226 for (; i < len; i++) {
227 // ensure feature hasnt already been instantiated
228 if (!features[i].isFeature) {
229 features[i] = Ext.create('feature.' + features[i].ftype, features[i]);
231 // inject a reference to view
232 features[i].view = me;
233 me.featuresMC.add(features[i]);
237 <span id='Ext-view-Table-method-attachEventsForFeatures'> /**
238 </span> * Gives features an injection point to attach events to the markup that
239 * has been created for this view.
242 attachEventsForFeatures: function() {
243 var features = this.features,
244 ln = features.length,
247 for (; i < ln; i++) {
248 if (features[i].isFeature) {
249 features[i].attachEvents();
254 afterRender: function() {
259 scroll: me.fireBodyScroll,
262 me.el.unselectable();
263 me.attachEventsForFeatures();
266 fireBodyScroll: function(e, t) {
267 this.fireEvent('bodyscroll', e, t);
270 // TODO: Refactor headerCt dependency here to colModel
271 <span id='Ext-view-Table-method-prepareData'> /**
272 </span> * Uses the headerCt to transform data from dataIndex keys in a record to
273 * headerId keys in each header and then run them through each feature to
274 * get additional data for variables they have injected into the view template.
277 prepareData: function(data, idx, record) {
279 orig = me.headerCt.prepareData(data, idx, record, me, me.ownerCt),
280 features = me.features,
281 ln = features.length,
285 for (; i < ln; i++) {
286 feature = features[i];
287 if (feature.isFeature) {
288 Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, me));
295 // TODO: Refactor headerCt dependency here to colModel
296 collectData: function(records, startIndex) {
297 var preppedRecords = this.callParent(arguments),
298 headerCt = this.headerCt,
299 fullWidth = headerCt.getFullWidth(),
300 features = this.features,
301 ln = features.length,
303 rows: preppedRecords,
312 jln = preppedRecords.length;
313 // process row classes, rowParams has been deprecated and has been moved
314 // to the individual features that implement the behavior.
315 if (this.getRowClass) {
316 for (; j < jln; j++) {
318 preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
321 Ext.Error.raise("The getRowClass alt property is no longer supported.");
323 if (rowParams.tstyle) {
324 Ext.Error.raise("The getRowClass tstyle property is no longer supported.");
326 if (rowParams.cells) {
327 Ext.Error.raise("The getRowClass cells property is no longer supported.");
329 if (rowParams.body) {
330 Ext.Error.raise("The getRowClass body property is no longer supported. Use the getAdditionalData method of the rowbody feature.");
332 if (rowParams.bodyStyle) {
333 Ext.Error.raise("The getRowClass bodyStyle property is no longer supported.");
335 if (rowParams.cols) {
336 Ext.Error.raise("The getRowClass cols property is no longer supported.");
341 // currently only one feature may implement collectData. This is to modify
342 // what's returned to the view before its rendered
343 for (; i < ln; i++) {
344 feature = features[i];
345 if (feature.isFeature && feature.collectData && !feature.disabled) {
346 o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
353 // TODO: Refactor header resizing to column resizing
354 <span id='Ext-view-Table-method-onHeaderResize'> /**
355 </span> * When a header is resized, setWidth on the individual columns resizer class,
356 * the top level table, save/restore scroll state, generate a new template and
357 * restore focus to the grid view's element so that keyboard navigation
361 onHeaderResize: function(header, w, suppressFocus) {
366 me.saveScrollState();
367 // Grab the col and set the width, css
368 // class is generated in TableChunker.
369 // Select composites because there may be several chunks.
372 // Setting the width of the first TD does not work - ends up with a 1 pixel discrepancy.
373 // We need to increment the passed with in this case.
374 if (Ext.isIE6 || Ext.isIE7) {
375 if (header.el.hasCls(Ext.baseCSSPrefix + 'column-header-first')) {
379 el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
380 el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(me.headerCt.getFullWidth());
381 me.restoreScrollState();
383 if (!suppressFocus) {
389 <span id='Ext-view-Table-method-onHeaderShow'> /**
390 </span> * When a header is shown restore its oldWidth if it was previously hidden.
393 onHeaderShow: function(headerCt, header, suppressFocus) {
394 // restore headers that were dynamically hidden
395 if (header.oldWidth) {
396 this.onHeaderResize(header, header.oldWidth, suppressFocus);
397 delete header.oldWidth;
398 // flexed headers will have a calculated size set
399 // this additional check has to do with the fact that
400 // defaults: {width: 100} will fight with a flex value
401 } else if (header.width && !header.flex) {
402 this.onHeaderResize(header, header.width, suppressFocus);
404 this.setNewTemplate();
407 <span id='Ext-view-Table-method-onHeaderHide'> /**
408 </span> * When the header hides treat it as a resize to 0.
411 onHeaderHide: function(headerCt, header, suppressFocus) {
412 this.onHeaderResize(header, 0, suppressFocus);
415 <span id='Ext-view-Table-method-setNewTemplate'> /**
416 </span> * Set a new template based on the current columns displayed in the
420 setNewTemplate: function() {
422 columns = me.headerCt.getColumnsForTpl(true);
424 me.tpl = me.getTableChunker().getTableTpl({
426 features: me.features
430 <span id='Ext-view-Table-method-getTableChunker'> /**
431 </span> * Get the configured chunker or default of Ext.view.TableChunker
433 getTableChunker: function() {
434 return this.chunker || Ext.view.TableChunker;
437 <span id='Ext-view-Table-method-addRowCls'> /**
438 </span> * Add a CSS Class to a specific row.
439 * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model representing this row
440 * @param {String} cls
442 addRowCls: function(rowInfo, cls) {
443 var row = this.getNode(rowInfo);
445 Ext.fly(row).addCls(cls);
449 <span id='Ext-view-Table-method-removeRowCls'> /**
450 </span> * Remove a CSS Class from a specific row.
451 * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model representing this row
452 * @param {String} cls
454 removeRowCls: function(rowInfo, cls) {
455 var row = this.getNode(rowInfo);
457 Ext.fly(row).removeCls(cls);
461 // GridSelectionModel invokes onRowSelect as selection changes
462 onRowSelect : function(rowIdx) {
463 this.addRowCls(rowIdx, this.selectedItemCls);
466 // GridSelectionModel invokes onRowDeselect as selection changes
467 onRowDeselect : function(rowIdx) {
470 me.removeRowCls(rowIdx, me.selectedItemCls);
471 me.removeRowCls(rowIdx, me.focusedItemCls);
474 onCellSelect: function(position) {
475 var cell = this.getCellByPosition(position);
477 cell.addCls(this.selectedCellCls);
481 onCellDeselect: function(position) {
482 var cell = this.getCellByPosition(position);
484 cell.removeCls(this.selectedCellCls);
489 onCellFocus: function(position) {
490 //var cell = this.getCellByPosition(position);
491 this.focusCell(position);
494 getCellByPosition: function(position) {
495 var row = position.row,
496 column = position.column,
498 node = this.getNode(row),
499 header = this.headerCt.getHeaderAtIndex(column),
503 if (header && node) {
504 cellSelector = header.getCellSelector();
505 cell = Ext.fly(node).down(cellSelector);
510 // GridSelectionModel invokes onRowFocus to 'highlight'
511 // the last row focused
512 onRowFocus: function(rowIdx, highlight, supressFocus) {
514 row = me.getNode(rowIdx);
517 me.addRowCls(rowIdx, me.focusedItemCls);
521 //this.el.dom.setAttribute('aria-activedescendant', row.id);
523 me.removeRowCls(rowIdx, me.focusedItemCls);
527 <span id='Ext-view-Table-method-focusRow'> /**
528 </span> * Focus a particular row and bring it into view. Will fire the rowfocus event.
529 * @param {Mixed} rowIdx An HTMLElement template node, index of a template node, the
530 * id of a template node or the record associated with the node.
532 focusRow: function(rowIdx) {
534 row = me.getNode(rowIdx),
542 if (row && el) {
543 elRegion = el.getRegion();
544 rowRegion = Ext.fly(row).getRegion();
546 if (rowRegion.top < elRegion.top) {
547 adjustment = rowRegion.top - elRegion.top;
549 } else if (rowRegion.bottom > elRegion.bottom) {
550 adjustment = rowRegion.bottom - elRegion.bottom;
552 record = me.getRecord(row);
553 rowIdx = me.store.indexOf(record);
556 // scroll the grid itself, so that all gridview's update.
557 panel.scrollByDeltaY(adjustment);
559 me.fireEvent('rowfocus', record, row, rowIdx);
563 focusCell: function(position) {
565 cell = me.getCellByPosition(position),
569 elRegion = el.getRegion(),
575 cellRegion = cell.getRegion();
577 if (cellRegion.top < elRegion.top) {
578 adjustmentY = cellRegion.top - elRegion.top;
580 } else if (cellRegion.bottom > elRegion.bottom) {
581 adjustmentY = cellRegion.bottom - elRegion.bottom;
585 if (cellRegion.left < elRegion.left) {
586 adjustmentX = cellRegion.left - elRegion.left;
588 } else if (cellRegion.right > elRegion.right) {
589 adjustmentX = cellRegion.right - elRegion.right;
593 // scroll the grid itself, so that all gridview's update.
594 panel.scrollByDeltaY(adjustmentY);
597 panel.scrollByDeltaX(adjustmentX);
600 me.fireEvent('cellfocus', record, cell, position);
604 <span id='Ext-view-Table-method-scrollByDelta'> /**
605 </span> * Scroll by delta. This affects this individual view ONLY and does not
606 * synchronize across views or scrollers.
607 * @param {Number} delta
608 * @param {String} dir (optional) Valid values are scrollTop and scrollLeft. Defaults to scrollTop.
611 scrollByDelta: function(delta, dir) {
612 dir = dir || 'scrollTop';
613 var elDom = this.el.dom;
614 elDom[dir] = (elDom[dir] += delta);
617 onUpdate: function(ds, index) {
618 this.callParent(arguments);
621 <span id='Ext-view-Table-method-saveScrollState'> /**
622 </span> * Save the scrollState in a private variable.
623 * Must be used in conjunction with restoreScrollState
625 saveScrollState: function() {
626 var dom = this.el.dom,
627 state = this.scrollState;
629 state.left = dom.scrollLeft;
630 state.top = dom.scrollTop;
633 <span id='Ext-view-Table-method-restoreScrollState'> /**
634 </span> * Restore the scrollState.
635 * Must be used in conjunction with saveScrollState
638 restoreScrollState: function() {
639 var dom = this.el.dom,
640 state = this.scrollState,
641 headerEl = this.headerCt.el.dom;
643 headerEl.scrollLeft = dom.scrollLeft = state.left;
644 dom.scrollTop = state.top;
647 <span id='Ext-view-Table-method-refresh'> /**
648 </span> * Refresh the grid view.
649 * Saves and restores the scroll state, generates a new template, stripes rows
650 * and invalidates the scrollers.
652 refresh: function() {
653 this.setNewTemplate();
654 this.callParent(arguments);
657 processItemEvent: function(record, row, rowIndex, e) {
659 cell = e.getTarget(me.cellSelector, row),
660 cellIndex = cell ? cell.cellIndex : -1,
661 map = me.statics().EventMap,
662 selModel = me.getSelectionModel(),
666 if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
667 // CellModel, otherwise we can't tell which cell to invoke
668 cell = me.getCellByPosition(selModel.getCurrentPosition());
671 cellIndex = cell.cellIndex;
675 result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
677 if (result === false || me.callParent(arguments) === false) {
681 // Don't handle cellmouseenter and cellmouseleave events for now
682 if (type == 'mouseover' || type == 'mouseout') {
687 // We are adding cell and feature events
688 (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
689 (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
690 (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
691 (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
695 processSpecialEvent: function(e) {
697 map = me.statics().EventMap,
698 features = me.features,
699 ln = features.length,
701 i, feature, prefix, featureTarget,
705 me.callParent(arguments);
707 if (type == 'mouseover' || type == 'mouseout') {
711 for (i = 0; i < ln; i++) {
712 feature = features[i];
713 if (feature.hasFeatureEvent) {
714 featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
716 prefix = feature.eventPrefix;
717 // allows features to implement getFireEventArgs to change the
718 // fireEvent signature
719 beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e);
720 args = feature.getFireEventArgs(prefix + type, me, featureTarget, e);
724 (me.fireEvent.apply(me, beforeArgs) === false) ||
726 (panel.fireEvent.apply(panel, beforeArgs) === false) ||
728 (me.fireEvent.apply(me, args) === false) ||
730 (panel.fireEvent.apply(panel, args) === false)
740 onCellMouseDown: Ext.emptyFn,
741 onCellMouseUp: Ext.emptyFn,
742 onCellClick: Ext.emptyFn,
743 onCellDblClick: Ext.emptyFn,
744 onCellContextMenu: Ext.emptyFn,
745 onCellKeyDown: Ext.emptyFn,
746 onBeforeCellMouseDown: Ext.emptyFn,
747 onBeforeCellMouseUp: Ext.emptyFn,
748 onBeforeCellClick: Ext.emptyFn,
749 onBeforeCellDblClick: Ext.emptyFn,
750 onBeforeCellContextMenu: Ext.emptyFn,
751 onBeforeCellKeyDown: Ext.emptyFn,
753 <span id='Ext-view-Table-method-expandToFit'> /**
754 </span> * Expand a particular header to fit the max content width.
755 * This will ONLY expand, not contract.
758 expandToFit: function(header) {
760 var maxWidth = this.getMaxContentWidth(header);
762 header.setWidth(maxWidth);
766 <span id='Ext-view-Table-method-getMaxContentWidth'> /**
767 </span> * Get the max contentWidth of the header's text and all cells
768 * in the grid under this header.
771 getMaxContentWidth: function(header) {
772 var cellSelector = header.getCellInnerSelector(),
773 cells = this.el.query(cellSelector),
776 maxWidth = header.el.dom.scrollWidth,
779 for (; i < ln; i++) {
780 scrollWidth = cells[i].scrollWidth;
781 if (scrollWidth > maxWidth) {
782 maxWidth = scrollWidth;
788 getPositionByEvent: function(e) {
790 cellNode = e.getTarget(me.cellSelector),
791 rowNode = e.getTarget(me.itemSelector),
792 record = me.getRecord(rowNode),
793 header = me.getHeaderByCell(cellNode);
795 return me.getPosition(record, header);
798 getHeaderByCell: function(cell) {
800 var m = cell.className.match(this.cellRe);
801 if (m && m[1]) {
802 return Ext.getCmp(m[1]);
808 <span id='Ext-view-Table-method-walkCells'> /**
809 </span> * @param {Object} position The current row and column: an object containing the following properties:<ul>
810 * <li>row<div class="sub-desc"> The row <b>index</b></div></li>
811 * <li>column<div class="sub-desc">The column <b>index</b></div></li>
813 * @param {String} direction 'up', 'down', 'right' and 'left'
814 * @param {Ext.EventObject} e event
815 * @param {Boolean} preventWrap Set to true to prevent wrap around to the next or previous row.
816 * @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.
817 * @param {Scope} scope Scope to run the verifierFn in
818 * @returns {Object} newPosition An object containing the following properties:<ul>
819 * <li>row<div class="sub-desc"> The row <b>index</b></div></li>
820 * <li>column<div class="sub-desc">The column <b>index</b></div></li>
824 walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
828 rowCount = me.store.getCount(),
829 firstCol = me.getFirstVisibleColumnIndex(),
830 lastCol = me.getLastVisibleColumnIndex(),
831 newPos = {row: row, column: column},
832 activeHeader = me.headerCt.getHeaderAtIndex(column);
834 // no active header or its currently hidden
835 if (!activeHeader || activeHeader.hidden) {
840 direction = direction.toLowerCase();
843 // has the potential to wrap if its last
844 if (column === lastCol) {
845 // if bottom row and last column, deny right
846 if (preventWrap || row === rowCount - 1) {
850 // otherwise wrap to nextRow and firstCol
851 newPos.row = row + 1;
852 newPos.column = firstCol;
857 newPos.column = column + me.getRightGap(activeHeader);
859 newPos.column = lastCol;
865 // has the potential to wrap
866 if (column === firstCol) {
867 // if top row and first column, deny left
868 if (preventWrap || row === 0) {
872 // otherwise wrap to prevRow and lastCol
873 newPos.row = row - 1;
874 newPos.column = lastCol;
879 newPos.column = column + me.getLeftGap(activeHeader);
881 newPos.column = firstCol;
887 // if top row, deny up
893 newPos.row = row - 1;
901 // if bottom row, deny down
902 if (row === rowCount - 1) {
907 newPos.row = row + 1;
909 newPos.row = rowCount - 1;
915 if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
921 getFirstVisibleColumnIndex: function() {
922 var headerCt = this.getHeaderCt(),
923 allColumns = headerCt.getGridColumns(),
924 visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
925 firstHeader = visHeaders[0];
927 return headerCt.getHeaderIndex(firstHeader);
930 getLastVisibleColumnIndex: function() {
931 var headerCt = this.getHeaderCt(),
932 allColumns = headerCt.getGridColumns(),
933 visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
934 lastHeader = visHeaders[visHeaders.length - 1];
936 return headerCt.getHeaderIndex(lastHeader);
939 getHeaderCt: function() {
940 return this.headerCt;
943 getPosition: function(record, header) {
946 gridCols = me.headerCt.getGridColumns();
949 row: store.indexOf(record),
950 column: Ext.Array.indexOf(gridCols, header)
954 <span id='Ext-view-Table-method-getRightGap'> /**
955 </span> * Determines the 'gap' between the closest adjacent header to the right
956 * that is not hidden.
959 getRightGap: function(activeHeader) {
960 var headerCt = this.getHeaderCt(),
961 headers = headerCt.getGridColumns(),
962 activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
963 i = activeHeaderIdx + 1,
966 for (; i <= headers.length; i++) {
967 if (!headers[i].hidden) {
973 return nextIdx - activeHeaderIdx;
976 beforeDestroy: function() {
978 this.el.removeAllListeners();
980 this.callParent(arguments);
983 <span id='Ext-view-Table-method-getLeftGap'> /**
984 </span> * Determines the 'gap' between the closest adjacent header to the left
985 * that is not hidden.
988 getLeftGap: function(activeHeader) {
989 var headerCt = this.getHeaderCt(),
990 headers = headerCt.getGridColumns(),
991 activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
992 i = activeHeaderIdx - 1,
995 for (; i >= 0; i--) {
996 if (!headers[i].hidden) {
1002 return prevIdx - activeHeaderIdx;