1// Event countdown timer 2let countdownInterval = null 3let countdownInterval2 = null 4 5function updateCountdownForElements( 6 daysEl, 7 hoursEl, 8 minutesEl, 9 secondsEl, 10 eventDate 11) { 12 if (!daysEl || !hoursEl || !minutesEl || !secondsEl) return false 13 14 const now = new Date().getTime() 15 const distance = eventDate - now 16 17 if (distance < 0) { 18 daysEl.textContent = '0' 19 hoursEl.textContent = '0' 20 minutesEl.textContent = '0' 21 secondsEl.textContent = '0' 22 return false 23 } 24 25 const days = Math.floor(distance / (1000 * 60 * 60 * 24)) 26 const hours = Math.floor( 27 (distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) 28 ) 29 const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) 30 const seconds = Math.floor((distance % (1000 * 60)) / 1000) 31 32 daysEl.textContent = days 33 hoursEl.textContent = hours 34 minutesEl.textContent = minutes 35 secondsEl.textContent = seconds 36 return true 37} 38 39function startCountdown() { 40 const daysEl = document.getElementById('countdown-days') 41 const hoursEl = document.getElementById('countdown-hours') 42 const minutesEl = document.getElementById('countdown-minutes') 43 const secondsEl = document.getElementById('countdown-seconds') 44 45 // Event date: January 14, 2027 46 const eventDate = new Date('2027-01-14T00:00:00').getTime() 47 48 function updateCountdown() { 49 const running = updateCountdownForElements( 50 daysEl, 51 hoursEl, 52 minutesEl, 53 secondsEl, 54 eventDate 55 ) 56 if (!running && countdownInterval) { 57 clearInterval(countdownInterval) 58 } 59 } 60 61 updateCountdown() 62 countdownInterval = setInterval(updateCountdown, 1000) 63 64 // Second countdown timer (Limited Capacity section) 65 const daysEl2 = document.getElementById('countdown-days-2') 66 const hoursEl2 = document.getElementById('countdown-hours-2') 67 const minutesEl2 = document.getElementById('countdown-minutes-2') 68 const secondsEl2 = document.getElementById('countdown-seconds-2') 69 70 function updateCountdown2() { 71 const running = updateCountdownForElements( 72 daysEl2, 73 hoursEl2, 74 minutesEl2, 75 secondsEl2, 76 eventDate 77 ) 78 if (!running && countdownInterval2) { 79 clearInterval(countdownInterval2) 80 } 81 } 82 83 updateCountdown2() 84 countdownInterval2 = setInterval(updateCountdown2, 1000) 85} 86 87export function init() { 88 // Start countdown timer 89 startCountdown() 90 91 // 2-Step Form Functionality 92 const formStep1 = document.getElementById('form-step-1') 93 const formStep2 = document.getElementById('form-step-2') 94 const nextStepBtn = document.getElementById('next-step-btn') 95 const prevStepBtn = document.getElementById('prev-step-btn') 96 const step1Indicator = document.getElementById('step1-indicator') 97 const step2Indicator = document.getElementById('step2-indicator') 98 const registrationForm = document.getElementById('registration-form') 99 100 if (nextStepBtn && formStep1 && formStep2) { 101 nextStepBtn.addEventListener('click', () => { 102 // Validate Step 1 103 const firstName = document.getElementById('first_name') 104 const email = document.getElementById('email') 105 106 if (!firstName.value.trim()) { 107 firstName.focus() 108 return 109 } 110 111 if (!email.value.trim() || !email.value.includes('@')) { 112 email.focus() 113 return 114 } 115 116 // Transition to Step 2 117 formStep1.classList.add('hidden') 118 formStep2.classList.remove('hidden') 119 120 // Update indicators 121 if (step1Indicator) { 122 const circle = step1Indicator.querySelector('.step-circle') 123 if (circle) { 124 circle.classList.remove('active') 125 circle.classList.add('completed') 126 } 127 const text = step1Indicator.querySelector('span') 128 if (text) text.classList.remove('text-white') 129 if (text) text.classList.add('text-[#5DBFB3]') 130 } 131 132 if (step2Indicator) { 133 const circle = step2Indicator.querySelector('.step-circle') 134 if (circle) { 135 circle.classList.remove('bg-gray-600') 136 circle.classList.add('active') 137 circle.style.background = 138 'linear-gradient(135deg, #5DBFB3 0%, #E888B8 100%)' 139 } 140 const text = step2Indicator.querySelector('span') 141 if (text) text.classList.remove('text-gray-400') 142 if (text) text.classList.add('text-white') 143 } 144 }) 145 } 146 147 if (prevStepBtn && formStep1 && formStep2) { 148 prevStepBtn.addEventListener('click', () => { 149 // Transition back to Step 1 150 formStep2.classList.add('hidden') 151 formStep1.classList.remove('hidden') 152 153 // Update indicators 154 if (step1Indicator) { 155 const circle = step1Indicator.querySelector('.step-circle') 156 if (circle) { 157 circle.classList.add('active') 158 circle.classList.remove('completed') 159 circle.style.background = 160 'linear-gradient(135deg, #5DBFB3 0%, #E888B8 100%)' 161 } 162 const text = step1Indicator.querySelector('span') 163 if (text) text.classList.add('text-white') 164 if (text) text.classList.remove('text-[#5DBFB3]') 165 } 166 167 if (step2Indicator) { 168 const circle = step2Indicator.querySelector('.step-circle') 169 if (circle) { 170 circle.classList.add('bg-gray-600') 171 circle.classList.remove('active') 172 circle.style.background = '#4B5563' 173 } 174 const text = step2Indicator.querySelector('span') 175 if (text) text.classList.add('text-gray-400') 176 if (text) text.classList.remove('text-white') 177 } 178 }) 179 } 180 181 if (registrationForm) { 182 registrationForm.addEventListener('submit', (e) => { 183 e.preventDefault() 184 185 const submitBtn = registrationForm.querySelector('button[type="submit"]') 186 if (submitBtn) { 187 const originalText = submitBtn.innerHTML 188 submitBtn.innerHTML = 189 '<i class="fa-solid fa-spinner fa-spin"></i> Processing...' 190 submitBtn.disabled = true 191 192 // Simulate form submission (replace with actual payment URL) 193 setTimeout(() => { 194 // Get selected payment plan 195 const selectedPlan = document.querySelector( 196 'input[name="payment_plan"]:checked' 197 ) 198 const planValue = selectedPlan ? selectedPlan.value : 'payment_plan' 199 200 // Show confirmation 201 alert( 202 'Thank you for registering! You will be redirected to our secure payment page.' 203 ) 204 205 // Reset button 206 submitBtn.innerHTML = originalText 207 submitBtn.disabled = false 208 209 // In production, redirect to payment processor here 210 // window.location.href = 'YOUR_PAYMENT_URL'; 211 }, 1500) 212 } 213 }) 214 } 215} 216 217export function teardown() { 218 // Clean up countdown timer 219 if (countdownInterval) { 220 clearInterval(countdownInterval) 221 countdownInterval = null 222 } 223 224 if (countdownInterval2) { 225 clearInterval(countdownInterval2) 226 countdownInterval2 = null 227 } 228 229 // Clean up event listeners 230 const nextStepBtn = document.getElementById('next-step-btn') 231 const prevStepBtn = document.getElementById('prev-step-btn') 232 const registrationForm = document.getElementById('registration-form') 233 234 if (nextStepBtn) { 235 const newBtn = nextStepBtn.cloneNode(true) 236 nextStepBtn.parentNode.replaceChild(newBtn, nextStepBtn) 237 } 238 239 if (prevStepBtn) { 240 const newBtn = prevStepBtn.cloneNode(true) 241 prevStepBtn.parentNode.replaceChild(newBtn, prevStepBtn) 242 } 243 244 if (registrationForm) { 245 const newForm = registrationForm.cloneNode(true) 246 registrationForm.parentNode.replaceChild(newForm, registrationForm) 247 } 248}
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.