UNPKG

e-virt-table

Version:

A powerful data table based on canvas. You can use it as data grid、Microsoft Excel or Google sheets. It supports virtual scroll、cell edit etc.

554 lines 17.9 kB
import Database from './Database'; import History from './History'; import EventBrowser from './EventBrowser'; import EventBus from './EventBus'; import Paint from './Paint'; import Config from './Config'; import Icons from './Icons'; import EventTable from './EventTable'; export default class Context { constructor(containerOptions, options) { Object.defineProperty(this, "eventBus", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "eventBrowser", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "eventTable", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "containerElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "stageElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "canvasElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "overlayerElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "editorElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "emptyElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "contextMenuElement", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "stageWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "stageHeight", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "paint", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "icons", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "isInsideTargetContainer", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "mousedown", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "isPointer", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "rowResizing", { enumerable: true, configurable: true, writable: true, value: false }); // 行调整大小中 Object.defineProperty(this, "columnResizing", { enumerable: true, configurable: true, writable: true, value: false }); // 列调整大小中 Object.defineProperty(this, "scrollerMove", { enumerable: true, configurable: true, writable: true, value: false }); // 滚动条移动中 Object.defineProperty(this, "scrollerFocus", { enumerable: true, configurable: true, writable: true, value: false }); // 滚动条focus中 Object.defineProperty(this, "autofillMove", { enumerable: true, configurable: true, writable: true, value: false }); // 自动填充移动中 Object.defineProperty(this, "selectorMove", { enumerable: true, configurable: true, writable: true, value: false }); // 选择器移动中 Object.defineProperty(this, "adjustPositioning", { enumerable: true, configurable: true, writable: true, value: false }); // 调整位置中 Object.defineProperty(this, "editing", { enumerable: true, configurable: true, writable: true, value: false }); // 编辑中 Object.defineProperty(this, "onlyMergeCell", { enumerable: true, configurable: true, writable: true, value: false }); // 只有合并单元格 Object.defineProperty(this, "selectOnlyOne", { enumerable: true, configurable: true, writable: true, value: false }); // 只选择一个 Object.defineProperty(this, "scrollY", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "scrollX", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "fixedLeftWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "fixedRightWidth", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "maxColIndex", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "maxRowIndex", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "hoverRow", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "clickCell", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "focusCell", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "hoverCell", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "clickCellHeader", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "focusCellHeader", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "hoverCellHeader", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "body", { enumerable: true, configurable: true, writable: true, value: { x: 0, y: 0, width: 0, height: 0, visibleHeight: 0, visibleWidth: 0, headIndex: 0, tailIndex: 0, visibleRows: [], renderRows: [], data: [], } }); Object.defineProperty(this, "footer", { enumerable: true, configurable: true, writable: true, value: { x: 0, y: 0, width: 0, height: 0, visibleHeight: 0, visibleWidth: 0, renderRows: [], } }); Object.defineProperty(this, "header", { enumerable: true, configurable: true, writable: true, value: { x: 0, y: 0, width: 0, height: 0, visibleHeight: 0, visibleWidth: 0, visibleLeafColumns: [], leafCellHeaders: [], renderLeafCellHeaders: [], renderCellHeaders: [], fixedLeftCellHeaders: [], fixedRightCellHeaders: [], renderCenterCellHeaders: [], } }); Object.defineProperty(this, "selector", { enumerable: true, configurable: true, writable: true, value: { enable: false, xArr: [-1, -1], yArr: [-1, -1], xArrCopy: [-1, -1], yArrCopy: [-1, -1], } }); Object.defineProperty(this, "autofill", { enumerable: true, configurable: true, writable: true, value: { enable: false, xArr: [-1, -1], yArr: [-1, -1], } }); Object.defineProperty(this, "database", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "history", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "config", { enumerable: true, configurable: true, writable: true, value: void 0 }); const { containerElement, stageElement, canvasElement, overlayerElement, editorElement, emptyElement, contextMenuElement, } = containerOptions; this.containerElement = containerElement; stageElement.tabIndex = 0; // 设置为可获取焦点 this.stageElement = stageElement; this.canvasElement = canvasElement; this.overlayerElement = overlayerElement; this.editorElement = editorElement; this.emptyElement = emptyElement; this.contextMenuElement = contextMenuElement; this.config = new Config(options.config || {}); this.eventBus = new EventBus(); this.eventBrowser = new EventBrowser(this); this.eventTable = new EventTable(this); this.paint = new Paint(this.canvasElement); this.database = new Database(this, options); this.history = new History(this); this.icons = new Icons(this); } setConfig(config) { this.config = new Config(config); } setItemValueByEditor(rowKey, key, value, history = true, reDraw = true) { // 启用合并单元格关联 if (this.config.ENABLE_MERGE_CELL_LINK) { const rowIndex = this.database.getRowIndexForRowKey(rowKey); const colIndex = this.database.getColIndexForKey(key); if (rowIndex === undefined || colIndex === undefined) return; const cell = this.database.getVirtualBodyCell(rowIndex, colIndex); if (cell) { const { dataList } = cell.getSpanInfo(); const data = dataList.map((item) => ({ ...item, value })); this.database.batchSetItemValue(data, history); } } else { this.database.setItemValue(rowKey, key, value, history, reDraw, true); } } batchSetItemValueByEditor(_list, history) { // 启用合并单元格关联 if (this.config.ENABLE_MERGE_CELL_LINK) { const list = []; _list.forEach((item) => { const rowIndex = this.database.getRowIndexForRowKey(item.rowKey); const colIndex = this.database.getColIndexForKey(item.key); if (rowIndex === undefined || colIndex === undefined) return; const cell = this.database.getVirtualBodyCell(rowIndex, colIndex); if (cell) { const { dataList } = cell.getSpanInfo(); const data = dataList.map((list) => ({ ...list, value: item.value })); list.push(...data); } }); // 去重 // const uniqueData = list.reduce((acc, curr) => { // // 检查组合的 rowKey 和 key 是否已存在 // const exists = acc.some((item) => item.rowKey === curr.rowKey && item.key === curr.key); // if (!exists) { // acc.push(curr); // 如果不存在,则添加到结果数组中 // } // return acc; // }, [] as typeof list); this.database.batchSetItemValue(list, history); } else { this.database.batchSetItemValue(_list, history); } } setFocusCell(cell) { if (this.focusCell === cell) return; if (this.focusCell?.rowKey !== cell.rowKey) { // 提前设置一下,保证rowFocusChange事件,能用focusCell this.focusCell = cell; this.emit('rowFocusChange', cell); } this.focusCell = cell; this.emit('cellFocusChange', cell); } clearSelector() { this.selector = { enable: false, xArr: [-1, -1], yArr: [-1, -1], xArrCopy: [-1, -1], yArrCopy: [-1, -1], }; } clearAutofill() { this.autofill = { enable: false, xArr: [-1, -1], yArr: [-1, -1], }; } /** * 获取选中的数据 * @returns */ getSelectedData() { const rowsData = []; const yArr = this.selector.yArr; const xArr = this.selector.xArr; let text = ''; for (let ri = 0; ri <= yArr[1] - yArr[0]; ri++) { const cellsData = []; for (let ci = 0; ci <= xArr[1] - xArr[0]; ci++) { const rowIndex = ri + yArr[0]; const colIndex = ci + xArr[0]; const item = this.database.getItemValueForRowIndexAndColIndex(rowIndex, colIndex); if (item) { cellsData.push(item.value); } } text += `${cellsData.join('\t')}\r`; rowsData.push(cellsData); } text = text ? text.replace(/\r$/, '') : ' '; // 去掉最后一个\n,否则会导致复制到excel里多一行空白 return { xArr, yArr, text, value: rowsData, }; } setScroll(x, y) { let scrollX = Math.floor(x); const scrollMaxX = this.body.width - this.body.visibleWidth; // x边界处理 if (scrollX < 0) { scrollX = 0; } else if (scrollX > scrollMaxX) { scrollX = scrollMaxX; } // y边界处理 let scrollY = Math.floor(y); let scrollMaxY = this.body.height - this.body.visibleHeight; if (!this.config.FOOTER_FIXED) { scrollMaxY = this.body.height + this.footer.height - this.body.visibleHeight; } if (scrollY < 0) { scrollY = 0; } else if (scrollY > scrollMaxY) { scrollY = scrollMaxY; } this.emit('setScroll', scrollX, scrollY); } setScrollX(x) { let scrollX = Math.floor(x); const scrollMaxX = this.body.width - this.body.visibleWidth; // 边界处理 if (scrollX < 0) { scrollX = 0; } else if (scrollX > scrollMaxX) { scrollX = scrollMaxX; } this.emit('setScrollX', scrollX); } setScrollY(y) { // 边界处理 let scrollY = Math.floor(y); let footerHeight = 0; if (!this.config.FOOTER_FIXED) { footerHeight = this.footer.height; } const scrollMaxY = this.body.height - this.body.visibleHeight + footerHeight; if (scrollY < 0) { scrollY = 0; } else if (scrollY > scrollMaxY) { scrollY = scrollMaxY; } this.emit('setScrollY', scrollY); } isTarget() { // 鼠标在容器内 return this.isInsideTargetContainer; } getOffset(e) { const { left, top } = this.containerElement.getBoundingClientRect(); return { offsetX: e.clientX - left, offsetY: e.clientY - top, }; } hasEvent(event) { return this.eventBus.has(event); } on(event, callback) { this.eventBus.on(event, callback); } once(event, callback) { this.eventBus.once(event, callback); } off(event, callback) { this.eventBus.off(event, callback); } emit(event, ...args) { this.eventBus.emit(event, ...args); } destroy() { this.eventTable.destroy(); this.eventBrowser.destroy(); this.eventBus.destroy(); } } //# sourceMappingURL=Context.js.map