1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-view.Table'>/**
2 </span> * @class Ext.view.Table
3 * @extends Ext.view.View
5 This class encapsulates the user interface for a tabular data set.
6 It acts as a centralized manager for controlling the various interface
7 elements of the view. This includes handling events, such as row and cell
8 level based DOM events. It also reacts to events from the underlying {@link Ext.selection.Model}
9 to provide visual feedback to the user.
11 This class does not provide ways to manipulate the underlying data of the configured
12 {@link Ext.data.Store}.
14 This is the base class for both {@link Ext.grid.View} and {@link Ext.tree.View} and is not
20 * @author Nicolas Ferrero
22 Ext.define('Ext.view.Table', {
23 extend: 'Ext.view.View',
24 alias: 'widget.tableview',
26 'Ext.view.TableChunker',
27 'Ext.util.DelayedTask',
28 'Ext.util.MixedCollection'
31 cls: Ext.baseCSSPrefix + 'grid-view',
34 itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
36 cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
38 selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
39 selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
40 focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
41 overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
42 altRowCls: Ext.baseCSSPrefix + 'grid-row-alt',
43 rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
44 cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
49 <span id='Ext-view.Table-method-getRowClass'> /**
50 </span> * Override this function to apply custom CSS classes to rows during rendering. You can also supply custom
51 * parameters to the row template for the current row to customize how it is rendered using the <b>rowParams</b>
52 * parameter. This function should return the CSS class name (or empty string '' for none) that will be added
53 * to the row's wrapping div. To apply multiple class names, simply return them space-delimited within the string
54 * (e.g., 'my-class another-class'). Example usage:
55 <pre><code>
58 showPreview: true, // custom property
59 enableRowBody: true, // required to create a second, full-width row to show expanded Record data
60 getRowClass: function(record, rowIndex, rp, ds){ // rp = rowParams
62 rp.body = '&lt;p>'+record.data.excerpt+'&lt;/p>';
63 return 'x-grid3-row-expanded';
65 return 'x-grid3-row-collapsed';
68 </code></pre>
69 * @param {Model} model The {@link Ext.data.Model} corresponding to the current row.
70 * @param {Number} index The row index.
71 * @param {Object} rowParams (DEPRECATED) A config object that is passed to the row template during rendering that allows
72 * customization of various aspects of a grid row.
73 * <p>If {@link #enableRowBody} is configured <b><tt></tt>true</b>, then the following properties may be set
74 * by this function, and will be used to render a full-width expansion row below each grid row:</p>
76 * <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>
77 * <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>
79 * The following property will be passed in, and may be appended to:
81 * <li><code>tstyle</code> : String <div class="sub-desc">A CSS style specification that willl be applied to the &lt;table> element which encapsulates
82 * both the standard grid row, and any expansion row.</div></li>
84 * @param {Store} store The {@link Ext.data.Store} this grid is bound to
86 * @return {String} a CSS class name to add to the row.
90 initComponent: function() {
91 this.scrollState = {};
92 this.selModel.view = this;
93 this.headerCt.view = this;
95 this.setNewTemplate();
97 this.mon(this.store, {
98 load: this.onStoreLoad,
105 // * @param {Ext.data.Record} record
106 // * @param {HTMLElement} row
107 // * @param {Number} rowIdx
113 // scroll to top of the grid when store loads
114 onStoreLoad: function(){
115 if (this.invalidateScrollerOnRefresh) {
117 if (!this.scrollToTopTask) {
118 this.scrollToTopTask = Ext.create('Ext.util.DelayedTask', this.scrollToTop, this);
120 this.scrollToTopTask.delay(1);
127 // scroll the view to the top
128 scrollToTop: Ext.emptyFn,
130 <span id='Ext-view.Table-method-getGridColumns'> /**
131 </span> * Get the columns used for generating a template via TableChunker.
132 * See {@link Ext.grid.header.Container#getGridColumns}.
135 getGridColumns: function() {
136 return this.headerCt.getGridColumns();
139 <span id='Ext-view.Table-method-getHeaderAtIndex'> /**
140 </span> * Get a leaf level header by index regardless of what the nesting
143 * @param {Number} index The index
145 getHeaderAtIndex: function(index) {
146 return this.headerCt.getHeaderAtIndex(index);
149 <span id='Ext-view.Table-method-getCell'> /**
150 </span> * Get the cell (td) for a particular record and column.
151 * @param {Ext.data.Model} record
152 * @param {Ext.grid.column.Colunm} column
155 getCell: function(record, column) {
156 var row = this.getNode(record);
157 return Ext.fly(row).down(column.getCellSelector());
160 <span id='Ext-view.Table-method-getFeature'> /**
161 </span> * Get a reference to a feature
162 * @param {String} id The id of the feature
163 * @return {Ext.grid.feature.Feature} The feature. Undefined if not found
165 getFeature: function(id) {
166 var features = this.featuresMC;
168 return features.get(id);
172 <span id='Ext-view.Table-method-initFeatures'> /**
173 </span> * Initializes each feature and bind it to this view.
176 initFeatures: function() {
177 this.features = this.features || [];
178 var features = this.features,
179 ln = features.length,
182 this.featuresMC = Ext.create('Ext.util.MixedCollection');
183 for (; i < ln; i++) {
184 // ensure feature hasnt already been instantiated
185 if (!features[i].isFeature) {
186 features[i] = Ext.create('feature.'+features[i].ftype, features[i]);
188 // inject a reference to view
189 features[i].view = this;
190 this.featuresMC.add(features[i]);
194 <span id='Ext-view.Table-method-attachEventsForFeatures'> /**
195 </span> * Gives features an injection point to attach events to the markup that
196 * has been created for this view.
199 attachEventsForFeatures: function() {
200 var features = this.features,
201 ln = features.length,
204 for (; i < ln; i++) {
205 if (features[i].isFeature) {
206 features[i].attachEvents();
211 afterRender: function() {
214 scroll: this.fireBodyScroll,
217 this.attachEventsForFeatures();
220 fireBodyScroll: function(e, t) {
221 this.fireEvent('bodyscroll', e, t);
224 // TODO: Refactor headerCt dependency here to colModel
225 <span id='Ext-view.Table-method-prepareData'> /**
226 </span> * Uses the headerCt to transform data from dataIndex keys in a record to
227 * headerId keys in each header and then run them through each feature to
228 * get additional data for variables they have injected into the view template.
231 prepareData: function(data, idx, record) {
232 var orig = this.headerCt.prepareData(data, idx, record, this),
233 features = this.features,
234 ln = features.length,
238 for (; i < ln; i++) {
239 feature = features[i];
240 if (feature.isFeature) {
241 Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, this));
248 // TODO: Refactor headerCt dependency here to colModel
249 collectData: function(records, startIndex) {
250 var preppedRecords = this.callParent(arguments),
251 headerCt = this.headerCt,
252 fullWidth = headerCt.getFullWidth(),
253 features = this.features,
254 ln = features.length,
256 rows: preppedRecords,
265 jln = preppedRecords.length;
266 // process row classes, rowParams has been deprecated and has been moved
267 // to the individual features that implement the behavior.
268 if (this.getRowClass) {
269 for (; j < jln; j++) {
271 preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
274 Ext.Error.raise("The getRowClass alt property is no longer supported.");
276 if (rowParams.tstyle) {
277 Ext.Error.raise("The getRowClass tstyle property is no longer supported.");
279 if (rowParams.cells) {
280 Ext.Error.raise("The getRowClass cells property is no longer supported.");
282 if (rowParams.body) {
283 Ext.Error.raise("The getRowClass body property is no longer supported. Use the getAdditionalData method of the rowbody feature.");
285 if (rowParams.bodyStyle) {
286 Ext.Error.raise("The getRowClass bodyStyle property is no longer supported.");
288 if (rowParams.cols) {
289 Ext.Error.raise("The getRowClass cols property is no longer supported.");
294 // currently only one feature may implement collectData. This is to modify
295 // what's returned to the view before its rendered
296 for (; i < ln; i++) {
297 feature = features[i];
298 if (feature.isFeature && feature.collectData && !feature.disabled) {
299 o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
306 // TODO: Refactor header resizing to column resizing
307 <span id='Ext-view.Table-method-onHeaderResize'> /**
308 </span> * When a header is resized, setWidth on the individual columns resizer class,
309 * the top level table, save/restore scroll state, generate a new template and
310 * restore focus to the grid view's element so that keyboard navigation
314 onHeaderResize: function(header, w, suppressFocus) {
317 this.saveScrollState();
318 // Grab the col and set the width, css
319 // class is generated in TableChunker.
320 // Select composites because there may be several chunks.
321 el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
322 el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(this.headerCt.getFullWidth());
323 this.restoreScrollState();
324 this.setNewTemplate();
325 if (!suppressFocus) {
331 <span id='Ext-view.Table-method-onHeaderShow'> /**
332 </span> * When a header is shown restore its oldWidth if it was previously hidden.
335 onHeaderShow: function(headerCt, header, suppressFocus) {
336 // restore headers that were dynamically hidden
337 if (header.oldWidth) {
338 this.onHeaderResize(header, header.oldWidth, suppressFocus);
339 delete header.oldWidth;
340 // flexed headers will have a calculated size set
341 // this additional check has to do with the fact that
342 // defaults: {width: 100} will fight with a flex value
343 } else if (header.width && !header.flex) {
344 this.onHeaderResize(header, header.width, suppressFocus);
346 this.setNewTemplate();
349 <span id='Ext-view.Table-method-onHeaderHide'> /**
350 </span> * When the header hides treat it as a resize to 0.
353 onHeaderHide: function(headerCt, header, suppressFocus) {
354 this.onHeaderResize(header, 0, suppressFocus);
357 <span id='Ext-view.Table-method-setNewTemplate'> /**
358 </span> * Set a new template based on the current columns displayed in the
362 setNewTemplate: function() {
363 var columns = this.headerCt.getColumnsForTpl(true);
364 this.tpl = this.getTableChunker().getTableTpl({
366 features: this.features
370 <span id='Ext-view.Table-method-getTableChunker'> /**
371 </span> * Get the configured chunker or default of Ext.view.TableChunker
373 getTableChunker: function() {
374 return this.chunker || Ext.view.TableChunker;
377 <span id='Ext-view.Table-method-addRowCls'> /**
378 </span> * Add a CSS Class to a specific row.
379 * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model representing this row
380 * @param {String} cls
382 addRowCls: function(rowInfo, cls) {
383 var row = this.getNode(rowInfo);
385 Ext.fly(row).addCls(cls);
389 <span id='Ext-view.Table-method-removeRowCls'> /**
390 </span> * Remove a CSS Class from a specific row.
391 * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model representing this row
392 * @param {String} cls
394 removeRowCls: function(rowInfo, cls) {
395 var row = this.getNode(rowInfo);
397 Ext.fly(row).removeCls(cls);
401 // GridSelectionModel invokes onRowSelect as selection changes
402 onRowSelect : function(rowIdx) {
403 this.addRowCls(rowIdx, this.selectedItemCls);
406 // GridSelectionModel invokes onRowDeselect as selection changes
407 onRowDeselect : function(rowIdx) {
408 this.removeRowCls(rowIdx, this.selectedItemCls);
409 this.removeRowCls(rowIdx, this.focusedItemCls);
412 onCellSelect: function(position) {
413 var cell = this.getCellByPosition(position);
415 cell.addCls(this.selectedCellCls);
419 onCellDeselect: function(position) {
420 var cell = this.getCellByPosition(position);
422 cell.removeCls(this.selectedCellCls);
427 onCellFocus: function(position) {
428 //var cell = this.getCellByPosition(position);
429 this.focusCell(position);
432 getCellByPosition: function(position) {
433 var row = position.row,
434 column = position.column,
436 node = this.getNode(row),
437 header = this.headerCt.getHeaderAtIndex(column),
442 cellSelector = header.getCellSelector();
443 cell = Ext.fly(node).down(cellSelector);
448 // GridSelectionModel invokes onRowFocus to 'highlight'
449 // the last row focused
450 onRowFocus: function(rowIdx, highlight, supressFocus) {
451 var row = this.getNode(rowIdx);
454 this.addRowCls(rowIdx, this.focusedItemCls);
456 this.focusRow(rowIdx);
458 //this.el.dom.setAttribute('aria-activedescendant', row.id);
460 this.removeRowCls(rowIdx, this.focusedItemCls);
464 <span id='Ext-view.Table-cfg-An'> /**
465 </span> * Focus a particular row and bring it into view. Will fire the rowfocus event.
466 * @cfg {Mixed} An HTMLElement template node, index of a template node, the
467 * id of a template node or the record associated with the node.
469 focusRow: function(rowIdx) {
470 var row = this.getNode(rowIdx),
473 panel = this.ownerCt,
478 if (row && this.el) {
479 elRegion = el.getRegion();
480 rowRegion = Ext.fly(row).getRegion();
482 if (rowRegion.top < elRegion.top) {
483 adjustment = rowRegion.top - elRegion.top;
485 } else if (rowRegion.bottom > elRegion.bottom) {
486 adjustment = rowRegion.bottom - elRegion.bottom;
488 record = this.getRecord(row);
489 rowIdx = this.store.indexOf(record);
492 // scroll the grid itself, so that all gridview's update.
493 panel.scrollByDeltaY(adjustment);
495 this.fireEvent('rowfocus', record, row, rowIdx);
499 focusCell: function(position) {
500 var cell = this.getCellByPosition(position),
504 elRegion = el.getRegion(),
505 panel = this.ownerCt,
510 cellRegion = cell.getRegion();
512 if (cellRegion.top < elRegion.top) {
513 adjustmentY = cellRegion.top - elRegion.top;
515 } else if (cellRegion.bottom > elRegion.bottom) {
516 adjustmentY = cellRegion.bottom - elRegion.bottom;
520 if (cellRegion.left < elRegion.left) {
521 adjustmentX = cellRegion.left - elRegion.left;
523 } else if (cellRegion.right > elRegion.right) {
524 adjustmentX = cellRegion.right - elRegion.right;
528 // scroll the grid itself, so that all gridview's update.
529 panel.scrollByDeltaY(adjustmentY);
532 panel.scrollByDeltaX(adjustmentX);
535 this.fireEvent('cellfocus', record, cell, position);
539 <span id='Ext-view.Table-method-scrollByDelta'> /**
540 </span> * Scroll by delta. This affects this individual view ONLY and does not
541 * synchronize across views or scrollers.
542 * @param {Number} delta
543 * @param {String} dir (optional) Valid values are scrollTop and scrollLeft. Defaults to scrollTop.
546 scrollByDelta: function(delta, dir) {
547 dir = dir || 'scrollTop';
548 var elDom = this.el.dom;
549 elDom[dir] = (elDom[dir] += delta);
552 onUpdate: function(ds, index) {
553 this.callParent(arguments);
556 <span id='Ext-view.Table-method-saveScrollState'> /**
557 </span> * Save the scrollState in a private variable.
558 * Must be used in conjunction with restoreScrollState
560 saveScrollState: function() {
561 var dom = this.el.dom,
562 state = this.scrollState;
564 state.left = dom.scrollLeft;
565 state.top = dom.scrollTop;
568 <span id='Ext-view.Table-method-restoreScrollState'> /**
569 </span> * Restore the scrollState.
570 * Must be used in conjunction with saveScrollState
573 restoreScrollState: function() {
574 var dom = this.el.dom,
575 state = this.scrollState,
576 headerEl = this.headerCt.el.dom;
578 headerEl.scrollLeft = dom.scrollLeft = state.left;
579 dom.scrollTop = state.top;
582 <span id='Ext-view.Table-method-refresh'> /**
583 </span> * Refresh the grid view.
584 * Saves and restores the scroll state, generates a new template, stripes rows
585 * and invalidates the scrollers.
586 * @param {Boolean} firstPass This is a private flag for internal use only.
588 refresh: function(firstPass) {
592 //this.saveScrollState();
595 // The table.unselectable() call below adds a selectstart listener to the table element.
596 // Before we clear the whole dataview in the callParent, we remove all the listeners from the
597 // table. This prevents a big memory leak on IE6 and IE7.
599 table = me.el.child('table');
601 table.removeAllListeners();
605 me.callParent(arguments);
607 //this.restoreScrollState();
609 // Make the table view unselectable
610 table = me.el.child('table');
612 table.unselectable();
616 // give focus back to gridview
622 processItemEvent: function(type, record, row, rowIndex, e) {
624 cell = e.getTarget(me.cellSelector, row),
625 cellIndex = cell ? cell.cellIndex : -1,
626 map = me.statics().EventMap,
627 selModel = me.getSelectionModel(),
630 if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
631 // CellModel, otherwise we can't tell which cell to invoke
632 cell = me.getCellByPosition(selModel.getCurrentPosition());
635 cellIndex = cell.cellIndex;
639 result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
641 if (result === false || me.callParent(arguments) === false) {
645 // Don't handle cellmouseenter and cellmouseleave events for now
646 if (type == 'mouseover' || type == 'mouseout') {
651 // We are adding cell and feature events
652 (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
653 (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
654 (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
655 (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
659 processSpecialEvent: function(e) {
661 map = this.statics().EventMap,
662 features = this.features,
663 ln = features.length,
665 i, feature, prefix, featureTarget,
669 this.callParent(arguments);
671 if (type == 'mouseover' || type == 'mouseout') {
675 for (i = 0; i < ln; i++) {
676 feature = features[i];
677 if (feature.hasFeatureEvent) {
678 featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
680 prefix = feature.eventPrefix;
681 // allows features to implement getFireEventArgs to change the
682 // fireEvent signature
683 beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget);
684 args = feature.getFireEventArgs(prefix + type, me, featureTarget);
688 (me.fireEvent.apply(me, beforeArgs) === false) ||
690 (panel.fireEvent.apply(panel, beforeArgs) === false) ||
692 (me.fireEvent.apply(me, args) === false) ||
694 (panel.fireEvent.apply(panel, args) === false)
704 onCellMouseDown: Ext.emptyFn,
705 onCellMouseUp: Ext.emptyFn,
706 onCellClick: Ext.emptyFn,
707 onCellDblClick: Ext.emptyFn,
708 onCellContextMenu: Ext.emptyFn,
709 onCellKeyDown: Ext.emptyFn,
710 onBeforeCellMouseDown: Ext.emptyFn,
711 onBeforeCellMouseUp: Ext.emptyFn,
712 onBeforeCellClick: Ext.emptyFn,
713 onBeforeCellDblClick: Ext.emptyFn,
714 onBeforeCellContextMenu: Ext.emptyFn,
715 onBeforeCellKeyDown: Ext.emptyFn,
717 <span id='Ext-view.Table-method-expandToFit'> /**
718 </span> * Expand a particular header to fit the max content width.
719 * This will ONLY expand, not contract.
722 expandToFit: function(header) {
723 var maxWidth = this.getMaxContentWidth(header);
725 header.setWidth(maxWidth);
728 <span id='Ext-view.Table-method-getMaxContentWidth'> /**
729 </span> * Get the max contentWidth of the header's text and all cells
730 * in the grid under this header.
733 getMaxContentWidth: function(header) {
734 var cellSelector = header.getCellInnerSelector(),
735 cells = this.el.query(cellSelector),
738 maxWidth = header.el.dom.scrollWidth,
741 for (; i < ln; i++) {
742 scrollWidth = cells[i].scrollWidth;
743 if (scrollWidth > maxWidth) {
744 maxWidth = scrollWidth;
750 getPositionByEvent: function(e) {
751 var cellNode = e.getTarget(this.cellSelector),
752 rowNode = e.getTarget(this.itemSelector),
753 record = this.getRecord(rowNode),
754 header = this.getHeaderByCell(cellNode);
756 return this.getPosition(record, header);
759 getHeaderByCell: function(cell) {
761 var m = cell.className.match(this.cellRe);
762 if (m && m[1]) {
763 return Ext.getCmp(m[1]);
769 <span id='Ext-view.Table-method-walkCells'> /**
770 </span> * @param {Object} position The current row and column: an object containing the following properties:<ul>
771 * <li>row<div class="sub-desc"> The row <b>index</b></div></li>
772 * <li>column<div class="sub-desc">The column <b>index</b></div></li>
774 * @param {String} direction 'up', 'down', 'right' and 'left'
775 * @param {Ext.EventObject} e event
776 * @param {Boolean} preventWrap Set to true to prevent wrap around to the next or previous row.
777 * @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.
778 * @param {Scope} scope Scope to run the verifierFn in
779 * @returns {Object} newPosition An object containing the following properties:<ul>
780 * <li>row<div class="sub-desc"> The row <b>index</b></div></li>
781 * <li>column<div class="sub-desc">The column <b>index</b></div></li>
785 walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
788 rowCount = this.store.getCount(),
789 firstCol = this.getFirstVisibleColumnIndex(),
790 lastCol = this.getLastVisibleColumnIndex(),
791 newPos = {row: row, column: column},
792 activeHeader = this.headerCt.getHeaderAtIndex(column);
794 // no active header or its currently hidden
795 if (!activeHeader || activeHeader.hidden) {
800 direction = direction.toLowerCase();
803 // has the potential to wrap if its last
804 if (column === lastCol) {
805 // if bottom row and last column, deny right
806 if (preventWrap || row === rowCount - 1) {
810 // otherwise wrap to nextRow and firstCol
811 newPos.row = row + 1;
812 newPos.column = firstCol;
817 newPos.column = column + this.getRightGap(activeHeader);
819 newPos.column = lastCol;
825 // has the potential to wrap
826 if (column === firstCol) {
827 // if top row and first column, deny left
828 if (preventWrap || row === 0) {
832 // otherwise wrap to prevRow and lastCol
833 newPos.row = row - 1;
834 newPos.column = lastCol;
839 newPos.column = column + this.getLeftGap(activeHeader);
841 newPos.column = firstCol;
847 // if top row, deny up
853 newPos.row = row - 1;
861 // if bottom row, deny down
862 if (row === rowCount - 1) {
867 newPos.row = row + 1;
869 newPos.row = rowCount - 1;
875 if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
881 getFirstVisibleColumnIndex: function() {
882 var headerCt = this.getHeaderCt(),
883 allColumns = headerCt.getGridColumns(),
884 visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
885 firstHeader = visHeaders[0];
887 return headerCt.getHeaderIndex(firstHeader);
890 getLastVisibleColumnIndex: function() {
891 var headerCt = this.getHeaderCt(),
892 allColumns = headerCt.getGridColumns(),
893 visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
894 lastHeader = visHeaders[visHeaders.length - 1];
896 return headerCt.getHeaderIndex(lastHeader);
899 getHeaderCt: function() {
900 return this.headerCt;
903 getPosition: function(record, header) {
906 gridCols = me.headerCt.getGridColumns();
909 row: store.indexOf(record),
910 column: Ext.Array.indexOf(gridCols, header)
914 <span id='Ext-view.Table-method-getRightGap'> /**
915 </span> * Determines the 'gap' between the closest adjacent header to the right
916 * that is not hidden.
919 getRightGap: function(activeHeader) {
920 var headerCt = this.getHeaderCt(),
921 headers = headerCt.getGridColumns(),
922 activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
923 i = activeHeaderIdx + 1,
926 for (; i <= headers.length; i++) {
927 if (!headers[i].hidden) {
933 return nextIdx - activeHeaderIdx;
936 beforeDestroy: function() {
938 table = this.el.child('table');
940 table.removeAllListeners();
943 this.callParent(arguments);
946 <span id='Ext-view.Table-method-getLeftGap'> /**
947 </span> * Determines the 'gap' between the closest adjacent header to the left
948 * that is not hidden.
951 getLeftGap: function(activeHeader) {
952 var headerCt = this.getHeaderCt(),
953 headers = headerCt.getGridColumns(),
954 activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
955 i = activeHeaderIdx - 1,
958 for (; i >= 0; i--) {
959 if (!headers[i].hidden) {
965 return prevIdx - activeHeaderIdx;
967 });</pre></pre></body></html>