Current directory: /home/klas4s23/domains/585455.klas4s23.mid-ica.nl/public_html/Gastenboek/uploads
// ===== Clean Website JS with Scroll Animations =====
// ===== Navigation Scroll Effect =====
const nav = document.querySelector('.nav');
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
nav.style.boxShadow = '0 2px 20px rgba(0, 0, 0, 0.08)';
nav.classList.add('scrolled');
} else {
nav.style.boxShadow = 'none';
nav.classList.remove('scrolled');
}
});
// ===== Smooth Scroll =====
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// ===== Stats Counter Animation =====
const stats = document.querySelectorAll('.stat-number');
let statsAnimated = false;
function animateStats() {
stats.forEach((stat, index) => {
const target = parseInt(stat.getAttribute('data-target'));
const duration = 2000;
setTimeout(() => {
const startTime = performance.now();
const updateCount = (currentTime) => {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
// Ease out cubic
const easedProgress = 1 - Math.pow(1 - progress, 3);
const current = Math.floor(easedProgress * target);
stat.textContent = current;
if (progress < 1) {
requestAnimationFrame(updateCount);
} else {
stat.textContent = target;
}
};
requestAnimationFrame(updateCount);
}, index * 200); // Stagger each stat
});
}
// Intersection Observer for stats
const statsSection = document.querySelector('.hero-stats');
const statsObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !statsAnimated) {
statsAnimated = true;
animateStats();
}
});
}, { threshold: 0.5 });
if (statsSection) {
statsObserver.observe(statsSection);
}
// ===== Enhanced Scroll Reveal Animation =====
const revealElements = document.querySelectorAll('.timeline-item, .silicon-card, .feature, .section-header, .about-text, .code-window, .terminal-window, .legend-card');
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('revealed');
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -80px 0px'
});
revealElements.forEach((el, index) => {
el.classList.add('scroll-reveal');
el.style.transitionDelay = `${(index % 4) * 0.1}s`;
revealObserver.observe(el);
});
// ===== Staggered Grid Animation =====
const gridContainers = document.querySelectorAll('.silicon-grid, .features-grid');
gridContainers.forEach(container => {
const gridObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const children = entry.target.children;
Array.from(children).forEach((child, i) => {
setTimeout(() => {
child.classList.add('revealed');
}, i * 150);
});
}
});
}, { threshold: 0.2 });
gridObserver.observe(container);
});
// ===== Timeline Animation =====
const timelineItems = document.querySelectorAll('.timeline-item');
const timelineObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('timeline-revealed');
// Animate the marker
const marker = entry.target.querySelector('.marker-dot');
if (marker) {
marker.classList.add('marker-active');
}
}
});
}, { threshold: 0.3, rootMargin: '0px 0px -100px 0px' });
timelineItems.forEach(item => {
timelineObserver.observe(item);
});
// ===== Section Title Animation =====
const sectionTitles = document.querySelectorAll('.section-title, .section-subtitle');
const titleObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('title-revealed');
}
});
}, { threshold: 0.5 });
sectionTitles.forEach(title => {
title.classList.add('title-animate');
titleObserver.observe(title);
});
// ===== Fade Up Animation for Hero Elements =====
const heroElements = document.querySelectorAll('.hero-badge, .hero-title, .hero-description, .hero-cta, .hero-stats');
heroElements.forEach((el, index) => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
setTimeout(() => {
el.style.transition = 'all 0.8s cubic-bezier(0.16, 1, 0.3, 1)';
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
}, 300 + (index * 150));
});
// ===== Legends Carousel =====
const legendCards = document.querySelectorAll('.legend-card');
const carouselDots = document.querySelectorAll('.carousel-dots .dot');
const prevBtn = document.querySelector('.carousel-btn.prev');
const nextBtn = document.querySelector('.carousel-btn.next');
let currentLegend = 0;
function showLegend(index) {
legendCards.forEach((card, i) => {
card.classList.remove('active');
card.style.display = 'none';
carouselDots[i]?.classList.remove('active');
});
legendCards[index].classList.add('active');
legendCards[index].style.display = 'grid';
carouselDots[index]?.classList.add('active');
currentLegend = index;
}
if (prevBtn && nextBtn) {
prevBtn.addEventListener('click', () => {
const newIndex = currentLegend === 0 ? legendCards.length - 1 : currentLegend - 1;
showLegend(newIndex);
});
nextBtn.addEventListener('click', () => {
const newIndex = currentLegend === legendCards.length - 1 ? 0 : currentLegend + 1;
showLegend(newIndex);
});
}
carouselDots.forEach((dot, index) => {
dot.addEventListener('click', () => showLegend(index));
});
// Auto-rotate carousel
setInterval(() => {
const newIndex = currentLegend === legendCards.length - 1 ? 0 : currentLegend + 1;
showLegend(newIndex);
}, 5000);
// ===== Terminal Typing Effect =====
const typingText = document.getElementById('typing-text');
const terminalOutput = document.getElementById('terminal-output');
const command = 'git log --oneline -5 history';
const outputs = [
`<div class="output-line"><span style="color: #fbbf24">a1b2c3d</span> <span style="color: #38bdf8">feat:</span> Added TypeScript (2012)</div>`,
`<div class="output-line"><span style="color: #fbbf24">e4f5g6h</span> <span style="color: #38bdf8">feat:</span> Added JavaScript (1995)</div>`,
`<div class="output-line"><span style="color: #fbbf24">i7j8k9l</span> <span style="color: #38bdf8">feat:</span> Added Python (1991)</div>`,
`<div class="output-line"><span style="color: #fbbf24">m0n1o2p</span> <span style="color: #38bdf8">feat:</span> Added C++ (1983)</div>`,
`<div class="output-line"><span style="color: #fbbf24">q3r4s5t</span> <span style="color: #4ade80">init:</span> Initial commit - Fortran (1957)</div>`,
];
let charIndex = 0;
let isTyping = false;
function typeCommand() {
if (charIndex < command.length) {
typingText.textContent += command[charIndex];
charIndex++;
setTimeout(typeCommand, 50);
} else {
setTimeout(() => {
document.querySelector('.terminal-line .cursor').style.display = 'none';
terminalOutput.innerHTML = outputs.join('');
}, 300);
}
}
// Start typing when terminal section is visible
const terminalSection = document.querySelector('.terminal-section');
const terminalObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !isTyping) {
isTyping = true;
setTimeout(typeCommand, 500);
}
});
}, { threshold: 0.3 });
if (terminalSection) {
terminalObserver.observe(terminalSection);
}
// ===== Active Nav Link =====
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
window.addEventListener('scroll', () => {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop - 150;
const sectionHeight = section.offsetHeight;
if (window.pageYOffset >= sectionTop && window.pageYOffset < sectionTop + sectionHeight) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
const linkHref = link.getAttribute('href');
if (linkHref === `#${current}`) {
link.classList.add('active');
}
});
});
// ===== Page Load =====
document.body.style.opacity = '1';