📄 sync.datagrid.js
字号:
/** * Component rendering peer: DataGrid * * This is an EXPERIMENTAL component, it should not be used at this point for any purpose other than testing it. */Extras.Sync.DataGrid = Core.extend(Echo.Render.ComponentSync, { $load: function() { Echo.Render.registerPeer("Extras.DataGrid", this); }, $static: { LEFT: { h: -1, v: 0 }, RIGHT: { h: 1, v: 0 }, UP: { h: 0, v: -1 }, DOWN: { h: 0, v: 1 }, INDEX: 0, PX: 1, PERECNT: 2, REGION_LOCATIONS: { topLeft: { h: -1, v: -1 }, top: { h: 0, v: -1 }, topRight: { h: 1, v: -1 }, left: { h: -1, v: 0 }, center: { h: 0, v: 0 }, right: { h: 1, v: 0 }, bottomLeft: { h: -1, v: 1 }, bottom: { h: 0, v: 1 }, bottomRight: { h: 1, v: 1 } }, /** * Determines if two segments in a line share any points. * * @param {Number} a1 first point of segment A * @param {Number} a2 second point of segment A * @param {Number} b1 first point of segment B * @param {Number} b2 second point of segment B * @return true if the segments share any points */ intersect: function(a1, a2, b1, b2) { return (b1 <= a1 && a1 <= b2) || (a1 <= b1 && b1 <= a2); }, /** * Representation of a "tile", a sub-table that renders a portion of the DataGrid. * Tiles are contained within Regions. */ Tile: Core.extend({ /** * The containing DataGrid instance. * @type Extras.Sync.DataGrid */ dataGrid: null, /** * Flag indicating whether the tile is displayed. * @type Boolean */ displayed: false, /** * The div element. Outermost element of a tile, contains the <code>_table</code> element as its only child. * @type Element */ div: null, /** * The table element. Contained within the <code>div</code> element. * @type Element */ _table: null, /** * The region containing the tile. * @type Extras.Sync.DataGrid.Region */ region: null, /** * Edge information object. Contains boolean "top", "right", "left", and "bottom" properties, * each of which evaluates to true if the tile is at that extreme edge. */ edge: null, /** * Cell index information object. Contains integer "top", "right", "left", and "bottom" properties, * each of which indicates the index of cells at that edge of the tile. */ cellIndex: null, /** * Tile index information object. Contains row and column properties indicating the row/column of the tile * within the grid of tiles. */ tileIndex: null, /** * The rendered bounds of the tile. Contains "top", "left", "width", and "height" properties describing * rendered bounds of the tile. Initialized when the tile is displayed. */ bounds: null, /** * Creates a new <code>Tile</code>. * * @param {Extras.Sync.DataGrid} dataGrid the containing data grid peer * @param {Extras.Sync.DataGrid.Region} region the containing region * @param {Number} tileColumnIndex the column index of the tile * @param {Number} tileRowIndex the row index of the tile */ $construct: function(dataGrid, region, tileColumnIndex, tileRowIndex) { this.dataGrid = dataGrid; this.containerElement = region.element; this.tileIndex = { column: tileColumnIndex, row: tileRowIndex }; this.region = region; this.cellIndex = { }; // Determine left cell. switch (this.region.location.h) { case 0: this.cellIndex.left = this.tileIndex.column * this.dataGrid.tileSize.columns + this.dataGrid.fixedCells.left; break; case -1: this.cellIndex.left = this.tileIndex.column * this.dataGrid.tileSize.columns; break; case 1: // FIXME Impl. throw new Error("unsupported"); } // Determine top cell. switch (this.region.location.v) { case 0: this.cellIndex.top = this.tileIndex.row * this.dataGrid.tileSize.rows + this.dataGrid.fixedCells.top; break; case -1: this.cellIndex.top = this.tileIndex.row * this.dataGrid.tileSize.rows; break; case 1: // FIXME Impl. throw new Error("unsupported"); } this.edge = { left: this.tileIndex.column === 0, top: this.tileIndex.row === 0 }; // Determine right cell. this.cellIndex.right = this.cellIndex.left + this.dataGrid.tileSize.columns - 1; if (this.cellIndex.right >= this.dataGrid.size.columns - this.dataGrid.fixedCells.right - 1) { this.cellIndex.right = this.dataGrid.size.columns - this.dataGrid.fixedCells.right - 1; this.edge.right = true; } // Determine bottom cell. this.cellIndex.bottom = this.cellIndex.top + this.dataGrid.tileSize.rows - 1; if (this.cellIndex.bottom >= this.dataGrid.size.rows - this.dataGrid.fixedCells.bottom - 1) { this.cellIndex.bottom = this.dataGrid.size.rows - this.dataGrid.fixedCells.bottom - 1; this.edge.bottom = true; } }, /** * Adjusts the position of the tile. * Has no effect in directions in which the cell is fixed (per region location property). * * @param {Number} h the number of pixels to adjust the tile horizontally * @param {Number} v the number of pixels to adjust the tile vertically */ adjustPosition: function(h, v) { if (this.div) { if (h && !this.region.location.h) { this.bounds.left += h; this.div.style.left = this.bounds.left + "px"; } if (v && !this.region.location.v) { this.bounds.top += v; this.div.style.top = this.bounds.top + "px"; } } if (!this.isOnScreen()) { this.remove(); } }, /** * Renders the tile. Sets the div and _table element properties, measures rendered tile and sets * bounds property. */ create: function() { var tr, td, row, column; var columnWidths = []; this.bounds = { }; this.bounds.width = 0; for (column = this.cellIndex.left; column <= this.cellIndex.right; ++column) { this.bounds.width += columnWidths[column] = this.dataGrid._getColumnWidth(column); } this.div = document.createElement("div"); this.div.style.cssText = "position:absolute;"; this._table = this.dataGrid.getPrototypeTable().cloneNode(true); this._table.style.width = this.bounds.width + "px"; this.div.appendChild(this._table); for (row = this.cellIndex.top; row <= this.cellIndex.bottom; ++row) { tr = document.createElement("tr"); for (column = this.cellIndex.left; column <= this.cellIndex.right; ++column) { td = document.createElement("td"); td.style.padding = 0; Echo.Sync.Border.render(this.dataGrid._cellBorder, td); if (row === this.cellIndex.top) { td.style.width = columnWidths[column] + "px"; } td.appendChild(document.createTextNode(this.dataGrid._model.get(column, row))); tr.appendChild(td); } this._table.firstChild.appendChild(tr); } this.bounds.height = new Core.Web.Measure.Bounds(this.div).height; this.div.style.width = this.bounds.width + "px"; }, /** * Displays the tile at the specified coordinates. * Does nothing if the tile is already displayed. * * @param {Number} left the left pixel coordinate of the tile within the region * @param {Number} top the top pixel coordinate of the tile within the region */ display: function(left, top) { if (this.displayed) { return; } if (!this.div) { this.create(); } this.bounds.top = top; this.bounds.left = left; this.div.style.top = top + "px"; this.div.style.left = left + "px"; this.containerElement.appendChild(this.div); this.displayed = true; }, /** * Disposes resources used by the tile. * Must be invoked before the tile is discarded. */ dispose: function() { this.div = this._table = null; }, /** * Determines if this tile is currently covering the bottom edge of the screen (pixel 0). */ isEdgeBottom: function() { return this.edge.bottom || (this.bounds.top < this.region.bounds.height && this.bounds.top + this.bounds.height >= this.region.bounds.height); }, /** * Determines if this tile is currently covering the left edge of the screen (pixel 0). */ isEdgeLeft: function() { return this.edge.left || this.tileIndex.column === 0 || (this.bounds.left <= 0 && this.bounds.left + this.bounds.width > 0); }, /** * Determines if this tile is currently covering the left edge of the screen (pixel 0). */ isEdgeRight: function() { return this.edge.right || (this.bounds.left < this.region.bounds.width && this.bounds.left + this.bounds.width >= this.region.bounds.width); }, /** * Determines if this tile is currently covering the top edge of the screen (pixel 0). */ isEdgeTop: function() { return this.edge.top || this.tileIndex.row === 0 || (this.bounds.top <= 0 && this.bounds.top + this.bounds.height > 0); }, /** * Determines if any portion of this tile is currently on screen. */ isOnScreen: function() { if (!this.displayed) { return false; } return Extras.Sync.DataGrid.intersect(this.bounds.left, this.bounds.left + this.bounds.width, 0, this.region.bounds.width) && Extras.Sync.DataGrid.intersect(this.bounds.top, this.bounds.top + this.bounds.height, 0, this.region.bounds.height); }, /** * Disposes of resources used by the tile. */ remove: function() { if (this.displayed) { this.div.parentNode.removeChild(this.div); this.displayed = false; } }, /** @see Object#toString */ toString: function() { return "Tile (" + this.tileIndex.column + "," + this.tileIndex.row + ")"; } }), /** * Represents a region of the DataGrid. A DataGrid may have up to nine regions, arranged as three * rows and three columns. Regions in the center row can be vertically scrolled, while the top and bottom rows * are vertically fixed. Regions in the center column can be horizontally scrolled , while the left and right * columns are horizontally fixed. */ Region: Core.extend({ /** * The containing Extras.Sync.DataGrid instance. * @type Extras.Sync.DataGrid */ dataGrid: null, /** * Object containing all <code>Tile</code> instances held within the region. * This object maps tile row indices to tile column maps. * The tile column maps map column indices to actual tiles. * The indices used are the indices of tiles, not the indices of the cells they contain. * This object is organized like a two dimensional array, with rows as the first dimension and columns as the seccond, * e.g., requesting _tiles[4][2] would return the tile at row 4 (the fifth row) and column 2 (the third column). * Before making such a query one would have to ensure that _tiles[4] is defined. */ _tiles: null, /** * */ bounds: null, /** * The region name one of the following values: * topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight * @type String */ name: null, /** * The location of the region, an object containing h and v properties. * These h and v properties may have values of -1, 0, or 1. * A value of 0 indicates center, -1 indicates left/top, 1 indicates right/bottom. */ location: null,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -