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.
137 lines • 4.66 kB
JavaScript
import { computePosition, offset, flip, shift } from '@floating-ui/dom';
export default class ContextMenu {
constructor(ctx) {
Object.defineProperty(this, "ctx", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "contextMenuEl", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "custom", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
this.ctx = ctx;
if (this.ctx.contextMenuElement) {
this.custom = true;
this.contextMenuEl = this.ctx.contextMenuElement;
}
else {
this.custom = false;
this.contextMenuEl = document.createElement('div');
}
this.createContextMenu();
this.init();
}
init() {
this.ctx.on('cellContextMenuClick', (cell, e) => {
if (!this.ctx.config.ENABLE_CONTEXT_MENU)
return;
e.preventDefault();
const { xArr, yArr } = this.ctx.selector;
const [minX, maxX] = xArr;
const [minY, maxY] = yArr;
const { rowIndex, colIndex } = cell;
//判断是否在范围内
const isInRange = rowIndex >= minY && rowIndex <= maxY && colIndex >= minX && colIndex <= maxX;
if (!isInRange) {
this.ctx.emit('setSelectorCell', cell, e);
}
const virtualReference = {
getBoundingClientRect: () => ({
width: 0,
height: 0,
top: e.clientY,
left: e.clientX,
right: e.clientX,
bottom: e.clientY,
x: e.clientX,
y: e.clientY,
}),
contextElement: document.body,
};
computePosition(virtualReference, this.contextMenuEl, {
placement: 'right-start',
middleware: [offset(), shift(), flip()],
}).then(({ x, y }) => {
this.show(x, y);
});
});
this.ctx.on('click', this.hide.bind(this));
this.ctx.on('onScroll', this.hide.bind(this));
this.ctx.on('resize', this.hide.bind(this));
}
//创建右键菜单,绑定子项点击事件
createContextMenu() {
this.contextMenuEl.className = 'e-virt-table-context-menu';
this.ctx.containerElement.appendChild(this.contextMenuEl);
// 如果是自定义右键菜单,则不创建默认子菜单
if (this.custom)
return;
const { CONTEXT_MENU } = this.ctx.config;
this.createContextMenuItems(CONTEXT_MENU, (item) => {
switch (item.value) {
case 'copy':
this.ctx.emit('contextMenuCopy');
break;
case 'paste':
this.ctx.emit('contextMenuPaste');
break;
case 'cut':
this.ctx.emit('contextMenuCut');
break;
case 'clearSelected':
this.ctx.emit('contextMenuClearSelected');
break;
default:
}
this.hide();
});
}
//创建右键菜单子项元素
createContextMenuItems(items, callback) {
this.contextMenuEl.replaceChildren();
items.forEach((item) => {
const menuItemEl = document.createElement('div');
menuItemEl.className = 'e-virt-table-context-menu-item';
menuItemEl.innerText = item.label;
if (item.event) {
menuItemEl.onclick = () => {
item.event && item.event();
callback(item);
};
}
else {
menuItemEl.onclick = () => callback(item);
}
this.contextMenuEl.appendChild(menuItemEl);
});
}
show(x, y) {
Object.assign(this.contextMenuEl.style, {
left: `${x}px`,
top: `${y}px`,
});
}
hide() {
Object.assign(this.contextMenuEl.style, {
left: '-99999px',
top: '-99999px',
});
}
updated() {
this.createContextMenu();
}
destroy() {
this.contextMenuEl.remove();
}
}
//# sourceMappingURL=ContextMenu.js.map