Spaces:
Running
Running
File size: 6,357 Bytes
7469cbf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
// Mobile menu functionality
document.addEventListener('DOMContentLoaded', function() {
const mobileMenuBtn = document.getElementById('mobile-menu-btn');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuBtn && mobileMenu) {
mobileMenuBtn.addEventListener('click', function() {
mobileMenu.classList.toggle('hidden');
// Change menu icon
const icon = mobileMenuBtn.querySelector('[data-feather]');
if (mobileMenu.classList.contains('hidden')) {
icon.setAttribute('data-feather', 'menu');
} else {
icon.setAttribute('data-feather', 'x');
}
feather.replace();
});
}
// Smooth scrolling for navigation links
const navLinks = document.querySelectorAll('a[href^="#"]');
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href');
const targetElement = document.querySelector(targetId);
if (targetElement) {
const offsetTop = targetElement.offsetTop - 80; // Account for fixed navbar
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
});
// Close mobile menu if open
if (mobileMenu && !mobileMenu.classList.contains('hidden')) {
mobileMenu.classList.add('hidden');
const icon = mobileMenuBtn.querySelector('[data-feather]');
icon.setAttribute('data-feather', 'menu');
feather.replace();
}
}
});
});
// Navbar background on scroll
const navbar = document.querySelector('nav');
window.addEventListener('scroll', function() {
if (window.scrollY > 50) {
navbar.classList.add('shadow-lg');
} else {
navbar.classList.remove('shadow-lg');
}
});
// Intersection Observer for fade-in animations
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('animate-fade-in');
}
});
}, observerOptions);
// Observe sections for animations
const sections = document.querySelectorAll('section');
sections.forEach(section => {
observer.observe(section);
});
// Add loading animation to images
const images = document.querySelectorAll('img');
images.forEach(img => {
img.addEventListener('load', function() {
this.style.opacity = '1';
});
});
// Typing effect for hero text (optional enhancement)
function typeWriter(element, text, speed = 100) {
let i = 0;
element.innerHTML = '';
function type() {
if (i < text.length) {
text.charAt(i element.innerHTML +=);
i++;
setTimeout(type, speed);
}
}
type();
}
// Contact form handling (if you add a form)
const contactForm = document.getElementById('contact-form');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
// Get form data
const formData = new FormData(this);
const data = Object.fromEntries(formData);
// Simulate form submission
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.textContent = 'Sending...';
submitBtn.disabled = true;
setTimeout(() => {
submitBtn.textContent = 'Message Sent!';
setTimeout(() => {
submitBtn.textContent = originalText;
submitBtn.disabled = false;
this.reset();
}, 2000);
}, 1000);
});
}
// Theme toggle functionality (if you want to add dark mode later)
function toggleTheme() {
document.body.classList.toggle('dark');
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
}
// Load saved theme
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
document.body.classList.add('dark');
}
// Add keyboard navigation
document.addEventListener('keydown', function(e) {
// ESC key closes mobile menu
if (e.key === 'Escape' && mobileMenu && !mobileMenu.classList.contains('hidden')) {
mobileMenu.classList.add('hidden');
const icon = mobileMenuBtn.querySelector('[data-feather]');
icon.setAttribute('data-feather', 'menu');
feather.replace();
}
});
// Add performance optimizations
// Lazy load images
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) = entry.target;
{
const img img.src = img.dataset.src;
img.classList.remove('lazy');
imageObserver.unobserve(img);
}
});
});
const lazyImages = document.querySelectorAll('img[data-src]');
lazyImages.forEach(img => imageObserver.observe(img));
}
// Add error handling for images
images.forEach(img => {
img.addEventListener('error', function() {
this.style.display = 'none';
});
});
// Console message for developers
console.log('%c👋 Hi there! Thanks for checking out my portfolio.', 'color: #6366f1; font-size: 16px; font-weight: bold;');
console.log('%cIf you\'re interested in the code, feel free to reach out!', 'color: #4f46e5; font-size: 14px;');
}); |