/** * Scroll At-Bottom Handler * Adds 'at-bottom' class to buttons and footer when user scrolls to page bottom */ (function() { 'use strict'; // Wait for DOM to be ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } function init() { const footer = document.querySelector('footer.no-print'); if (!footer) return; // Get all fixed buttons that need 'at-bottom' state const buttons = document.querySelectorAll( '.download-btn, .print-friendly-btn, .shortcuts-btn, ' + '.info-button, .back-to-top, .color-theme-switcher' ); if (buttons.length === 0) return; // Throttle scroll events for better performance let ticking = false; function checkIfAtBottom() { // Calculate if we're at the bottom of the page // Allow 50px tolerance for smoother experience const scrollPosition = window.pageYOffset || document.documentElement.scrollTop; const windowHeight = window.innerHeight; const documentHeight = document.documentElement.scrollHeight; const distanceFromBottom = documentHeight - (scrollPosition + windowHeight); const isAtBottom = distanceFromBottom <= 50; if (isAtBottom) { // Add 'at-bottom' class to all buttons and footer buttons.forEach(btn => btn.classList.add('at-bottom')); footer.classList.add('at-bottom'); } else { // Remove 'at-bottom' class from all buttons and footer buttons.forEach(btn => btn.classList.remove('at-bottom')); footer.classList.remove('at-bottom'); } } function onScroll() { if (!ticking) { window.requestAnimationFrame(() => { checkIfAtBottom(); ticking = false; }); ticking = true; } } // Check initial state checkIfAtBottom(); // Listen to scroll events window.addEventListener('scroll', onScroll, { passive: true }); // Also check on resize (mobile orientation changes, etc.) window.addEventListener('resize', () => { setTimeout(checkIfAtBottom, 100); }); } })();