Files
website/static/js/script.js
SimolZimol 09b0b2f3b7 new file: .gitignore
new file:   Dockerfile
	new file:   README.md
	new file:   app.py
	new file:   index.html
	new file:   projekte des/PROJECT_DESCRIPTION.txt
	new file:   projekte des/WEBSITE_DESCRIPTION.md
	new file:   projekte des/website_project_description_en.txt
	new file:   requirements.txt
	new file:   script.js
	new file:   static/css/styles.css
	new file:   static/js/script.js
	new file:   styles.css
	new file:   templates/about.html
	new file:   templates/base.html
	new file:   templates/contact.html
	new file:   templates/index.html
	new file:   templates/minecraft.html
	new file:   templates/project_detail.html
	new file:   templates/projects.html
2025-10-26 19:13:18 +01:00

99 lines
3.4 KiB
JavaScript

// Mirrors root script.js for Flask static serving
// Mobile Navigation Toggle
document.addEventListener('DOMContentLoaded', function() {
const hamburger = document.querySelector('.hamburger');
const navLinks = document.querySelector('.nav-links');
if (hamburger && navLinks) {
hamburger.addEventListener('click', function() {
navLinks.classList.toggle('active');
hamburger.classList.toggle('active');
});
document.querySelectorAll('.nav-links a').forEach(link => {
link.addEventListener('click', () => {
navLinks.classList.remove('active');
hamburger.classList.remove('active');
});
});
}
});
// Smooth scrolling for navigation links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
const href = this.getAttribute('href');
if (href && href.startsWith('#')) {
e.preventDefault();
const target = document.querySelector(href);
if (target) {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
});
});
// Navbar background on scroll
window.addEventListener('scroll', function() {
const navbar = document.querySelector('.navbar');
if (navbar) {
navbar.style.background = window.scrollY > 100 ? 'rgba(10, 10, 10, 0.98)' : 'rgba(10, 10, 10, 0.95)';
}
});
// Intersection Observer for animations
const observeElements = () => {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
document.querySelectorAll('.project-card, .tech-item, .contact-card').forEach((el, i) => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = `opacity 0.6s ease ${i * 0.1}s, transform 0.6s ease ${i * 0.1}s`;
observer.observe(el);
});
};
document.addEventListener('DOMContentLoaded', observeElements);
// Hover effects for project cards
document.querySelectorAll('.project-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-10px) scale(1.02)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0) scale(1)';
});
});
// Active state to navigation links based on scroll position
const updateActiveNav = () => {
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-links a[href^="#"]');
let current = '';
sections.forEach(section => {
if (pageYOffset >= section.offsetTop - 200) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.toggle('active', link.getAttribute('href') === `#${current}`);
});
};
window.addEventListener('scroll', updateActiveNav);
// Inject minimal CSS for active nav indicator
const style = document.createElement('style');
style.textContent = `
.nav-links a.active { color: #00d4ff !important; }
.nav-links a.active::before { width: 100% !important; }
`;
document.head.appendChild(style);