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.
205 lines • 7.45 kB
JavaScript
import { computePosition, offset, arrow, flip, shift } from '@floating-ui/dom';
export default class Tooltip {
constructor(ctx) {
Object.defineProperty(this, "ctx", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "enable", {
enumerable: true,
configurable: true,
writable: true,
value: false
});
Object.defineProperty(this, "contentEl", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "floatingEl", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "arrowEl", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.ctx = ctx;
const { TOOLTIP_BG_COLOR, TOOLTIP_TEXT_COLOR, TOOLTIP_ZINDEX, TOOLTIP_CUSTOM_STYLE, CSS_PREFIX } = this.ctx.config;
this.contentEl = document.createElement('div');
this.arrowEl = document.createElement('div');
this.floatingEl = document.createElement('div');
this.floatingEl.className = `${CSS_PREFIX}-tooltip`;
this.contentEl.className = `${CSS_PREFIX}-tooltip-content`;
this.arrowEl.className = `${CSS_PREFIX}-tooltip-arrow`;
const floatingStyle = {
display: 'none',
position: 'absolute',
background: TOOLTIP_BG_COLOR,
color: TOOLTIP_TEXT_COLOR,
boxSizing: 'border-box',
zIndex: TOOLTIP_ZINDEX,
padding: '8px',
borderRadius: `4px`,
fontSize: `12px`,
...TOOLTIP_CUSTOM_STYLE,
};
const arrowStyle = {
position: 'absolute',
width: '10px',
height: '10px',
background: floatingStyle.background,
backgroundColor: floatingStyle.backgroundColor,
transform: 'rotate(45deg)',
zIndex: floatingStyle.zIndex,
};
Object.assign(this.arrowEl.style, arrowStyle);
Object.assign(this.floatingEl.style, floatingStyle);
this.floatingEl.appendChild(this.contentEl);
this.floatingEl.appendChild(this.arrowEl);
this.ctx.containerElement.appendChild(this.floatingEl);
this.init();
}
init() {
this.ctx.on('mousemove', (e) => {
// 鼠标移动时,判断是否在target上,不在则隐藏
if (!this.ctx.isTarget()) {
return;
}
const targetRect = this.ctx.containerElement.getBoundingClientRect();
if (!targetRect) {
return;
}
if (e.clientX < targetRect.x ||
e.clientX > targetRect.x + targetRect.width ||
e.clientY < targetRect.y ||
e.clientY > targetRect.y + targetRect.height) {
this.hide();
}
});
// 开始编辑时隐藏
this.ctx.on('startEdit', () => {
this.hide();
});
this.ctx.on('visibleCellHoverChange', (cell) => {
// 有移除或者有错误message时显示
if (cell.ellipsis || cell.message) {
this.show(cell);
}
});
this.ctx.on('visibleCellMouseleave', () => {
this.hide();
});
}
show(cell) {
// 如果没有设置overflowTooltipShow=true,则不显示
if (!cell.overflowTooltipShow) {
return;
}
// 如果是鼠标按下状态,则不显示
if (this.ctx.mousedown) {
return;
}
this.floatingEl.style.display = 'block';
let text = cell.getText();
// 如果有message,则显示message
if (cell.message) {
text = cell.message;
}
const targetRect = this.ctx.containerElement.getBoundingClientRect();
if (!targetRect) {
return;
}
this.enable = true;
// 设置最大宽度
this.contentEl.style.maxWidth = `${cell.overflowTooltipMaxWidth || 500}px`;
this.contentEl.style.minWidth = '100px';
this.contentEl.style.width = '100%';
this.contentEl.style.display = 'inline-block';
this.contentEl.style.wordBreak = 'break-all';
this.contentEl.style.lineHeight = '1.5';
this.contentEl.innerText = text;
const cellX = cell.drawX + targetRect.x;
const cellY = cell.drawY + targetRect.y;
// 这个是相对于视口的位置
const virtualEl = {
getBoundingClientRect() {
return {
width: cell.visibleWidth,
height: cell.visibleHeight,
x: cellX,
y: cellY,
left: cellX,
right: cellX + cell.visibleWidth,
top: cellY,
bottom: cellY + cell.visibleHeight,
};
},
};
computePosition(virtualEl, this.floatingEl, {
placement: cell.overflowTooltipPlacement,
middleware: [shift(), flip(), offset(6), arrow({ element: this.arrowEl })],
}).then((val) => {
const { x, y, placement, middlewareData } = val;
Object.assign(this.floatingEl.style, {
top: `${y}px`,
left: `${x}px`,
});
if (middlewareData.arrow) {
const arrow = middlewareData.arrow;
if (['left', 'left-start', 'left-end'].includes(placement)) {
Object.assign(this.arrowEl.style, {
top: `${arrow.y}px`,
bottom: '',
left: '',
right: `-5px`,
});
}
else if (['right', 'right-start', 'right-end'].includes(placement)) {
Object.assign(this.arrowEl.style, {
top: `${arrow.y}px`,
bottom: '',
left: `-5px`,
right: '',
});
}
else if (['bottom', 'bottom-start', 'bottom-end'].includes(placement)) {
Object.assign(this.arrowEl.style, {
top: `-5px`,
bottom: '',
left: `${arrow.x}px`,
right: '',
});
}
else if (['top', 'top-start', 'top-end'].includes(placement)) {
Object.assign(this.arrowEl.style, {
top: '',
bottom: `-5px`,
left: `${arrow.x}px`,
right: '',
});
}
}
});
}
hide() {
if (!this.enable) {
return;
}
this.enable = false;
this.floatingEl.style.display = 'none';
}
destroy() {
this.contentEl.remove();
this.arrowEl.remove();
this.floatingEl.remove();
}
}
//# sourceMappingURL=Tooltip.js.map