1// Main JavaScript file 2import { initCalculator } from './components/calculator.js'; 3import { initNavigation } from './components/navigation.js'; 4import { initNewsletter } from './components/newsletter.js'; 5import { fetchMortgageRate } from './components/rates.js'; 6// import { initBookCovers } from './components/bookCovers.js'; // Removed - using actual images now 7import { initDiscordSection } from './components/discord.js'; 8// Temporarily disabled - requires build step for Supabase 9// import { initAuth, initSocialAuth } from './components/auth.js'; 10 11// Initialize all components when DOM is loaded 12document.addEventListener('DOMContentLoaded', () => { 13 // Initialize navigation 14 initNavigation(); 15 16 // Initialize authentication - Temporarily disabled (requires build step) 17 // initAuth(); 18 // initSocialAuth(); 19 20 // Initialize calculator 21 initCalculator(); 22 23 // Initialize newsletter 24 initNewsletter(); 25 26 // Initialize book covers - Removed, using actual images now 27 // initBookCovers(); 28 29 // Initialize Discord integration 30 initDiscordSection(); 31 32 // Fetch and display current mortgage rate 33 updateMortgageRate(); 34 35 // Smooth scrolling for anchor links 36 initSmoothScrolling(); 37 38 // Initialize success ticker 39 initSuccessTicker(); 40}); 41 42// Smooth scrolling 43function initSmoothScrolling() { 44 document.querySelectorAll('a[href^="#"]').forEach(anchor => { 45 anchor.addEventListener('click', function (e) { 46 e.preventDefault(); 47 const targetId = this.getAttribute('href'); 48 const targetElement = document.querySelector(targetId); 49 50 if (targetElement) { 51 const headerOffset = 80; 52 const elementPosition = targetElement.getBoundingClientRect().top; 53 const offsetPosition = elementPosition + window.pageYOffset - headerOffset; 54 55 window.scrollTo({ 56 top: offsetPosition, 57 behavior: 'smooth' 58 }); 59 } 60 }); 61 }); 62} 63 64// Update mortgage rate 65async function updateMortgageRate() { 66 const rateElement = document.getElementById('current-rate'); 67 const sourceElement = document.getElementById('rate-source'); 68 const updateElement = document.getElementById('rate-update'); 69 70 if (!rateElement) return; 71 72 try { 73 // Add loading state with animation 74 rateElement.classList.add('opacity-50'); 75 rateElement.textContent = 'Loading...'; 76 77 // Fetch real rate from FRED API 78 const rate = await fetchMortgageRate(); 79 80 // Animate the update 81 rateElement.style.transition = 'all 0.3s ease'; 82 rateElement.textContent = `${rate}%`; 83 rateElement.classList.remove('opacity-50'); 84 85 // Update source info 86 const source = sessionStorage.getItem('rate_source') || 'Market Data'; 87 if (sourceElement) { 88 sourceElement.textContent = `Source: ${source}`; 89 } 90 91 // Update timestamp 92 if (updateElement) { 93 const timestamp = sessionStorage.getItem('rate_timestamp'); 94 if (timestamp) { 95 const date = new Date(parseInt(timestamp)); 96 const timeStr = date.toLocaleTimeString('en-US', { 97 hour: 'numeric', 98 minute: '2-digit' 99 }); 100 updateElement.textContent = `Updated ${timeStr}`; 101 } else { 102 // Set current time if no timestamp 103 const now = new Date(); 104 const timeStr = now.toLocaleTimeString('en-US', { 105 hour: 'numeric', 106 minute: '2-digit' 107 }); 108 updateElement.textContent = `Updated ${timeStr}`; 109 } 110 } 111 } catch (error) { 112 console.error('Failed to fetch mortgage rate:', error); 113 rateElement.classList.remove('opacity-50'); 114 rateElement.textContent = '7.25%'; 115 // Keep the default rate if fetch fails 116 } 117} 118 119// Success ticker animation 120function initSuccessTicker() { 121 const ticker = document.querySelector('.ticker-content'); 122 if (!ticker) return; 123 124 // Clone the ticker content for seamless loop 125 const tickerContent = ticker.innerHTML; 126 ticker.innerHTML = tickerContent + tickerContent; 127} 128 129// Add scroll effect to header 130window.addEventListener('scroll', () => { 131 const header = document.getElementById('header'); 132 if (window.scrollY > 50) { 133 header.classList.add('shadow-lg'); 134 } else { 135 header.classList.remove('shadow-lg'); 136 } 137});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.