FLaME / static /js /tooltips.js
mokamoto's picture
model tooltips
1f3572e
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());
});
});