169 lines
No EOL
6 KiB
JavaScript
169 lines
No EOL
6 KiB
JavaScript
// Main JavaScript for KH3 Website
|
|
|
|
// This function will handle all animations defined by data-attributes in the HTML
|
|
function initDynamicAnimations() {
|
|
const animatedElements = document.querySelectorAll("[data-anim]");
|
|
animatedElements.forEach((el) => {
|
|
const delay = el.getAttribute("data-anim-delay") || "0";
|
|
el.style.animationDelay = `${delay}ms`;
|
|
// CORRECTED: Adds the required 'animate-' prefix for Tailwind to recognize the animation
|
|
el.classList.add(`animate-${el.getAttribute('data-anim')}`);
|
|
el.style.animationFillMode = 'forwards'; // Ensure animation state persists after it runs
|
|
});
|
|
}
|
|
|
|
// Navigation functionality
|
|
function initNavigation() {
|
|
const menuToggle = document.getElementById("menuToggle");
|
|
const navMenu = document.getElementById("navMenu");
|
|
const menuGrid = document.getElementById("menuGrid");
|
|
const navLinks = document.querySelectorAll(".nav-link");
|
|
|
|
if (menuToggle && navMenu && menuGrid) {
|
|
let isMenuOpen = false;
|
|
const menuPetal = document.getElementById("menuPetal");
|
|
const menuWrap = document.getElementById("menuWrap");
|
|
|
|
if (menuWrap) menuWrap.classList.remove("open");
|
|
|
|
menuToggle.addEventListener("click", () => {
|
|
isMenuOpen = !isMenuOpen; // Toggle the state
|
|
navMenu.classList.toggle("hidden");
|
|
if (menuWrap) menuWrap.classList.toggle("open");
|
|
});
|
|
|
|
document.addEventListener("click", (e) => {
|
|
if (isMenuOpen && !menuToggle.contains(e.target) && !navMenu.contains(e.target)) {
|
|
navMenu.classList.add("hidden");
|
|
if (menuWrap) menuWrap.classList.remove("open");
|
|
isMenuOpen = false;
|
|
}
|
|
});
|
|
|
|
navLinks.forEach((link) => {
|
|
link.addEventListener("click", () => {
|
|
navMenu.classList.add("hidden");
|
|
if (menuWrap) menuWrap.classList.remove("open");
|
|
isMenuOpen = false;
|
|
});
|
|
});
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
if (e.key === "Escape" && isMenuOpen) {
|
|
navMenu.classList.add("hidden");
|
|
if (menuWrap) menuWrap.classList.remove("open");
|
|
isMenuOpen = false;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Custom cursor
|
|
function initCustomCursor() {
|
|
if (window.innerWidth <= 768) return;
|
|
const cursor = document.getElementById("customCursor");
|
|
if (!cursor) return;
|
|
|
|
document.addEventListener("mousemove", (e) => {
|
|
cursor.style.left = e.clientX - 12 + "px";
|
|
cursor.style.top = e.clientY - 12 + "px";
|
|
});
|
|
}
|
|
|
|
// Loading screen
|
|
function initLoadingScreen() {
|
|
const loadingScreen = document.getElementById("loadingScreen");
|
|
if (loadingScreen) {
|
|
setTimeout(() => {
|
|
loadingScreen.style.opacity = "0";
|
|
setTimeout(() => {
|
|
loadingScreen.style.display = "none";
|
|
}, 500);
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
|
|
// --- Main Execution ---
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
initDynamicAnimations();
|
|
initNavigation();
|
|
initActiveNav();
|
|
initCustomCursor();
|
|
initLoadingScreen();
|
|
loadTeamMembers(); //
|
|
// Add other initializations here if needed
|
|
document.getElementById('current-year').textContent = new Date().getFullYear();
|
|
});
|
|
|
|
// Handle back/forward navigation cache
|
|
window.addEventListener('pageshow', function (event) {
|
|
if (event.persisted) {
|
|
// Page was loaded from cache, so we reload to ensure scripts run correctly
|
|
window.location.reload();
|
|
}
|
|
});
|
|
|
|
// NEW: Function to load team members from JSON
|
|
async function loadTeamMembers() {
|
|
const container = document.getElementById('teamGridContainer');
|
|
// Only run this function if the container exists on the current page (i.e., on who.html)
|
|
if (!container) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('data/team.json');
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
const teamMembers = await response.json();
|
|
|
|
const teamHTML = teamMembers.map((member, index) => {
|
|
// Create the HTML for each team member card
|
|
return `
|
|
<div class="group relative team-card opacity-0" data-anim="fade-in-up" data-anim-delay="${200 + index * 100}">
|
|
<div class="bg-kh3-grey/20 p-8 rounded-lg hover:bg-kh3-grey/30 transition-all duration-500 transform hover:scale-105 hover:-translate-y-2">
|
|
<div class="w-48 h-64 bg-gradient-to-br from-kh3-red/20 to-kh3-grey/40 rounded-lg mx-auto mb-6 flex items-center justify-center overflow-hidden group-hover:shadow-lg group-hover:shadow-red-500/20 transition-all duration-500">
|
|
<img src="${member.image}" alt="${member.name.join(' ')}" class="w-full h-full object-cover rounded-lg transition-all duration-500 group-hover:scale-110" />
|
|
</div>
|
|
<div class="text-center">
|
|
<h3 class="text-2xl font-bold text-white mb-2 transition-all duration-300 group-hover:text-kh3-red group-hover:scale-105">
|
|
${member.name.join('<br>')}
|
|
</h3>
|
|
<p class="text-kh3-red font-medium transition-all duration-300 group-hover:text-red-400">
|
|
${member.title}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
|
|
container.innerHTML = teamHTML;
|
|
// After adding the cards to the DOM, re-run the animation initializer to apply the staggered delays
|
|
initDynamicAnimations();
|
|
|
|
} catch (error) {
|
|
console.error("Could not load team members:", error);
|
|
container.innerHTML = `<p class="text-center text-kh3-red col-span-full">Failed to load team members. Please try again later.</p>`;
|
|
}
|
|
}
|
|
|
|
function initActiveNav() {
|
|
const currentPage = window.location.pathname.split('/').pop();
|
|
const navLinks = document.querySelectorAll('#navMenu a');
|
|
|
|
navLinks.forEach(link => {
|
|
const linkPage = link.getAttribute('href').split('/').pop();
|
|
|
|
// Handle the index page case where the path might be empty
|
|
if (currentPage === '' && (linkPage === 'index.html' || linkPage === '')) {
|
|
link.classList.add('active');
|
|
}
|
|
// Handle other pages
|
|
else if (linkPage !== '' && currentPage === linkPage) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
} |