import './css/tooltip.scss'; import { createElement } from "../functions"; // import { global } from "../utility"; export function setTooltip(container, content, flag = false, parent = null) { const isParent = parent instanceof HTMLElement; if (isParent) { const tipid = container.dataset.tipId; const tip = parent.querySelector(`.ui-tooltip-wrapper[data-tip-id="${tipid}"]`); tip?.remove(); } else { const tip = container.querySelector('.ui-tooltip-wrapper'); tip?.remove(); } const wrapper = createElement('div', wrapper => { wrapper.className = 'ui-tooltip-wrapper ui-tooltip-color'; // wrapper.style.visibility = 'hidden'; // wrapper.style.opacity = 0; // wrapper.style.top = '0'; // wrapper.style.left = '0'; wrapper.style.cssText += 'display: none; visibility: hidden; opacity: 0; top: 0; left: 0'; }, createElement('div', 'ui-tooltip-pointer ui-tooltip-color'), createElement('div', 'ui-tooltip-curtain ui-tooltip-color'), createElement('div', cnt => { cnt.className = 'ui-tooltip-content'; if (content instanceof Element) { cnt.appendChild(content); } else { cnt.innerText = content; } }) ); // container.insertAdjacentElement('afterend', wrapper); if (isParent) { const tipId = String(Math.random()).substring(2); container.dataset.tipId = tipId; wrapper.dataset.tipId = tipId; parent.appendChild(wrapper); } else { container.appendChild(wrapper); } let tid; container.addEventListener('mouseenter', () => { tid && clearTimeout(tid); let c = container; while (c?.offsetWidth == null) { c = c.parentElement; } if (c == null) { return; } if (!flag || c.scrollWidth > c.offsetWidth) { tid = setTimeout(() => { let p; let left; let top; left = c.offsetLeft; top = c.offsetTop; if (isParent) { p = c.offsetParent; while (p != null && p !== parent) { left += p.offsetLeft; top += p.offsetTop; p = p.offsetParent; } } p = c.parentElement; const offsetParent = isParent ? parent : c.offsetParent; while (p != null && p !== offsetParent) { left -= p.scrollLeft; top -= p.scrollTop; p = p.parentElement; } wrapper.style.display = ''; const offsetHeight = wrapper.offsetHeight; const offsetWidth = wrapper.offsetWidth; if (isParent) { top -= offsetHeight + 14; if (top < -offsetHeight) { top += c.offsetHeight + offsetHeight + 14; wrapper.classList.add('ui-tooltip-down'); } left += (c.offsetWidth - offsetWidth) / 2; if (left < 1) { left = 1; } } else { // check overflow let t = c.offsetTop; let l = c.offsetLeft; p = c.offsetParent; if (p == null) { return; } let lastWidth = p.clientWidth; let lastHeight = p.clientHeight; while (p != null) { const overflow = window.getComputedStyle(p).overflow; if (overflow !== 'visible') { break; } t += p.offsetTop; l += p.offsetLeft; const parent = p.offsetParent; while (p != null) { const w = p.clientWidth; if (w < lastWidth) { lastWidth += l; } else { lastWidth = p.clientWidth; } const h = p.clientHeight; if (h < lastHeight) { lastHeight += t; } else { lastHeight = p.clientHeight; } t -= p.scrollTop; l -= p.scrollLeft; if (p === parent) { break; } p = p.parentElement; } } if (t - offsetHeight - 14 < 0) { const containerOffsetHeight = c.offsetHeight; if (t + containerOffsetHeight + offsetHeight + 14 > lastHeight) { top = t + (containerOffsetHeight - offsetHeight) / 2; if (top + offsetHeight + 1 > lastHeight) { top = lastHeight - offsetHeight - 1; } wrapper.classList.add('ui-tooltip-no'); } else { top += containerOffsetHeight + 14; wrapper.classList.add('ui-tooltip-down'); } } else { top -= offsetHeight + 14; wrapper.classList.remove('ui-tooltip-down'); } left += (c.offsetWidth - offsetWidth) / 2; if (l - offsetWidth < 0) { left = 1; } else if (left + offsetWidth + 1 > lastWidth) { left = lastWidth - offsetWidth - 1; } } // wrapper.style.left = `${left}px`; // wrapper.style.top = `${top}px`; // wrapper.style.visibility = 'visible'; // wrapper.style.opacity = 1; wrapper.style.cssText += `left: ${left}px; top: ${top}px; visibility: visible; opacity: 1`; }, 100); } }); container.addEventListener('mouseleave', () => { tid && clearTimeout(tid); tid = setTimeout(() => { wrapper.style.visibility = 'hidden'; wrapper.style.opacity = 0; tid = setTimeout(() => wrapper.style.display = 'none', 120); }, 300); }); return container; } export function resolveTooltip(container = document.body) { const tips = container.querySelectorAll('[title]'); for (let tip of tips) { const title = tip.getAttribute('title'); if (title != null) { tip.removeAttribute('title'); setTooltip(tip, title); } } return container; }