/** * HVAC Community Events Animation Helper * * This script adds animation support for dynamic elements and * provides animation utility functions. */ (function() { document.addEventListener('DOMContentLoaded', function() { // Only run animations on HVAC pages const isHVACPage = document.querySelector('.hvac-content') !== null; if (!isHVACPage) { return; // Exit early if not on an HVAC page } // Apply animations to elements with data-animate attribute function animateElements() { const elements = document.querySelectorAll('[data-animate]'); elements.forEach(element => { const animationClass = element.getAttribute('data-animate'); const delay = element.getAttribute('data-animate-delay') || 0; setTimeout(() => { element.classList.add(animationClass); element.style.opacity = '1'; }, delay); }); } // Initialize animations when page loads animateElements(); // DISABLED - MutationObserver was causing Safari hanging issues // The heavy DOM monitoring with childList: true, subtree: true // creates excessive overhead that Safari's engine can't handle /* function setupMutationObserver() { // Watch for new elements being added to the DOM const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.addedNodes && mutation.addedNodes.length > 0) { // Check if any added node has animation attributes mutation.addedNodes.forEach(node => { // Skip non-element nodes if (node.nodeType !== 1) return; // Check for data-animate attribute if (node.getAttribute('data-animate')) { const animationClass = node.getAttribute('data-animate'); const delay = node.getAttribute('data-animate-delay') || 0; setTimeout(() => { node.classList.add(animationClass); node.style.opacity = '1'; }, delay); } // Check children for data-animate attribute const childElements = node.querySelectorAll('[data-animate]'); if (childElements.length > 0) { childElements.forEach(element => { const animationClass = element.getAttribute('data-animate'); const delay = element.getAttribute('data-animate-delay') || 0; setTimeout(() => { element.classList.add(animationClass); element.style.opacity = '1'; }, delay); }); } }); } }); }); // Start observing the document observer.observe(document.body, { childList: true, subtree: true }); } // Start the observer - DISABLED // setupMutationObserver(); */ // Animate table rows in sequence - only on HVAC pages function animateTableRows() { // Only run on HVAC pages (check for hvac-content wrapper) if (!document.querySelector('.hvac-content')) { return; } const tables = document.querySelectorAll('.hvac-content .hvac-table, .hvac-content .events-table, .hvac-content .hvac-transactions-table'); tables.forEach(table => { const rows = table.querySelectorAll('tbody tr'); rows.forEach((row, index) => { row.style.opacity = '0'; setTimeout(() => { row.classList.add('hvac-animate-slide-in-bottom'); row.style.opacity = '1'; }, 50 * (index + 1)); // Stagger animation }); }); } // Run table row animations setTimeout(animateTableRows, 300); // Add animation class to alerts and messages const alerts = document.querySelectorAll('.hvac-alert, .hvac-email-sent, .hvac-email-error, .login-error, .hvac-errors, .hvac-success'); alerts.forEach(alert => { alert.classList.add('hvac-animate-fade-in'); }); // Expose animation API to global scope window.hvacAnimations = { animateElement: function(element, animationClass, delay = 0) { if (!element) return; element.style.opacity = '0'; setTimeout(() => { element.classList.add(animationClass); element.style.opacity = '1'; }, delay); }, animateElements: animateElements, animateTableRows: animateTableRows }; // Check if user prefers reduced motion const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (prefersReducedMotion) { document.body.classList.add('reduced-motion'); } }); })();