UNPKG

@visactor/vtable

Version:

canvas table width high performance

163 lines (155 loc) 14.2 kB
import { EventHandler } from "../../../event/EventHandler"; import { Placement } from "../../../ts-types"; import { createElement } from "../../../tools/dom"; import { importStyle } from "./BubbleTooltipElementStyle"; import { isDivSelected, isMobile } from "../../../tools/util"; importStyle(); const TOOLTIP_CLASS = "vtable__bubble-tooltip-element", CONTENT_CLASS = `${TOOLTIP_CLASS}__content`, TRIANGLE_CLASS = `${TOOLTIP_CLASS}__triangle`, HIDDEN_CLASS = `${TOOLTIP_CLASS}--hidden`, SHOWN_CLASS = `${TOOLTIP_CLASS}--shown`; export class BubbleTooltipElement { constructor() { this._handler = new EventHandler; const rootElement = this._rootElement = createElement("div", [ TOOLTIP_CLASS, HIDDEN_CLASS ]), messageElement = createElement("div", [ CONTENT_CLASS ]), triangle = createElement("span", [ TRIANGLE_CLASS ]); rootElement.appendChild(triangle), rootElement.appendChild(messageElement), this._messageElement = rootElement.querySelector(`.${CONTENT_CLASS}`) || void 0, this._triangleElement = rootElement.querySelector(`.${TRIANGLE_CLASS}`) || void 0, rootElement.addEventListener("mousemove", (() => { this._disappearDelayId && clearTimeout(this._disappearDelayId); })), rootElement.addEventListener("mouseleave", (() => { this._disappearDelay = void 0, this.unbindFromCell(); })), messageElement.addEventListener("wheel", (e => { e.stopPropagation(); })), messageElement.addEventListener("copy", (e => { isDivSelected(messageElement) && e.stopPropagation(); })); } bindToCell(table, col, row, tooltipInstanceInfo, confine) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u; this._disappearDelay = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.disappearDelay, this._disappearDelayId && clearTimeout(this._disappearDelayId); const rootElement = this._rootElement, messageElement = this._messageElement, triangle = this._triangleElement; if (null == rootElement || rootElement.classList.remove(SHOWN_CLASS), null == rootElement || rootElement.classList.add(HIDDEN_CLASS), this._canBindToCell(table, col, row)) { messageElement.setAttribute("style", ""), triangle.setAttribute("style", ""), (null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.className) && rootElement.classList.add(tooltipInstanceInfo.className), (null === (_a = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _a ? void 0 : _a.bgColor) && (messageElement.style.backgroundColor = null === (_b = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _b ? void 0 : _b.bgColor), (null === (_c = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _c ? void 0 : _c.bgColor) && (triangle.style.backgroundColor = null === (_d = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _d ? void 0 : _d.bgColor), triangle.style.display = !0 === (null === (_e = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _e ? void 0 : _e.arrowMark) ? "block" : "none", (null === (_f = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _f ? void 0 : _f.fontSize) && (messageElement.style.fontSize = (null !== (_h = null === (_g = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _g ? void 0 : _g.fontSize) && void 0 !== _h ? _h : 12) + "px"), (null === (_j = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _j ? void 0 : _j.fontFamily) && (messageElement.style.fontFamily = null === (_k = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _k ? void 0 : _k.fontFamily), (null === (_l = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _l ? void 0 : _l.color) && (messageElement.style.color = null === (_m = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _m ? void 0 : _m.color), (null === (_o = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _o ? void 0 : _o.padding) && (messageElement.style.padding = `${null === (_p = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _p ? void 0 : _p.padding.join("px ")}px`), (null === (_q = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _q ? void 0 : _q.maxHeight) && (messageElement.style.maxHeight = `${null === (_r = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _r ? void 0 : _r.maxHeight}px`), (null === (_s = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _s ? void 0 : _s.maxWidth) && (messageElement.style.maxWidth = `${null === (_t = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _t ? void 0 : _t.maxWidth}px`), messageElement && (messageElement.textContent = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.content); if (this._bindToCell(table, col, row, null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.position, null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.referencePosition, confine, null === (_u = null == tooltipInstanceInfo ? void 0 : tooltipInstanceInfo.style) || void 0 === _u ? void 0 : _u.arrowMark)) return null == rootElement || rootElement.classList.add(SHOWN_CLASS), null == rootElement || rootElement.classList.remove(HIDDEN_CLASS), !0; } else this.unbindFromCell(); return !1; } release() { var _a, _b; this.unbindFromCell(); const rootElement = this._rootElement; (null == rootElement ? void 0 : rootElement.parentElement) && rootElement.parentElement.removeChild(rootElement), null === (_b = null === (_a = this._handler) || void 0 === _a ? void 0 : _a.release) || void 0 === _b || _b.call(_a), delete this._rootElement, delete this._messageElement; } move(table, col, row, tooltipOptions, confine) { const rootElement = this._rootElement; this._canBindToCell(table, col, row) ? (this._bindToCell(table, col, row, null == tooltipOptions ? void 0 : tooltipOptions.position, null == tooltipOptions ? void 0 : tooltipOptions.referencePosition, confine), null == rootElement || rootElement.classList.add(SHOWN_CLASS), null == rootElement || rootElement.classList.remove(HIDDEN_CLASS)) : this.unbindFromCell(); } unbindFromCell() { var _a; if (this._disappearDelay) this._disappearDelayId = setTimeout((() => { const rootElement = this._rootElement; (null == rootElement ? void 0 : rootElement.parentElement) && (rootElement.classList.remove(SHOWN_CLASS), rootElement.classList.add(HIDDEN_CLASS)); }), null !== (_a = this._disappearDelay) && void 0 !== _a ? _a : 0); else { const rootElement = this._rootElement; (null == rootElement ? void 0 : rootElement.parentElement) && (rootElement.classList.remove(SHOWN_CLASS), rootElement.classList.add(HIDDEN_CLASS)); } } _canBindToCell(table, col, row) { const rect = table.getCellRangeRelativeRect({ col: col, row: row }), element = table.getElement(), {bottom: bottom, left: left, right: right, top: top} = rect; if (table.isFrozenCell(col, row)) return !0; if (bottom < table.getFrozenRowsHeight() || right < table.getFrozenColsWidth() || left > table.tableNoFrameWidth - table.getRightFrozenColsWidth() || top > table.tableNoFrameHeight - table.getBottomFrozenRowsHeight()) return !1; const {offsetHeight: offsetHeight, offsetWidth: offsetWidth} = element; return !(top > offsetHeight) && !(left > offsetWidth); } _bindToCell(table, col, row, position, referencePosition, confine, arrowMark) { const rootElement = this._rootElement, rect = table.getCellRangeRelativeRect({ col: col, row: row }), element = table.internalProps.tooltip.parentElement, containerWidth = table.internalProps.element.offsetWidth, {width: width} = rect; if (rootElement) { let tooltipY, tooltipX; rootElement.parentElement !== element && element.appendChild(rootElement), rootElement.style.left = "0px"; const maxWidth = Math.min(.8 * containerWidth, 4 * width); rootElement.style.maxWidth = `${maxWidth}px`; const rootElementWidth = rootElement.clientWidth, rootElementHeight = rootElement.clientHeight; if (!position && !referencePosition) return !1; { const tooltipPosition = this.getComputedPosition(table, col, row, position, referencePosition, confine, arrowMark); tooltipX = tooltipPosition.x, tooltipY = tooltipPosition.y; } rootElement.style.left = `${tooltipX}px`, rootElement.style.top = `${tooltipY}px`, isMobile() && (rootElement.style.fontSize = "11px"); const {x1: menuLeft, x2: menuRight, y1: menuTop, y2: menuBottom} = table.stateManager.menu.bounds, tooltipLeft = tooltipX, tooltipRight = tooltipLeft + rootElementWidth, tooltipTop = tooltipY, tooltipBottom = tooltipLeft + rootElementHeight; return !(table.stateManager.menu.isShow && menuLeft < tooltipRight && menuRight > tooltipLeft && menuBottom > tooltipTop && menuTop < tooltipBottom); } return !1; } getComputedPosition(table, col, row, position, referencePosition, confine, arrowMark) { var _a; const rootElement = this._rootElement, rect = table.getCellRangeRelativeRect({ col: col, row: row }), {x: parentX, y: parentY} = table.internalProps.tooltip.parentElement.getBoundingClientRect(), {width: containerWidth, height: containerHeight, x: x, y: y} = table.internalProps.element.getBoundingClientRect(), {width: width} = rect; let tooltipY, tooltipX; const maxWidth = Math.min(.8 * containerWidth, 4 * width); rootElement.style.maxWidth = `${maxWidth}px`; const rootElementWidth = rootElement.clientWidth, rootElementHeight = rootElement.clientHeight, triangleHeight = arrowMark ? 6 : 0; if (position) tooltipX = position.x, tooltipY = position.y + triangleHeight, this._triangleElement.style.left = "50%", this._triangleElement.style.marginLeft = "-5px", this._triangleElement.style.top = "-5px"; else if (referencePosition) { let placement = null !== (_a = referencePosition.placement) && void 0 !== _a ? _a : Placement.bottom; const referenceXMiddle = referencePosition.rect.left + referencePosition.rect.width / 2, referenceYMiddle = referencePosition.rect.top + referencePosition.rect.height / 2, referenceTop = referencePosition.rect.top, referenceBottom = referencePosition.rect.bottom, referenceLeft = referencePosition.rect.left, referenceRight = referencePosition.rect.right; let callCount = 0; const adjustPosition = () => { callCount++, callCount >= 4 || (this.removeStyleFromTriangle(), placement === Placement.top ? (tooltipX = referenceXMiddle - rootElementWidth / 2, tooltipY = referenceTop - rootElementHeight - triangleHeight, this._triangleElement.style.left = "50%", this._triangleElement.style.marginLeft = "-5px", this._triangleElement.style.bottom = "-5px", confine && tooltipY < 0 && (placement = Placement.right, adjustPosition())) : placement === Placement.bottom ? (tooltipX = referenceXMiddle - rootElementWidth / 2, tooltipY = referenceBottom + triangleHeight, this._triangleElement.style.left = "50%", this._triangleElement.style.marginLeft = "-5px", this._triangleElement.style.top = "-5px", confine && tooltipY + rootElementHeight > containerHeight && (placement = Placement.left, adjustPosition())) : placement === Placement.left ? (tooltipY = referenceYMiddle - rootElementHeight / 2, tooltipX = referenceLeft - rootElementWidth - triangleHeight, this._triangleElement.style.top = "50%", this._triangleElement.style.marginTop = "-5px", this._triangleElement.style.right = "-5px", confine && tooltipX < 0 && (placement = Placement.top, adjustPosition())) : placement === Placement.right && (tooltipY = referenceYMiddle - rootElementHeight / 2, tooltipX = referenceRight + triangleHeight, this._triangleElement.style.top = "50%", this._triangleElement.style.marginTop = "-5px", this._triangleElement.style.left = "-5px", confine && tooltipX + rootElementWidth > containerWidth && (placement = Placement.bottom, adjustPosition()))); }; adjustPosition(); } return confine && (tooltipX < 0 ? tooltipX = 0 : tooltipX + rootElement.offsetWidth > containerWidth && (tooltipX = containerWidth - rootElement.offsetWidth)), { x: tooltipX + x - parentX, y: tooltipY + y - parentY }; } removeStyleFromTriangle() { this._triangleElement.style.left = "", this._triangleElement.style.right = "", this._triangleElement.style.top = "", this._triangleElement.style.bottom = "", this._triangleElement.style.marginLeft = "", this._triangleElement.style.marginTop = ""; } _locate(table, col, row, position, referencePosition, confine) { const tooltipPosition = this.getComputedPosition(table, col, row, position, referencePosition, confine), tooltipX = tooltipPosition.x, tooltipY = tooltipPosition.y; this._rootElement.style.left = `${tooltipX}px`, this._rootElement.style.top = `${tooltipY}px`; } } //# sourceMappingURL=BubbleTooltipElement.js.map