/** * Ultimate Liquid Tooltip System (TXA Tooltip V2) * High performance, mouse-following, glassmorphism design * Supports data-txa-tooltip, data-txatooltip, and .txatooltip class */ (function () { 'use strict'; if (window.isTxaTooltipInit) return; window.isTxaTooltipInit = true; const tooltip = document.getElementById('txa-tooltip') || document.createElement('div'); if (!tooltip.id) { tooltip.id = 'txa-tooltip'; tooltip.style.cssText = ` position: fixed; pointer-events: none; z-index: 2147483647; padding: 12px 18px; background: rgba(15, 23, 42, 0.96); backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 16px; color: #fff; font-size: 14px; font-weight: 500; box-shadow: 0 20px 50px rgba(0,0,0,0.6), 0 0 20px rgba(99, 102, 241, 0.2); opacity: 0; transform: scale(0.95) translateY(10px); transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1), transform 0.3s cubic-bezier(0.16, 1, 0.3, 1); white-space: normal; max-width: 320px; line-height: 1.6; text-align: left; word-break: break-word; font-family: 'Outfit', sans-serif; `; } function initTooltip() { if (!document.body) { window.addEventListener('DOMContentLoaded', initTooltip); return; } if (!document.getElementById('txa-tooltip')) { document.body.appendChild(tooltip); } } window.initTxaTooltips = initTooltip; initTooltip(); document.addEventListener('astro:page-load', initTooltip); let currentTarget = null; let hideTimeout = null; let isMouseOnTooltip = false; tooltip.addEventListener('mouseenter', () => { isMouseOnTooltip = true; clearTimeout(hideTimeout); }); tooltip.addEventListener('mouseleave', () => { isMouseOnTooltip = false; if (!currentTarget) hideTooltip(); }); function showTooltip(text, target, e = null) { if (!text) return; clearTimeout(hideTimeout); const link = target.getAttribute('data-tooltip-link'); const linkTitle = target.getAttribute('data-tooltip-link-title') || 'Xem chi tiết'; let content = `
${text}
`; if (link) { content += `
${linkTitle}
`; tooltip.style.pointerEvents = 'auto'; } else { tooltip.style.pointerEvents = 'none'; } tooltip.innerHTML = content; // Dynamic alignment tooltip.style.textAlign = text.length > 40 ? 'left' : 'center'; tooltip.style.opacity = '1'; tooltip.style.transform = 'scale(1) translateY(0)'; currentTarget = target; if (e) { updatePosition(e); } } function hideTooltip() { if (isMouseOnTooltip) return; hideTimeout = setTimeout(() => { if (isMouseOnTooltip) return; tooltip.style.opacity = '0'; tooltip.style.transform = 'scale(0.95) translateY(10px)'; currentTarget = null; }, 100); } function updatePosition(e) { if (tooltip.style.opacity === '0' || isMouseOnTooltip) return; const offset = 20; const rect = tooltip.getBoundingClientRect(); let x = e.clientX - (rect.width / 2); let y = e.clientY - rect.height - offset; const padding = 15; if (x < padding) x = padding; if (x + rect.width + padding > window.innerWidth) { x = window.innerWidth - rect.width - padding; } if (y < padding) { y = e.clientY + offset; } tooltip.style.left = x + 'px'; tooltip.style.top = y + 'px'; } document.addEventListener('mouseover', (e) => { const target = e.target.closest('[data-txa-tooltip], [data-txatooltip], .txatooltip, .txaxtooltip'); if (target) { // Logic for sidebar menu items (collapsed state) if (target.classList.contains('menu-item') || target.classList.contains('sidebar-link')) { const isSidebarCollapsed = document.body.classList.contains('sidebar-collapsed'); if (!isSidebarCollapsed && window.innerWidth > 992) return; } const tooltipText = target.getAttribute('data-txa-tooltip') || target.getAttribute('data-txatooltip') || target.title; if (tooltipText) { // Remove title to prevent browser default tooltip if (target.title) { target.setAttribute('data-original-title', target.title); target.title = ''; } showTooltip(tooltipText, target, e); } } }); document.addEventListener('mouseout', (e) => { const target = e.target.closest('[data-txa-tooltip], [data-txatooltip], .txatooltip, .txaxtooltip'); if (target) { // Restore title if needed const originalTitle = target.getAttribute('data-original-title'); if (originalTitle) { target.title = originalTitle; target.removeAttribute('data-original-title'); } hideTooltip(); } }); document.addEventListener('mousemove', (e) => { if (currentTarget) updatePosition(e); }); document.addEventListener('click', (e) => { if (!tooltip.contains(e.target)) hideTooltip(); }); // Fullscreen support function handleFullscreenChange() { const fsElem = document.fullscreenElement || document.webkitFullscreenElement; if (fsElem) { fsElem.appendChild(tooltip); tooltip.style.zIndex = '2147483647'; } else { if (document.body && !document.body.contains(tooltip)) { document.body.appendChild(tooltip); } } } document.addEventListener('fullscreenchange', handleFullscreenChange); document.addEventListener('webkitfullscreenchange', handleFullscreenChange); })();