Files
gitblog/web/static/js/main.js
2025-09-15 04:02:11 +03:00

132 lines
3.7 KiB
JavaScript

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);