Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', () => { | |
| console.log('Tooltip script loaded'); | |
| // Function to fix problematic tooltips | |
| window.fixProblemTooltips = () => { | |
| console.log('Fixing problem tooltips'); | |
| // Find all tooltip elements with tooltip-trigger class | |
| const allTooltips = document.querySelectorAll('.tooltip-trigger'); | |
| console.log(`Found ${allTooltips.length} tooltip triggers`); | |
| // Process each tooltip - fix all tooltips with tooltip-trigger class | |
| allTooltips.forEach(tooltip => { | |
| const tooltipContent = tooltip.getAttribute('data-tooltip') || ''; | |
| if (tooltipContent) { | |
| console.log(`Processing tooltip: ${tooltip.innerText}`); | |
| // Get tooltip title | |
| const tooltipTitle = tooltip.getAttribute('data-title') || tooltip.innerText; | |
| const tooltipId = 'custom-' + tooltipTitle.replace(/[^a-zA-Z0-9]/g, ''); | |
| // Fix this tooltip | |
| fixSingleTooltip(tooltip, tooltipTitle, tooltipId); | |
| } | |
| }); | |
| }; | |
| // Function to fix a single tooltip | |
| const fixSingleTooltip = (tooltip, title, id) => { | |
| console.log(`Fixing tooltip for ${title} with ID ${id}`); | |
| // Remove any existing event listeners | |
| const clone = tooltip.cloneNode(true); | |
| tooltip.parentNode.replaceChild(clone, tooltip); | |
| tooltip = clone; | |
| // Add tooltip-right class and inline styles | |
| tooltip.classList.add('tooltip-right'); | |
| tooltip.style.position = 'relative'; | |
| // Add data-title if missing | |
| if (!tooltip.getAttribute('data-title')) { | |
| tooltip.setAttribute('data-title', title); | |
| } | |
| // Get tooltip content | |
| const tooltipContent = tooltip.getAttribute('data-tooltip') || ''; | |
| // Show the tooltip on the left side | |
| tooltip.addEventListener('mouseenter', (event) => { | |
| console.log(`Mouse entered ${title}`); | |
| // Remove any existing custom tooltip with this ID | |
| const existingTooltip = document.getElementById(id); | |
| if (existingTooltip) { | |
| existingTooltip.remove(); | |
| } | |
| // Create custom tooltip element | |
| const customTooltip = document.createElement('div'); | |
| customTooltip.id = id; | |
| customTooltip.className = 'custom-tooltip'; | |
| customTooltip.innerHTML = `<strong>${title}</strong>${tooltipContent}`; | |
| document.body.appendChild(customTooltip); | |
| // Position tooltip near the element | |
| const rect = tooltip.getBoundingClientRect(); | |
| console.log(`Element position: top=${rect.top}, left=${rect.left}, width=${rect.width}, height=${rect.height}`); | |
| const tooltipWidth = 300; // Width of our tooltip in pixels | |
| const horizontalOffset = 5; // Small gap between element and tooltip | |
| // Check if this is a model tooltip in the cost analysis tab (in first column of any table) | |
| const isModelTooltip = (tooltip.closest('td:first-child') !== null || | |
| tooltip.closest('th:first-child') !== null); | |
| // Position tooltip either to the right or below based on location | |
| if (isModelTooltip) { | |
| console.log('Positioning model tooltip to the right'); | |
| // Position to the right for model tooltips in cost analysis | |
| // Calculate vertical centering (tooltip height is variable) | |
| const tooltipHeight = 300; // Estimate for most model tooltips | |
| // Position exactly at vertical center of the model name | |
| const modelMiddle = rect.top + (rect.height / 2); | |
| // Set position as fixed to work properly with scrolling | |
| customTooltip.style.position = 'fixed'; | |
| customTooltip.style.top = `${modelMiddle}px`; | |
| customTooltip.style.transform = 'translateY(-50%)'; | |
| customTooltip.style.left = `${rect.right + horizontalOffset}px`; | |
| // Create arrow element for the model tooltip - using orange color from FLaME | |
| const arrow = document.createElement('div'); | |
| arrow.style.position = 'absolute'; | |
| arrow.style.left = '-10px'; // Move it a bit further out for visibility | |
| arrow.style.top = '50%'; | |
| arrow.style.transform = 'translateY(-50%)'; | |
| arrow.style.width = '0'; | |
| arrow.style.height = '0'; | |
| arrow.style.borderTop = '11px solid transparent'; // Make it larger | |
| arrow.style.borderBottom = '11px solid transparent'; // Make it larger | |
| arrow.style.borderRight = '11px solid rgba(0, 0, 0, 0.9)'; // Orange accent color for visibility | |
| arrow.style.display = 'block'; | |
| arrow.style.zIndex = '9999'; | |
| customTooltip.appendChild(arrow); | |
| // Make sure tooltip doesn't go too close to the top edge | |
| if (modelMiddle < 50) { | |
| customTooltip.style.top = '50px'; | |
| } | |
| // Check if tooltip would go off the right edge of the screen | |
| const viewportWidth = window.innerWidth; | |
| const tooltipRight = rect.right + horizontalOffset + tooltipWidth; | |
| if (tooltipRight > viewportWidth - 20) { | |
| // Position to the left of the element instead | |
| customTooltip.style.left = `${rect.left - tooltipWidth - horizontalOffset}px`; | |
| // Move the arrow to the right side and flip it | |
| if (arrow) { | |
| arrow.style.left = 'auto'; | |
| arrow.style.right = '-8px'; | |
| arrow.style.borderRight = 'none'; | |
| arrow.style.borderLeft = '8px solid rgba(0, 0, 0, 0.9)'; // Orange color for visibility | |
| } | |
| } | |
| } else { | |
| // Default behavior - position below and centered | |
| const verticalOffset = 5; | |
| // Set tooltip position below the element | |
| customTooltip.style.top = `${window.scrollY + rect.bottom + verticalOffset}px`; | |
| // Center the tooltip horizontally on the element | |
| const tooltipLeft = rect.left + (rect.width / 2) - (tooltipWidth / 2); | |
| // But make sure it stays within the viewport bounds | |
| const viewportWidth = window.innerWidth; | |
| let adjustedLeft = tooltipLeft; | |
| // Check right edge | |
| if (tooltipLeft + tooltipWidth > viewportWidth - 20) { | |
| adjustedLeft = viewportWidth - tooltipWidth - 20; | |
| } | |
| // Check left edge | |
| if (adjustedLeft < 20) { | |
| adjustedLeft = 20; | |
| } | |
| customTooltip.style.left = `${adjustedLeft}px`; | |
| // Add a small arrow at the top pointing to the element | |
| const arrow = document.createElement('div'); | |
| arrow.style.position = 'absolute'; | |
| arrow.style.top = '-8px'; | |
| arrow.style.left = `${Math.max(0, Math.min(tooltipWidth - 20, rect.left + (rect.width / 2) - adjustedLeft - 8))}px`; | |
| arrow.style.width = '0'; | |
| arrow.style.height = '0'; | |
| arrow.style.borderLeft = '8px solid transparent'; | |
| arrow.style.borderRight = '8px solid transparent'; | |
| arrow.style.borderBottom = '8px solid rgba(0, 0, 0, 0.9)'; | |
| customTooltip.appendChild(arrow); | |
| } | |
| console.log(`Tooltip position: top=${customTooltip.style.top}, left=${customTooltip.style.left}`); | |
| }); | |
| // Hide tooltip on mouseout | |
| tooltip.addEventListener('mouseleave', (event) => { | |
| console.log(`Mouse left ${title}`); | |
| const customTooltip = document.getElementById(id); | |
| if (customTooltip) { | |
| customTooltip.remove(); | |
| } | |
| }); | |
| }; | |
| // Run when DOM is ready | |
| console.log('Setting up initial tooltip fix'); | |
| setTimeout(fixProblemTooltips, 500); | |
| // Run again when tabs are clicked | |
| const tabs = document.querySelectorAll('.tabs li'); | |
| console.log(`Found ${tabs.length} tabs`); | |
| tabs.forEach(tab => { | |
| tab.addEventListener('click', (event) => { | |
| console.log(`Tab clicked: ${tab.textContent}`); | |
| // Give time for the content to be displayed | |
| setTimeout(fixProblemTooltips, 500); | |
| }); | |
| }); | |
| // Handle window resize | |
| window.addEventListener('resize', () => { | |
| console.log('Window resized, removing tooltips'); | |
| // Remove all custom tooltips on resize | |
| document.querySelectorAll('.custom-tooltip').forEach(t => t.remove()); | |
| }); | |
| }); |