class BlogApp { constructor() { this.init(); } init() { this.setupSmoothScrolling(); this.setupLazyLoading(); this.setupSearch(); this.setupAnimations(); } setupSmoothScrolling() { const links = document.querySelectorAll('a[href^="#"]'); links.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const target = document.querySelector(link.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } setupLazyLoading() { const images = document.querySelectorAll('img[data-src]'); const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.classList.remove('lazy'); observer.unobserve(img); } }); }); images.forEach(img => imageObserver.observe(img)); } setupSearch() { const searchInput = document.getElementById('search-input'); if (searchInput) { searchInput.addEventListener('input', this.debounce((e) => { this.performSearch(e.target.value); }, 300)); } } setupAnimations() { const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-in'); } }); }, observerOptions); const animatedElements = document.querySelectorAll('.post-card, .post, .page'); animatedElements.forEach(el => { el.classList.add('animate-ready'); observer.observe(el); }); } performSearch(query) { if (query.length < 2) return; const posts = document.querySelectorAll('.post-card'); posts.forEach(post => { const title = post.querySelector('.post-title').textContent.toLowerCase(); const excerpt = post.querySelector('.post-excerpt').textContent.toLowerCase(); const tags = Array.from(post.querySelectorAll('.tag')).map(tag => tag.textContent.toLowerCase()); const matches = title.includes(query.toLowerCase()) || excerpt.includes(query.toLowerCase()) || tags.some(tag => tag.includes(query.toLowerCase())); post.style.display = matches ? 'block' : 'none'; }); } debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } } document.addEventListener('DOMContentLoaded', () => { new BlogApp(); }); const style = document.createElement('style'); style.textContent = ` .animate-ready { opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease, transform 0.6s ease; } .animate-in { opacity: 1; transform: translateY(0); } .lazy { opacity: 0; transition: opacity 0.3s ease; } .lazy.loaded { opacity: 1; } `; document.head.appendChild(style);