Website overhaul completed
This commit is contained in:
parent
4cb566828a
commit
9115a41488
18 changed files with 1407 additions and 263 deletions
111
src/js/sectionTracker.js
Normal file
111
src/js/sectionTracker.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
// Section tracking and navigation highlighting
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const sections = document.querySelectorAll("section[id]");
|
||||
const navLinks = document.querySelectorAll(".nav-links a");
|
||||
|
||||
// Configuration
|
||||
const offset = 100; // Offset for when section becomes "active" (accounts for fixed nav)
|
||||
let isScrolling = false;
|
||||
|
||||
function getCurrentSection() {
|
||||
let currentSection = "";
|
||||
const scrollPosition = window.scrollY + offset;
|
||||
|
||||
// Find which section we're currently in
|
||||
sections.forEach((section) => {
|
||||
const sectionTop = section.offsetTop;
|
||||
const sectionHeight = section.offsetHeight;
|
||||
const sectionId = section.getAttribute("id");
|
||||
|
||||
if (
|
||||
scrollPosition >= sectionTop &&
|
||||
scrollPosition < sectionTop + sectionHeight
|
||||
) {
|
||||
currentSection = sectionId;
|
||||
}
|
||||
});
|
||||
|
||||
// Special case: if we're at the very top, activate the first section
|
||||
if (window.scrollY < 100) {
|
||||
currentSection = sections[0]?.getAttribute("id") || "";
|
||||
}
|
||||
|
||||
return currentSection;
|
||||
}
|
||||
|
||||
function updateActiveNavLink() {
|
||||
const currentSection = getCurrentSection();
|
||||
|
||||
navLinks.forEach((link) => {
|
||||
const href = link.getAttribute("href");
|
||||
|
||||
// Remove active class from all links
|
||||
link.classList.remove("active");
|
||||
|
||||
// Add active class to matching link
|
||||
if (href === `#${currentSection}`) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Throttle scroll events for better performance
|
||||
function handleScroll() {
|
||||
if (!isScrolling) {
|
||||
window.requestAnimationFrame(() => {
|
||||
updateActiveNavLink();
|
||||
isScrolling = false;
|
||||
});
|
||||
isScrolling = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for scroll events
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
|
||||
// Update on page load
|
||||
updateActiveNavLink();
|
||||
|
||||
// Also update when clicking nav links (for smooth scroll)
|
||||
navLinks.forEach((link) => {
|
||||
link.addEventListener("click", function (e) {
|
||||
// Remove active from all
|
||||
navLinks.forEach((l) => l.classList.remove("active"));
|
||||
// Add active to clicked link
|
||||
this.classList.add("active");
|
||||
|
||||
// Let the scroll handler update it properly after scroll completes
|
||||
setTimeout(updateActiveNavLink, 100);
|
||||
});
|
||||
});
|
||||
|
||||
// Handle hash changes (browser back/forward)
|
||||
window.addEventListener("hashchange", function () {
|
||||
setTimeout(updateActiveNavLink, 100);
|
||||
});
|
||||
|
||||
// Intersection Observer for more precise tracking (progressive enhancement)
|
||||
if ("IntersectionObserver" in window) {
|
||||
const observerOptions = {
|
||||
rootMargin: "-20% 0px -70% 0px", // Trigger when section is roughly in the middle of viewport
|
||||
threshold: 0,
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
const sectionId = entry.target.getAttribute("id");
|
||||
navLinks.forEach((link) => {
|
||||
link.classList.remove("active");
|
||||
if (link.getAttribute("href") === `#${sectionId}`) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
// Observe all sections
|
||||
sections.forEach((section) => observer.observe(section));
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue