| |
| document.addEventListener('DOMContentLoaded', () => { |
| const hoverMedia = window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)'); |
|
|
| if (!hoverMedia) { |
| return; |
| } |
|
|
| let cleanupTooltip = null; |
|
|
| function enableTooltip() { |
| if (cleanupTooltip) return; |
|
|
| |
| const tooltip = document.createElement('div'); |
| tooltip.className = 'custom-tooltip'; |
| document.body.appendChild(tooltip); |
|
|
| let activeElement = null; |
|
|
| function updateTooltipPosition() { |
| if (!activeElement) return; |
|
|
| const rect = activeElement.getBoundingClientRect(); |
| const tooltipRect = tooltip.getBoundingClientRect(); |
| const gap = 10; |
|
|
| |
| let top = rect.bottom + gap; |
| |
| let left = rect.left + (rect.width - tooltipRect.width) / 2; |
|
|
| const winWidth = window.innerWidth; |
| const winHeight = window.innerHeight; |
|
|
| |
| if (top + tooltipRect.height > winHeight - gap) { |
| top = rect.top - tooltipRect.height - gap; |
| } |
|
|
| |
| if (left < gap) { |
| left = gap; |
| } else if (left + tooltipRect.width > winWidth - gap) { |
| left = winWidth - tooltipRect.width - gap; |
| } |
|
|
| tooltip.style.left = left + 'px'; |
| tooltip.style.top = top + 'px'; |
| } |
|
|
| |
| function onMouseOver(e) { |
| const target = e.target.closest('[data-tooltip]'); |
| if (!target) return; |
|
|
| const tooltipText = target.getAttribute('data-tooltip'); |
| if (!tooltipText) return; |
|
|
| activeElement = target; |
| tooltip.textContent = tooltipText; |
| tooltip.classList.add('visible'); |
| |
| updateTooltipPosition(); |
| } |
|
|
| |
| function onMouseOut(e) { |
| const target = e.target.closest('[data-tooltip]'); |
| if (!target || target !== activeElement) return; |
|
|
| |
| if (target.contains(e.relatedTarget)) return; |
|
|
| activeElement = null; |
| tooltip.classList.remove('visible'); |
| } |
|
|
| document.addEventListener('mouseover', onMouseOver); |
| document.addEventListener('mouseout', onMouseOut); |
|
|
| cleanupTooltip = () => { |
| document.removeEventListener('mouseover', onMouseOver); |
| document.removeEventListener('mouseout', onMouseOut); |
|
|
| activeElement = null; |
| tooltip.classList.remove('visible'); |
| tooltip.remove(); |
| }; |
| } |
|
|
| function disableTooltip() { |
| if (!cleanupTooltip) return; |
| cleanupTooltip(); |
| cleanupTooltip = null; |
| } |
|
|
| function syncTooltipEnabled() { |
| if (hoverMedia.matches) { |
| enableTooltip(); |
| } else { |
| disableTooltip(); |
| } |
| } |
|
|
| syncTooltipEnabled(); |
|
|
| |
| if (hoverMedia.addEventListener) { |
| hoverMedia.addEventListener('change', syncTooltipEnabled); |
| } else if (hoverMedia.addListener) { |
| hoverMedia.addListener(syncTooltipEnabled); |
| } |
| }); |
|
|