diff options
| author | Eltrac <hi@guhub.cn> | 2025-07-27 09:56:40 +0800 |
|---|---|---|
| committer | Eltrac <hi@guhub.cn> | 2025-07-27 09:56:40 +0800 |
| commit | 50dbd00f57e72c54ed93c54d39a3969769bd4388 (patch) | |
| tree | c62378f6f4aa0a8b8ff9b71b60d62c502a337719 /assets | |
| parent | 7e7d95f85995d2df66ec47144d16d663eeb3eea0 (diff) | |
refactor: extract tooltip feature as a global script
Former-commit-id: b64e0b67a1a425bb79055c1e42b12f5807836d66
Diffstat (limited to 'assets')
| -rw-r--r-- | assets/js/tooltip.js | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/assets/js/tooltip.js b/assets/js/tooltip.js new file mode 100644 index 00000000..c90658a2 --- /dev/null +++ b/assets/js/tooltip.js @@ -0,0 +1,54 @@ +(() => { + const allTooltipped = document.querySelectorAll('[data-tooltip], [title]'); + + const createOrUpdateTooltip = (element) => { + const tooltipText = element.getAttribute('data-tooltip') || element.getAttribute('title'); + + if (!tooltipText) return; + + let tooltipElement = element.querySelector('.__generated-tooltip'); + if (!tooltipElement) { + element.classList.add('group', 'relative', 'tooltipped'); + + tooltipElement = document.createElement('div'); + tooltipElement.classList.add( + '__generated-tooltip', + ...'absolute bottom-full left-1/2 transform -translate-x-1/2 translate-y-1 bg-black/80 text-white px-2.5 py-1.5 rounded text-xs whitespace-nowrap opacity-0 invisible transition-all duration-300 pointer-events-none mb-2 z-1000 group-hover:opacity-100 group-hover:visible group-hover:translate-y-0 dark:bg-white/90 dark:text-black'.split(' ') + ); + element.appendChild(tooltipElement); + } + + tooltipElement.textContent = tooltipText; + }; + + const observer = new IntersectionObserver((entries, obs) => { + entries.forEach(entry => { + if (!entry.isIntersecting) return; + + const element = entry.target; + createOrUpdateTooltip(element); + + // listen to tooltip text changes + const mutationObserver = new MutationObserver(mutations => { + for (const mutation of mutations) { + if (mutation.type === 'attributes' && + (mutation.attributeName === 'title' || mutation.attributeName === 'data-tooltip')) { + createOrUpdateTooltip(element); + } + } + }); + + mutationObserver.observe(element, { + attributes: true, + attributeFilter: ['title', 'data-tooltip'], + }); + + obs.unobserve(element); // 不再需要 Intersection 监听 + }); + }, { + rootMargin: '100px', + threshold: 0.1, + }); + + allTooltipped.forEach(el => observer.observe(el)); +})(); |
