177 lines
7.0 KiB
JavaScript
177 lines
7.0 KiB
JavaScript
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;
|
|
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;
|
|
} |