1/** 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * All rights reserved. 4 * 5 * This source code is licensed under the BSD-style license found in the 6 * LICENSE file in the root directory of this source tree. 7 */ 8 9document.addEventListener("DOMContentLoaded", function() { 10 const steps = Array.from(document.querySelectorAll('.progress-bar-item')); 11 const h2s = Array.from(document.querySelectorAll('h2')); 12 13 // Populate captions from h2s 14 h2s.forEach((h2, index) => { 15 const captionElem = document.getElementById(`caption-${index + 1}`); 16 if (captionElem) { 17 captionElem.innerText = h2.innerText; 18 } 19 }); 20 21 // Throttle function to optimize performance 22 function throttle(func, delay) { 23 let lastCall = 0; 24 return function() { 25 const now = Date.now(); 26 if (now - lastCall < delay) return; 27 lastCall = now; 28 func.apply(this, arguments); 29 } 30 } 31 32 document.addEventListener("scroll", throttle(function() { 33 let activeIndex = 0; 34 let closestDistance = Number.MAX_VALUE; 35 const totalHeight = document.documentElement.scrollHeight; 36 const viewportHeight = window.innerHeight; 37 const scrollBottom = window.scrollY + viewportHeight; 38 const isAtBottom = totalHeight === scrollBottom; 39 40 h2s.forEach((h2, index) => { 41 const rect = h2.getBoundingClientRect(); 42 const distanceToTop = Math.abs(rect.top); 43 if (distanceToTop < closestDistance) { 44 closestDistance = distanceToTop; 45 activeIndex = index; 46 } 47 }); 48 49 steps.forEach((step, index) => { 50 if (isAtBottom) { 51 step.classList.remove('active'); 52 step.classList.add('completed'); 53 } else { 54 if (index < activeIndex) { 55 step.classList.remove('active'); 56 step.classList.add('completed'); 57 } else if (index === activeIndex) { 58 step.classList.add('active'); 59 step.classList.remove('completed'); 60 } else { 61 step.classList.remove('active', 'completed'); 62 } 63 } 64 }); 65 }, 100)); 66}); 67