📄 gridrenderer.js
字号:
// override to return ratio in terms of rowNum instead of scrollTop vs scrollHeightgetScrollRatio : function (vertical,b,c,d) { if (!vertical || !this.virtualScrolling) { return this.invokeSuper(isc.GridRenderer, "getScrollRatio", vertical,b,c,d); } if (this.isDirty() && this._scrollRatio != null) return this._scrollRatio; // if there are 0 or 1 rows, we're at the top var maxRow = this.getTotalRows() - 1; if (maxRow <= 0) return 0; var scrollTop = this.getScrollTop(), topCoord = this.getRowCoordinate(scrollTop), ratio = topCoord / maxRow; //this.logWarn("getScrollRatio: " + ratio + // ", maxRow: " + maxRow + // ", topCoord: " + topCoord); return Math.min(1,ratio);},// show a fixed-size thumb in virtualScrolling mode. Otherwise thumb size fluctuates// meaninglessly.getViewportRatio : function (vertical,b,c,d) { if (!vertical || !this.virtualScrolling) { return this.invokeSuper(isc.GridRenderer, "getViewportRatio", vertical,b,c,d); } var avgRowHeight = this._viewRatioRowHeight || this.avgRowHeight; return Math.min(1, (this.getViewportHeight() / avgRowHeight) / this.getTotalRows());},// take some drawn row that is likely to remain drawn, and store the position it should be in// relative to the viewport, so that if we have to redraw, we can match user expectation by// placing rows where the user expects._storeTargetRow : function (scrollTop, delta) { // don't pick up a target row during the special scroll that places us on the target row if (this._literalScroll) return; // according to scrolling direction, pick the row at the top or bottom of the viewport as // the row most likely to remain onscreen var viewportEdge if (delta > 0) { // scrolling down viewportEdge = scrollTop + this.getViewportHeight(); } else { viewportEdge = scrollTop; } var targetRow = this.getEventRow(viewportEdge), maxRow = this.getTotalRows()-1, newScrollTop = scrollTop; if (targetRow < 0 || targetRow > maxRow) { this._targetRow = maxRow; this._rowOffset = 0; newScrollTop = this.getRowTop(maxRow); } else { this._targetRow = targetRow; // how far into the target row the top of the viewport should be (positive means more // of row is scrolled offscreen) this._rowOffset = scrollTop - this.getRowTop(this._targetRow) + delta; //var drawArea = this.getDrawArea(); //if (targetRow < drawArea[0] || targetRow > drawArea[1]) { if (Math.abs(this._rowOffset) > this.getViewportHeight()) { // happens only if we are programmatically scrolled by a large amount to a totally // new viewport, in which case anchoring to a row from the old viewport is useless // and could lead to surprises (eg if scrolled near max, scrolling to 10px should // place us on 10px into the first row but might do something different if we // calculate coordinates based on drawn row sizes in a viewport near the end). this.logInfo("storeTargetRow: targetRow: " + targetRow + " with offset: " + this._rowOffset + //" wouldn't fall within draw range: " + [drawArea[0],drawArea[1]] + ", clearing", "virtualScrolling"); this._rowOffset = this._targetRow = null; } } return newScrollTop;},// scroll the previously stored target row into the stored position_scrollToTargetRow : function () { var targetRow = this._targetRow, offset = this._rowOffset; var scrollTop = this.getRowTop(targetRow) + offset; this._literalScroll = true; this._scrollHeight = null; this.scrollTo(null, scrollTop); this._literalScroll = false; // stop reporting last requested scroll ratio since we've now scrolled to match the // requested ratio this._scrollRatio = null;},// if we're rendering rows/cols incrementally, we may need to redraw on scrollscrollTo : function (left, top, cssScroll,d) { if (isc._traceMarkers) arguments.__this = this; if (this.virtualScrolling && top != null && !cssScroll) { var oldScrollTop = this.getScrollTop(), delta = top - oldScrollTop; this._storeTargetRow(oldScrollTop, delta); top = Math.min(top, this.getRowTop(this.getTotalRows()-1)); } this.invokeSuper(isc.GridRenderer, "scrollTo", left,top,cssScroll,d); // don't check for the need to redraw if we're already dirty. Optimization: for // scroll-and-scroll-back situations, we could avoid a redraw by undirtying ourselves if (this.isDirty() || this._noRedraw) return; // if we're only drawing rows near the viewport.. var needRedraw = (this._needRowRedraw() || this._needColumnRedraw()); if (needRedraw) { if (this.scrollRedrawDelay == 0) { this.markForRedraw("scrolled"); } else { this.fireOnPause("scrollRedraw", "markForRedraw", this.scrollRedrawDelay); } this._scrollRedraw = true; }},_needRowRedraw : function () { if (this.showAllRows) return false; // we have a range of records that have been drawn, from grid._firstDrawnRow to // grid._lastDrawnRow (updated in getTableHTML). See if the new viewport falls // completely into the drawn range. // NOTE: we use visible rows rather than viewport fill rows because by using // actual rendered row height we can avoid some redraws when we have several viewports // worth of drawn data due to tall rows. // Note also that visible rows is only an approximation if asked about an undrawn area, // which is fine, because all we care about is whether the new viewport falls // completely within the drawn range. var visibleRows = this.getVisibleRows(), firstVisible = visibleRows[0], lastVisible = visibleRows[1]; // check that the last visible row doesn't exceed the total number of rows we will // draw. NOTE: -1 because totalRows is a count and lastVisible is an index. var totalRows = this.getTotalRows(); if (lastVisible > totalRows-1) lastVisible = totalRows-1; var needRedraw = (firstVisible < this._firstDrawnRow || lastVisible > this._lastDrawnRow); return needRedraw;},_needColumnRedraw : function () { // if we're only drawing columns near the viewport.. if (this.showAllColumns) return false; var visibleCols = this.getVisibleColumns(), firstVisible = visibleCols[0], lastVisible = visibleCols[1], needRedraw = (firstVisible < this._firstDrawnCol || lastVisible > this._lastDrawnCol); return needRedraw;},// disable incremental rendering when overflow:visible is set on the flysetOverflow : function (overflow) { if (overflow == isc.Canvas.VISIBLE) { this.showAllRows = true; this.showAllColumns = true; } return this.Super("setOverflow", arguments);},// Cache DOM mode// ---------------------------------------------------------------------------------------// Mode that caches rendered chunks of the grid area to avoid redrawing as a user revisits the// same area of the grid without having changed anything. Currently incomplete.// === cacheDOM mode limitations// - can't have fixedRecordHeights:false// - does not support row animation// - doesn't work with rowSpans// - shouldn't use with full-row inline edit and large number of columns// - doesn't support startSpace / endSpacegetRowChunkNum : function (logicalRowNum) { return Math.round(logicalRowNum / this._rowChunkSize);},getColChunkNum : function (logicalColNum) { return Math.round(logicalColNum / this._colChunkSize);},getTableChunk : function (rowChunkNum, colChunkNum) { var tableCache = this._tableCache; if (!tableCache) return; // if row and col are unpassed, return the chunk at 0,0 rowChunkNum = rowChunkNum || 0; colChunkNum = colChunkNum || 0; var colCache = tableCache[rowChunkNum]; return colCache ? colCache[colChunkNum] : null;},getTableChunkAt : function (logicalRowNum, logicalColNum) { var rowChunkNum = this.getRowChunkNum(logicalRowNum), colChunkNum = this.getColChunkNum(logicalColNum), tableElem = this.getTableChunk(rowChunkNum, colChunkNum); if (tableElem != null) { // semi-hack: set the offsets used in getTableElement() to find physical cells from // logical cells this._firstDrawRow = rowChunkNum * this._rowChunkSize; this._firstDrawnCol = colChunkNum * this._colChunkSize; return tableElem; }},_updateInnerHTML : function (a,b,c,d) { if (this.cacheDOM) { this.drawVisibleChunks(); } else { this.invokeSuper(isc.GridRenderer, "_updateInnerHTML", a,b,c,d); }},// in cacheDOM mode, this is called in lieue of normal redrawdrawVisibleChunks : function () { // figure out what undrawn chunks are visible and draw them var visibleRows = this.getVisibleRows(), visibleCols = this.getVisibleColumns(), startRowChunk = this.getRowChunkNum(visibleRows[0]), startColChunk = this.getColChunkNum(visibleCols[0]), endRowChunk = this.getRowChunkNum(visibleRows[1]), endColChunk = this.getColChunkNum(visibleCols[1]); for (var rowChunk = startRowChunk; rowChunk < endRowChunk; rowChunk++) { for (var colChunk = startColChunk; colChunk < endColChunk; colChunk++) { if (this.getTableChunk(rowChunk, colChunk) == null) { this.logWarn("drawing chunk: " + [rowChunk, colChunk]); this.renderTableChunk(rowChunk, colChunk); } } } var newHTML = this.getTableHTML();},renderTableChunk : function (rowChunkNum, colChunkNum) { // figure out geometry of table to draw var startRow = rowChunkNum * this._rowChunkSize, endRow = startRow + this._rowChunkSize, startCol = colChunkNum * this._colChunkSize, endCol = startCol + this._colChunkSize; // draw new table chunk var html = this.getTableHTML([startCol, endCol], startRow, endRow), tableElem = isc.Element.insertAdjacentHTML(this.getHandle(), "beforeEnd", html, true); //this.logWarn("html form chunk: " + [rowChunkNum, colChunkNum] + // "\n" + html + // "\nelement: " + this.echo(tableElem)); // cache the table element var tableCache = this._tableCache = this._tableCache || [], colCache = tableCache[rowChunkNum] = tableCache[rowChunkNum] || []; colCache[colChunkNum] = tableElem;},getDrawnRows : function () { return this.getVisibleRows();},//>Animation Row Animation support// ---------------------------------------------------------------------------------------// Methods to animate a show / hide of multiple rows//> @method gridRenderer.startRowAnimation()// Animates a show / hide of rows by growing the rows into view.// Note: the rows to be shown/hidden should already be in the data, and the calling function// is responsible for any manipulation to the data / redraw at the end of this method.// @param show (boolean) are we showing or hiding rows?// @param startRow (number) first row in range to be shown/hidden// @param endRow (number) last row in range to be shown/hidden// @param [callback] (callback) callback to fire when animation completes// @param [speed] (number) speed for the animation in pixels / second// @param [duration] (number) if speed is not set, number of milliseconds for the animation to take// @param [effect] (string) optional acceleration effect for the animation// @param [slideIn] (boolean) if specified, the rows will appear to slide into view rather than // being revealed//<// additional param indicates this was called from the listGrid - we use this to ensure// we fire the callback in the listGrid's scopestartRowAnimation : function (show, startRow, endRow, callback, speed, duration, effect, slideIn, fromListGrid, isDelayed) { // Always call finishRowAnimation - this will no op if there is no current/pending // row animation in progress this.finishRowAnimation(); if (!this.isDrawn() || !this.isVisible()) { if (callback != null) { var target = fromListGrid ? this.parentElement : this; target.fireCallback(callback); } return; } if (show == null) show = true; if (startRow == null) startRow = 0; if (endRow == null) endRow = this.getTotalRows() - 1; if (startRow == endRow) { this.logWarn("startRowAnimation passed empty row range, aborting: " + [startRow, endRow]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -