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.
671 lines • 21.7 kB
JavaScript
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, "loadingElement", {
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, "domSelectionStr", {
enumerable: true,
configurable: true,
writable: true,
value: ''
});
Object.defineProperty(this, "isMouseoverTargetContainer", {
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, "isEmpty", {
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, "disableHoverIconClick", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 禁用hoverIconClick,防止填充选择器移动时,触发hoverIconClick
Object.defineProperty(this, "selectColsIng", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 选择列中
Object.defineProperty(this, "selectRowsIng", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 选择行中
Object.defineProperty(this, "dragHeaderIng", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 拖拽表头中
Object.defineProperty(this, "finding", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 查找中
Object.defineProperty(this, "adjustPositioning", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 调整位置中
Object.defineProperty(this, "contextMenuIng", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 右键菜单中
Object.defineProperty(this, "editing", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 编辑中
Object.defineProperty(this, "loading", {
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, "hasSelection", {
enumerable: true,
configurable: true,
writable: true,
value: false
}); // 是否有选中
Object.defineProperty(this, "hasTree", {
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, "lastCenterColIndex", {
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, "currentCell", {
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, "mouseX", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
Object.defineProperty(this, "mouseY", {
enumerable: true,
configurable: true,
writable: true,
value: 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: [],
allCellHeaders: [],
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, "finderBar", {
enumerable: true,
configurable: true,
writable: true,
value: {
text: '',
rowIndex: -1,
colIndex: -1,
type: 'body',
}
});
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, loadingElement, contextMenuElement, } = containerOptions;
this.containerElement = containerElement;
stageElement.tabIndex = 0; // 设置为可获取焦点
this.stageElement = stageElement;
this.canvasElement = canvasElement;
this.overlayerElement = overlayerElement;
this.editorElement = editorElement;
this.emptyElement = emptyElement;
this.loadingElement = loadingElement;
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, checkReadonly = true) {
// 启用合并单元格关联
if (this.config.ENABLE_MERGE_CELL_LINK) {
const cell = this.database.getVirtualBodyCellByKey(rowKey, key);
if (cell && (cell.mergeRow || cell.mergeCol)) {
const { dataList } = cell.getSpanInfo();
const data = dataList.map((item) => ({ ...item, value }));
this.database.batchSetItemValue(data, history, checkReadonly);
return;
}
}
this.database.setItemValue(rowKey, key, value, history, reDraw, true, checkReadonly);
}
batchSetItemValueByEditor(_list, history = true, checkReadonly = true) {
// 启用合并单元格关联
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);
}
});
this.database.batchSetItemValue(list, history, checkReadonly);
}
else {
this.database.batchSetItemValue(_list, history, checkReadonly);
}
}
setFocusCell(cell) {
if (this.focusCell === cell)
return;
if (this.focusCell?.rowKey !== cell.rowKey) {
// 提前设置一下,保证rowFocusChange事件,能用focusCell
this.currentCell = cell;
this.emit('rowFocusChange', cell);
const data = {
rowIndex: cell.rowIndex,
rowKey: cell.rowKey,
row: cell.row,
};
this.emit('currentRowChange', data);
}
this.focusCell = cell;
this.emit('cellFocusChange', cell);
}
clearSelector() {
this.selector.enable = false;
this.selector.xArr = [-1, -1];
this.selector.yArr = [-1, -1];
this.emit('clearSelector');
}
clearSelectorCopy() {
this.selector.xArrCopy = [-1, -1];
this.selector.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 cell = this.database.getVirtualBodyCell(rowIndex, colIndex);
if (cell) {
// 选择器值类型
if (cell.selectorCellValueType === 'displayText') {
cellsData.push(cell.displayText);
}
else {
// 默认value
cellsData.push(cell.getValue());
}
}
}
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);
}
startAdjustPosition(e) {
this.emit('startAdjustPosition', e);
}
stopAdjustPosition() {
this.emit('stopAdjustPosition');
}
isTarget(e) {
if (!this.containerElement.contains(e.target)) {
return false;
}
return true;
}
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