188 lines
5.1 KiB
JavaScript
188 lines
5.1 KiB
JavaScript
// 2026 Horizons - Interactive Features
|
|
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
// Theme Toggle
|
|
const themeToggle = document.getElementById("themeToggle");
|
|
const themeIcon = themeToggle.querySelector("i");
|
|
|
|
// Check for saved theme or prefer-color-scheme
|
|
const savedTheme = localStorage.getItem("theme");
|
|
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
|
|
if (savedTheme === "dark" || (!savedTheme && prefersDark)) {
|
|
document.documentElement.setAttribute("data-theme", "dark");
|
|
themeIcon.className = "fas fa-sun";
|
|
}
|
|
|
|
themeToggle.addEventListener("click", function () {
|
|
const currentTheme = document.documentElement.getAttribute("data-theme");
|
|
|
|
if (currentTheme === "dark") {
|
|
document.documentElement.removeAttribute("data-theme");
|
|
themeIcon.className = "fas fa-moon";
|
|
localStorage.setItem("theme", "light");
|
|
} else {
|
|
document.documentElement.setAttribute("data-theme", "dark");
|
|
themeIcon.className = "fas fa-sun";
|
|
localStorage.setItem("theme", "dark");
|
|
}
|
|
});
|
|
|
|
// Smooth scroll for navigation links
|
|
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
|
|
anchor.addEventListener("click", function (e) {
|
|
e.preventDefault();
|
|
|
|
const targetId = this.getAttribute("href");
|
|
if (targetId === "#") return;
|
|
|
|
const targetElement = document.querySelector(targetId);
|
|
if (targetElement) {
|
|
const headerHeight = document.querySelector(".navbar").offsetHeight;
|
|
const targetPosition = targetElement.offsetTop - headerHeight - 20;
|
|
|
|
window.scrollTo({
|
|
top: targetPosition,
|
|
behavior: "smooth",
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Navbar scroll effect
|
|
const navbar = document.querySelector(".navbar");
|
|
let lastScrollTop = 0;
|
|
|
|
window.addEventListener("scroll", function () {
|
|
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
|
|
// Hide/show navbar on scroll
|
|
if (scrollTop > lastScrollTop && scrollTop > 100) {
|
|
navbar.style.transform = "translateY(-100%)";
|
|
} else {
|
|
navbar.style.transform = "translateY(0)";
|
|
}
|
|
|
|
lastScrollTop = scrollTop;
|
|
|
|
// Add shadow when scrolled
|
|
if (scrollTop > 10) {
|
|
navbar.style.boxShadow = "var(--shadow-md)";
|
|
} else {
|
|
navbar.style.boxShadow = "none";
|
|
}
|
|
});
|
|
|
|
// Animate elements on scroll
|
|
const observerOptions = {
|
|
threshold: 0.1,
|
|
rootMargin: "0px 0px -50px 0px",
|
|
};
|
|
|
|
const observer = new IntersectionObserver(function (entries) {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add("fade-in");
|
|
observer.unobserve(entry.target);
|
|
}
|
|
});
|
|
}, observerOptions);
|
|
|
|
// Observe elements to animate
|
|
document
|
|
.querySelectorAll(
|
|
".trend-card, .opportunity-card, .challenge-card, .highlight-card",
|
|
)
|
|
.forEach((el) => {
|
|
observer.observe(el);
|
|
});
|
|
|
|
// Stats counter animation
|
|
const stats = document.querySelectorAll(".stat-number");
|
|
|
|
const statsObserver = new IntersectionObserver(
|
|
function (entries) {
|
|
entries.forEach((entry) => {
|
|
if (entry.isIntersecting) {
|
|
const stat = entry.target;
|
|
const targetValue = parseInt(stat.textContent);
|
|
let currentValue = 0;
|
|
const increment = targetValue / 50;
|
|
const duration = 1500;
|
|
const stepTime = Math.floor(duration / 50);
|
|
|
|
const timer = setInterval(() => {
|
|
currentValue += increment;
|
|
if (currentValue >= targetValue) {
|
|
stat.textContent = targetValue;
|
|
clearInterval(timer);
|
|
} else {
|
|
stat.textContent = Math.floor(currentValue);
|
|
}
|
|
}, stepTime);
|
|
|
|
statsObserver.unobserve(stat);
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0.5 },
|
|
);
|
|
|
|
stats.forEach((stat) => {
|
|
statsObserver.observe(stat);
|
|
});
|
|
|
|
// Hover effects for cards
|
|
document
|
|
.querySelectorAll(".trend-card, .opportunity-card, .challenge-card")
|
|
.forEach((card) => {
|
|
card.addEventListener("mouseenter", function () {
|
|
this.style.zIndex = "10";
|
|
});
|
|
|
|
card.addEventListener("mouseleave", function () {
|
|
this.style.zIndex = "1";
|
|
});
|
|
});
|
|
|
|
// Current year in footer
|
|
const currentYear = new Date().getFullYear();
|
|
const yearElement = document.querySelector(".copyright p");
|
|
if (yearElement) {
|
|
yearElement.textContent = yearElement.textContent.replace(
|
|
"2026",
|
|
currentYear,
|
|
);
|
|
}
|
|
|
|
// Initialize animations
|
|
setTimeout(() => {
|
|
document.body.style.opacity = "1";
|
|
}, 100);
|
|
});
|
|
|
|
// Add CSS for initial load
|
|
const style = document.createElement("style");
|
|
style.textContent = `
|
|
body {
|
|
opacity: 0;
|
|
transition: opacity 0.5s ease-in;
|
|
}
|
|
|
|
.fade-in {
|
|
animation: fadeIn 0.8s ease-out forwards;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
`;
|
|
document.head.appendChild(style);
|