📄 sync.datagrid.js
字号:
/** * Creates a new Region. * * @param {Extras.Sync.DataGrid} dataGrid the containing data grid synchronization peer * @param {String} name the region name, one of the following values: * topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight */ $construct: function(dataGrid, name) { this.dataGrid = dataGrid; this.name = name; this._tiles = { }; this.location = Extras.Sync.DataGrid.REGION_LOCATIONS[name]; this.element = document.createElement("div"); this.element.style.cssText = "position:absolute;overflow:hidden;"; if (this.location.h === -1) { this.element.style.left = 0; } else if (this.location.h === 1) { this.element.style.right = 0; } if (this.location.v === -1) { this.element.style.top = 0; } else if (this.location.h === 1) { this.element.style.bottom = 0; } }, /** * Adjusts the positions of tiles within the region, additionally filling in any areas that become * unoccupied as a result of the adjustment. * * @param {Number} x the number of horizontal pixels to shift the tiles (positive values indicate to the right) * @param {Number} y the number of vertical pixels to shift the tiles (positive values indicate downward) */ adjustPosition: function(x, y) { if (this.location.h && this.location.y) { // This operation has no effect on corner tiles. return; } x = this.location.h ? 0 : x; y = this.location.v ? 0 : y; var row, tile; for (var rowIndex in this._tiles) { row = this._tiles[rowIndex]; for (var columnIndex in row) { tile = row[columnIndex]; tile.adjustPosition(x, y); } } this.fill(y > 0); }, /** * Clears the region of tiles, removing/disposing all tile objects in the process. */ clear: function() { for (var rowIndex in this._tiles) { var row = this._tiles[rowIndex]; for (var columnIndex in row) { var tile = row[columnIndex]; tile.remove(); tile.dispose(); } } this._tiles = { }; }, /** * Displays a tile immediately adjacent to a tile. * * @param {Echo.Sync.DataGrid.Tile} tile the origin tile * @param direction the adjacent direction, one of the following values (defined in Extras.Sync.DataGrid): * <ul> * <li><code>LEFT</code></li> * <li><code>RIGHT</code></li> * <li><code>UP</code></li> * <li><code>DOWN</code></li> * </ul> * @return the adjacent tile * @type Echo.Sync.DataGrid.Tile */ displayTileAdjacent: function(tile, direction) { if (!tile.displayed) { throw new Error("Tile not displayed, cannot position adjacent tile: " + tile); } var adjacentTile = this.getTile(tile.tileIndex.column + direction.h, tile.tileIndex.row + direction.v); if (adjacentTile == null) { return null; } adjacentTile.display(tile.bounds.left + (tile.bounds.width * direction.h), tile.bounds.top + (tile.bounds.height * direction.v)); return adjacentTile; }, /** * Ensures the region is filled with content. Invoked after the viewport has been scrolled. * * @param {Boolean} fromBottom flag indicating whether filling should start from the bottom (true) or top (false) */ fill: function(fromBottom) { // Find top/bottommost tile. var originTile = this._findVerticalEdgeTile(fromBottom); // Move left, displaying tiles until left edge tile is reached. while (!originTile.isEdgeLeft()) { originTile = this.displayTileAdjacent(originTile, Extras.Sync.DataGrid.LEFT); } if (originTile == null) { //FIXME impl. alert("FIXME...can't find origin tile, scenario not handled yet."); } else { do { // Move right. var tile = originTile; while (tile.isOnScreen() && !tile.isEdgeRight()) { tile = this.displayTileAdjacent(tile, Extras.Sync.DataGrid.RIGHT); } // Move down/up. originTile = this.displayTileAdjacent(originTile, fromBottom ? Extras.Sync.DataGrid.UP : Extras.Sync.DataGrid.DOWN); } while (originTile != null && originTile.isOnScreen()); } }, /** * Finds the topmost or bottommost tile that is on screen. The found tile may be anywhere in the row. * * @param {Boolean} bottom flag indicating whether topmost (false) or bottommost (true) tile should be returned */ _findVerticalEdgeTile: function(bottom) { var row, tile, topRowIndex = null, rowIndex; for (rowIndex in this._tiles) { if (topRowIndex == null || (bottom ? (rowIndex > topRowIndex) : (rowIndex < topRowIndex))) { row = this._tiles[rowIndex]; for (var columnIndex in row) { if (row[columnIndex].isOnScreen()) { tile = row[columnIndex]; topRowIndex = rowIndex; break; } } } } return tile; }, getTile: function(columnIndex, rowIndex) { if (columnIndex < 0 || rowIndex < 0 || rowIndex > this.dataGrid.size.rows / this.dataGrid.tileSize.rows || columnIndex > this.dataGrid.size.columns / this.dataGrid.tileSize.columns) { return null; } var cachedRow = this._tiles[rowIndex]; if (!cachedRow) { cachedRow = { }; this._tiles[rowIndex] = cachedRow; } var tile = cachedRow[columnIndex]; if (!tile) { tile = new Extras.Sync.DataGrid.Tile(this.dataGrid, this, columnIndex, rowIndex); cachedRow[columnIndex] = tile; } return tile; }, /** * Sets the position of the region. Invocation will clear all existing tiles. * * @param {Number} x the horizontal position of the region * @param {Number} the units of the horizontal position, one of the following values: * <ul> * <li><code>Extras.Sync.DataGrid.INDEX</code>: indicates the position value will * describe the index of the leftmost tile (may be a decimal value)</li> * <li><code>Extras.Sync.DataGrid.PERCENT</code>: indicates the percentile of the tile * that will be displayed in the center of the region, e.g., a value of 50 would * display the middle tile in the center of the screen</li> * </ul> * @param {Number} x the vertical position of the region * @param {Number} the units of the vertical position, one of the following values: * <ul> * <li><code>Extras.Sync.DataGrid.INDEX</code>: indicates the position value will * describe the index of the topmost tile (may be a decimal value)</li> * <li><code>Extras.Sync.DataGrid.PERCENT</code>: indicates the percentile of the tile * that will be displayed in the center of the region, e.g., a value of 50 would * display the middle tile in the center of the screen</li> * </ul> */ setPosition: function(x, xUnits, y, yUnits) { var tileRowIndex, tileColumnIndex, initTileColumnIndex, cursorXPx, cursorYPx, tile; this.clear(); switch (xUnits) { case Extras.Sync.DataGrid.INDEX: initTileColumnIndex = Math.floor(x / this.dataGrid.tileSize.columns); break; case Extras.Sync.DataGrid.PERCENT: throw new Error("Not yet supported."); default: throw new Error("Invalid yUnits: " + yUnits); } switch (yUnits) { case Extras.Sync.DataGrid.INDEX: tileRowIndex = Math.floor(y / this.dataGrid.tileSize.rows); break; case Extras.Sync.DataGrid.PERCENT: throw new Error("Not yet supported."); default: throw new Error("Invalid yUnits: " + yUnits); } cursorYPx = 0; while (cursorYPx < this.bounds.height) { tileColumnIndex = initTileColumnIndex; cursorXPx = 0; while (cursorXPx < this.bounds.width) { tile = this.getTile(tileColumnIndex, tileRowIndex); tile.display(cursorXPx, cursorYPx); if (tile.isEdgeRight()) { break; } cursorXPx += tile.bounds.width; ++tileColumnIndex; } if (tile.isEdgeBottom()) { break; } cursorYPx += tile.bounds.height; ++tileRowIndex; } }, /** * Updates the rendered bounds of the region. The values passed always indicate the pixel bounds of the * center region of the DataGrid. * * @param {Number} left the offset from the left edge of the DataGrid to the left edge of the center region * @param {Number} top the offset from the top edge of the DataGrid to the top edge of the center region * @param {Number} right the offset from the right edge of the DataGrid to the right edge of the center region * @param {Number} bottom the offset from the bottom edge of the DataGrid to the bottom edge of the center region */ updateBounds: function(left, top, right, bottom) { this.bounds = { }; switch (this.location.h) { case -1: this.element.style.width = left + "px"; this.bounds.width = left; break; case 0: this.element.style.left = left + "px"; this.element.style.right = right + "px"; this.bounds.width = this.dataGrid.scrollContainer.bounds.width - left - right; break; case 1: this.element.style.width = right + "px"; this.bounds.width = right; break; } switch (this.location.v) { case -1: this.element.style.height = top + "px"; this.bounds.height = top; break; case 0: this.element.style.top = top + "px"; this.element.style.bottom = bottom + "px"; this.bounds.height = this.dataGrid.scrollContainer.bounds.height - top - bottom; break; case 1: this.element.style.height = bottom + "px"; this.bounds.height = bottom; break; } } }) }, /** * Number of rows per tile. The last tile may have fewer rows. */ tileSize: { columns: 12, rows: 6 }, _fullRenderRequired: null, /** * The row to display at the topmost point of the viewable area. This value may be have a fractional part, * indicating that only part of the row is visible. */ _displayRowIndex: null, /** * The column to display at the leftmost point of the viewable area. This value may be have a fractional part, * indicating that only part of the column is visible. */ _displayColumnIndex: null, /** * The percentile of rows displayed on the viewable area, with 0% representing the topmost set of rows and 100% * representing the bottommost set of rows. This value may have a fractional part. */ _displayRowPercent: null, /** * The percentile of columns displayed on the viewable area, with 0% representing the leftmost set of columns and 100% * representing the rightmost set of columns. This value may have a fractional part. */ _displayColumnPercent: null, /** * Root DIV element of rendered component. */ _div: null, regions: null, /** * Data model. */ _model: null, /** * Size of grid in rows and columns. Contains numeric rows and columns properties. */ size: null, /** * Number of fixed cells in left, top, right, and bottom sides of the DataGrid. * Contains numeric left, top, right, and bottom properties. */ fixedCells: null, fixedCellSizes: null, /** * The ScrollContainer. */ scrollContainer: null, $construct: function() { this._div = null; this._displayRowIndex = 0; this._displayColumnIndex = 0; }, adjustPosition: function(x, y) { for (var name in this.regions) { this.regions[name].adjustPosition(x, y); } }, _createRegions: function() { this.regions = { }; if (this.fixedCells.top) { if (this.fixedCells.left) { this.regions.topLeft = new Extras.Sync.DataGrid.Region(this, "topLeft"); } this.regions.top = new Extras.Sync.DataGrid.Region(this, "top"); if (this.fixedCells.right) { this.regions.topRight = new Extras.Sync.DataGrid.Region(this, "topRight"); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -