Files
donovan-portfolio/js/main.js
2026-01-27 02:18:01 +00:00

73 lines
2.1 KiB
JavaScript

// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
const navHeight = document.querySelector('.nav').offsetHeight;
const targetPosition = target.getBoundingClientRect().top + window.pageYOffset - navHeight;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
});
});
// Nav background on scroll
const nav = document.querySelector('.nav');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
nav.style.boxShadow = '0 1px 3px rgba(0,0,0,0.1)';
} else {
nav.style.boxShadow = 'none';
}
lastScroll = currentScroll;
});
// Form submission handling
const form = document.querySelector('.contact-form');
if (form) {
form.addEventListener('submit', async (e) => {
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
// Show loading state
submitBtn.textContent = 'Sending...';
submitBtn.disabled = true;
// If using Formspree, let it handle normally
// This is just for UX feedback
setTimeout(() => {
submitBtn.textContent = originalText;
submitBtn.disabled = false;
}, 3000);
});
}
// Intersection Observer for fade-in animations
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0.1
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe elements (if you want fade-in effects, add .fade-in class to elements)
document.querySelectorAll('.fade-in').forEach(el => {
observer.observe(el);
});