/
Anders0n
/
TestWEB
Обзор
Документация
Войти
/
Anders0n
/
TestWEB
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
script.js
902 строки
25 KB
Anders0n
Test
20 дек 2025, 09:28
20 дек 2025, 09:28
bfc4d0f
Код
Авторство
О чём код?
// Main JavaScript functionality for Literary Forum website document.addEventListener('DOMContentLoaded', function () { console.log('Literary Forum website loaded successfully!'); // Initialize all functionality initNavigation(); initFilters(); initModals(); initLightbox(); initGallery(); initRepository(); initSearch(); initAnimations(); initForms(); }); // Navigation functionality function initNavigation() { const navToggle = document.getElementById('nav-toggle'); const navMenu = document.getElementById('nav-menu'); if (navToggle && navMenu) { navToggle.addEventListener('click', function () { navMenu.classList.toggle('active'); navToggle.classList.toggle('active'); }); // Close menu when clicking on a link const navLinks = document.querySelectorAll('.nav-link'); navLinks.forEach(link => { link.addEventListener('click', function () { navMenu.classList.remove('active'); navToggle.classList.remove('active'); }); }); // Close menu when clicking outside document.addEventListener('click', function (e) { if (!navToggle.contains(e.target) && !navMenu.contains(e.target)) { navMenu.classList.remove('active'); navToggle.classList.remove('active'); } }); } // Navbar scroll effect window.addEventListener('scroll', function () { const navbar = document.querySelector('.navbar'); if (navbar) { if (window.scrollY > 100) { navbar.style.background = 'rgba(255, 255, 255, 0.95)'; navbar.style.backdropFilter = 'blur(10px)'; } else { navbar.style.background = '#ffffff'; navbar.style.backdropFilter = 'none'; } } }); } // Filter functionality for different pages function initFilters() { // Material filters (Reading Room) const materialFilters = document.querySelectorAll('.category-filters .filter-btn'); const materialCards = document.querySelectorAll('.material-card'); materialFilters.forEach(filter => { filter.addEventListener('click', function () { // Update active filter materialFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); const category = this.getAttribute('data-category'); // Filter materials materialCards.forEach(card => { if (category === 'all' || card.getAttribute('data-category') === category) { card.style.display = 'block'; setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'translateY(0)'; }, 100); } else { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; setTimeout(() => { card.style.display = 'none'; }, 300); } }); }); }); // Resident filters const residentFilters = document.querySelectorAll('.role-filters .filter-btn'); const residentCards = document.querySelectorAll('.resident-card'); residentFilters.forEach(filter => { filter.addEventListener('click', function () { residentFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); const role = this.getAttribute('data-role'); residentCards.forEach(card => { if (role === 'all' || card.getAttribute('data-role') === role) { card.style.display = 'block'; setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'scale(1)'; }, 100); } else { card.style.opacity = '0'; card.style.transform = 'scale(0.8)'; setTimeout(() => { card.style.display = 'none'; }, 300); } }); }); }); // Competition winner filters const winnerFilters = document.querySelectorAll('.archive-filters .filter-btn'); const winnerCards = document.querySelectorAll('.winner-card'); winnerFilters.forEach(filter => { filter.addEventListener('click', function () { winnerFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); const year = this.getAttribute('data-year'); winnerCards.forEach(card => { if (year === 'all' || card.getAttribute('data-year') === year) { card.style.display = 'block'; setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'translateY(0)'; }, 100); } else { card.style.opacity = '0'; card.style.transform = 'translateY(20px)'; setTimeout(() => { card.style.display = 'none'; }, 300); } }); }); }); // Repository filters const yearFilters = document.querySelectorAll('.year-filters .filter-btn'); const typeFilters = document.querySelectorAll('.type-filters .filter-btn'); const archiveCards = document.querySelectorAll('.archive-card'); const contentItems = document.querySelectorAll('.content-item'); const videoItems = document.querySelectorAll('.video-item'); function filterRepository() { const selectedYear = document.querySelector('.year-filters .filter-btn.active')?.getAttribute('data-year') || 'all'; const selectedType = document.querySelector('.type-filters .filter-btn.active')?.getAttribute('data-type') || 'all'; // Filter archive cards archiveCards.forEach(card => { const cardYear = card.getAttribute('data-year'); if (selectedYear === 'all' || cardYear === selectedYear) { card.style.display = 'block'; } else { card.style.display = 'none'; } }); // Filter content items contentItems.forEach(item => { const itemType = item.getAttribute('data-type'); if (selectedType === 'all' || itemType === selectedType) { item.style.display = 'flex'; } else { item.style.display = 'none'; } }); // Filter video items videoItems.forEach(item => { const itemYear = item.getAttribute('data-year'); const itemType = item.getAttribute('data-type'); if ((selectedYear === 'all' || itemYear === selectedYear) && (selectedType === 'all' || itemType === selectedType)) { item.style.display = 'block'; } else { item.style.display = 'none'; } }); } yearFilters.forEach(filter => { filter.addEventListener('click', function () { yearFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); filterRepository(); }); }); typeFilters.forEach(filter => { filter.addEventListener('click', function () { typeFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); filterRepository(); }); }); // Gallery filters const albumFilters = document.querySelectorAll('.album-filters .filter-btn'); const tagFilters = document.querySelectorAll('.tag-filters .tag-filter'); const albumCards = document.querySelectorAll('.album-card'); albumFilters.forEach(filter => { filter.addEventListener('click', function () { albumFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); const album = this.getAttribute('data-album'); albumCards.forEach(card => { if (album === 'all' || card.getAttribute('data-album') === album) { card.style.display = 'block'; setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'scale(1)'; }, 100); } else { card.style.opacity = '0'; card.style.transform = 'scale(0.8)'; setTimeout(() => { card.style.display = 'none'; }, 300); } }); }); }); tagFilters.forEach(filter => { filter.addEventListener('click', function () { tagFilters.forEach(f => f.classList.remove('active')); this.classList.add('active'); const tag = this.getAttribute('data-tag'); albumCards.forEach(card => { const cardTags = card.querySelectorAll('.tag'); let hasTag = tag === 'all'; cardTags.forEach(cardTag => { if (cardTag.textContent.trim() === tag) { hasTag = true; } }); if (hasTag) { card.style.display = 'block'; setTimeout(() => { card.style.opacity = '1'; card.style.transform = 'scale(1)'; }, 100); } else { card.style.opacity = '0'; card.style.transform = 'scale(0.8)'; setTimeout(() => { card.style.display = 'none'; }, 300); } }); }); }); } // Modal functionality function initModals() { // Resident profile modal const residentModal = document.getElementById('resident-modal'); const viewProfileBtns = document.querySelectorAll('.view-profile'); const modalClose = document.querySelectorAll('.modal-close'); viewProfileBtns.forEach(btn => { btn.addEventListener('click', function (e) { e.preventDefault(); if (residentModal) { residentModal.style.display = 'block'; document.body.style.overflow = 'hidden'; // Animate modal appearance setTimeout(() => { residentModal.style.opacity = '1'; }, 10); } }); }); // Video modal const videoModal = document.getElementById('video-modal'); const videoItems = document.querySelectorAll('.video-item'); videoItems.forEach(item => { item.addEventListener('click', function () { const title = this.querySelector('.video-info h3').textContent; const description = this.querySelector('.video-info p').textContent; if (videoModal) { document.getElementById('video-title').textContent = title; document.getElementById('video-description').textContent = description; videoModal.style.display = 'block'; document.body.style.overflow = 'hidden'; } }); }); // Close modals modalClose.forEach(close => { close.addEventListener('click', function () { const modal = this.closest('.modal'); if (modal) { modal.style.opacity = '0'; setTimeout(() => { modal.style.display = 'none'; document.body.style.overflow = 'auto'; }, 300); } }); }); // Close modal when clicking outside window.addEventListener('click', function (e) { if (e.target.classList.contains('modal')) { e.target.style.opacity = '0'; setTimeout(() => { e.target.style.display = 'none'; document.body.style.overflow = 'auto'; }, 300); } }); } // Lightbox functionality for gallery function initLightbox() { const lightbox = document.getElementById('lightbox'); const lightboxImage = document.getElementById('lightbox-image'); const lightboxVideo = document.getElementById('lightbox-video'); const lightboxTitle = document.getElementById('lightbox-title'); const lightboxDescription = document.getElementById('lightbox-description'); const lightboxTags = document.getElementById('lightbox-tags'); const lightboxClose = document.querySelector('.lightbox-close'); const lightboxPrev = document.querySelector('.lightbox-prev'); const lightboxNext = document.querySelector('.lightbox-next'); let currentPhotoIndex = 0; let currentPhotos = []; function openLightbox(photos, index) { currentPhotos = photos; currentPhotoIndex = index; showPhoto(currentPhotoIndex); if (lightbox) { lightbox.style.display = 'block'; document.body.style.overflow = 'hidden'; setTimeout(() => { lightbox.style.opacity = '1'; }, 10); } } function showPhoto(index) { if (currentPhotos[index]) { const photo = currentPhotos[index]; if (lightboxImage && lightboxVideo) { if (photo.type === 'video') { lightboxImage.style.display = 'none'; lightboxVideo.style.display = 'block'; lightboxVideo.src = photo.src; } else { lightboxVideo.style.display = 'none'; lightboxImage.style.display = 'block'; lightboxImage.src = photo.src; lightboxImage.alt = photo.title; } } if (lightboxTitle) lightboxTitle.textContent = photo.title; if (lightboxDescription) lightboxDescription.textContent = photo.description; if (lightboxTags) { lightboxTags.innerHTML = ''; photo.tags.forEach(tag => { const tagElement = document.createElement('span'); tagElement.className = 'tag'; tagElement.textContent = tag; lightboxTags.appendChild(tagElement); }); } } } function closeLightbox() { if (lightbox) { lightbox.style.opacity = '0'; setTimeout(() => { lightbox.style.display = 'none'; document.body.style.overflow = 'auto'; if (lightboxVideo) { lightboxVideo.pause(); lightboxVideo.src = ''; } }, 300); } } // Event listeners if (lightboxClose) { lightboxClose.addEventListener('click', closeLightbox); } if (lightboxPrev) { lightboxPrev.addEventListener('click', function () { currentPhotoIndex = (currentPhotoIndex - 1 + currentPhotos.length) % currentPhotos.length; showPhoto(currentPhotoIndex); }); } if (lightboxNext) { lightboxNext.addEventListener('click', function () { currentPhotoIndex = (currentPhotoIndex + 1) % currentPhotos.length; showPhoto(currentPhotoIndex); }); } // Keyboard navigation document.addEventListener('keydown', function (e) { if (lightbox && lightbox.style.display === 'block') { switch (e.key) { case 'Escape': closeLightbox(); break; case 'ArrowLeft': currentPhotoIndex = (currentPhotoIndex - 1 + currentPhotos.length) % currentPhotos.length; showPhoto(currentPhotoIndex); break; case 'ArrowRight': currentPhotoIndex = (currentPhotoIndex + 1) % currentPhotos.length; showPhoto(currentPhotoIndex); break; } } }); // Close lightbox when clicking outside if (lightbox) { lightbox.addEventListener('click', function (e) { if (e.target === lightbox) { closeLightbox(); } }); } // Make openLightbox globally available window.openLightbox = openLightbox; } // Gallery functionality function initGallery() { const albumBtns = document.querySelectorAll('.view-album-btn'); const backToAlbums = document.querySelector('.back-to-albums'); const albumsSection = document.querySelector('.gallery-albums'); const photoGridSection = document.getElementById('photo-grid-section'); const photosGrid = document.getElementById('photos-grid'); const currentAlbumTitle = document.getElementById('current-album-title'); // Sample photo data for different albums const albumPhotos = { 'forum-2024': [ { src: 'assets/gallery-bg.jpg', title: 'Открытие форума 2024', description: 'Торжественное открытие литературного форума', tags: ['встречи', 'открытие', '2024'], type: 'image' }, { src: 'assets/reading-room-bg.jpg', title: 'Лекция о современной поэзии', description: 'Михаил Иванов выступает с лекцией', tags: ['лекции', 'поэзия', 'образование'], type: 'image' }, { src: 'assets/resident-placeholder.jpg', title: 'Участники форума', description: 'Групповое фото участников', tags: ['встречи', 'участники', 'фото'], type: 'image' } ], 'forum-2023': [ { src: 'assets/gallery-bg.jpg', title: 'Форум 2023 - День первый', description: 'Первый день литературного форума 2023', tags: ['встречи', '2023', 'день1'], type: 'image' }, { src: 'assets/competition-bg.jpg', title: 'Награждение победителей', description: 'Церемония награждения конкурса', tags: ['награждение', 'конкурс', 'победители'], type: 'image' } ], 'author-meetings': [ { src: 'assets/resident-placeholder.jpg', title: 'Встреча с Анной Петровой', description: 'Автор представляет новый роман', tags: ['встречи', 'авторы', 'презентация'], type: 'image' } ], 'lectures-workshops': [ { src: 'assets/reading-room-bg.jpg', title: 'Мастер-класс по прозе', description: 'Практическое занятие для молодых авторов', tags: ['мастер-классы', 'проза', 'обучение'], type: 'image' } ], 'children-program': [ { src: 'assets/gallery-bg.jpg', title: 'Детский творческий час', description: 'Дети участвуют в литературном мероприятии', tags: ['детская-программа', 'творчество', 'дети'], type: 'image' } ], 'exhibitions': [ { src: 'assets/gallery-bg.jpg', title: 'Выставка книжных иллюстраций', description: 'Работы художников-иллюстраторов', tags: ['выставки', 'иллюстрации', 'искусство'], type: 'image' } ] }; albumBtns.forEach(btn => { btn.addEventListener('click', function (e) { e.preventDefault(); const albumId = this.getAttribute('data-album-id'); const albumTitle = this.closest('.album-card').querySelector('.album-info h4').textContent; showPhotoGrid(albumId, albumTitle); }); }); if (backToAlbums) { backToAlbums.addEventListener('click', function () { showAlbums(); }); } function showPhotoGrid(albumId, title) { if (albumsSection) albumsSection.style.display = 'none'; if (photoGridSection) photoGridSection.style.display = 'block'; if (currentAlbumTitle) currentAlbumTitle.textContent = title; // Load photos for the album const photos = albumPhotos[albumId] || []; loadPhotos(photos); } function showAlbums() { if (photoGridSection) photoGridSection.style.display = 'none'; if (albumsSection) albumsSection.style.display = 'block'; } function loadPhotos(photos) { if (!photosGrid) return; photosGrid.innerHTML = ''; photos.forEach((photo, index) => { const photoItem = document.createElement('div'); photoItem.className = 'photo-item'; photoItem.innerHTML = ` <img src="${photo.src}" alt="${photo.title}" loading="lazy"> <div class="photo-overlay"> <h4>${photo.title}</h4> <p>${photo.description}</p> </div> `; photoItem.addEventListener('click', function () { if (window.openLightbox) { window.openLightbox(photos, index); } }); photosGrid.appendChild(photoItem); }); // Animate photo appearance setTimeout(() => { const photoItems = photosGrid.querySelectorAll('.photo-item'); photoItems.forEach((item, index) => { setTimeout(() => { item.style.opacity = '1'; item.style.transform = 'translateY(0)'; }, index * 100); }); }, 100); } } // Repository functionality function initRepository() { // Add any repository-specific functionality here console.log('Repository functionality initialized'); } // Search functionality function initSearch() { const searchInputs = document.querySelectorAll('#search-input, #residents-search, #gallery-search, #repository-search'); searchInputs.forEach(input => { input.addEventListener('input', function () { const query = this.value.toLowerCase().trim(); const targetSelector = getSearchTarget(this.id); if (targetSelector) { const items = document.querySelectorAll(targetSelector); items.forEach(item => { const text = item.textContent.toLowerCase(); if (query === '' || text.includes(query)) { item.style.display = ''; item.style.opacity = '1'; item.style.transform = 'translateY(0)'; } else { item.style.opacity = '0'; item.style.transform = 'translateY(20px)'; setTimeout(() => { if (item.style.opacity === '0') { item.style.display = 'none'; } }, 300); } }); } }); }); function getSearchTarget(inputId) { switch (inputId) { case 'search-input': return '.material-card'; case 'residents-search': return '.resident-card'; case 'gallery-search': return '.album-card'; case 'repository-search': return '.archive-card, .document-item, .video-item'; default: return null; } } } // Animation functionality function initAnimations() { // Intersection Observer for scroll 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.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; // Stagger animation for grid items if (entry.target.classList.contains('grid-container')) { const items = entry.target.querySelectorAll('.grid-item'); items.forEach((item, index) => { setTimeout(() => { item.style.opacity = '1'; item.style.transform = 'translateY(0)'; }, index * 100); }); } } }); }, observerOptions); // Observe elements for animation const animatedElements = document.querySelectorAll('.news-card, .resident-card, .infra-card, .event-item, .material-card, .album-card'); animatedElements.forEach(el => { el.style.opacity = '0'; el.style.transform = 'translateY(30px)'; el.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; observer.observe(el); }); // Smooth scrolling for anchor links const anchorLinks = document.querySelectorAll('a[href^="#"]'); anchorLinks.forEach(link => { link.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } // Form functionality function initForms() { const competitionForm = document.querySelector('.competition-form'); if (competitionForm) { competitionForm.addEventListener('submit', function (e) { e.preventDefault(); // Basic form validation const requiredFields = this.querySelectorAll('[required]'); let isValid = true; requiredFields.forEach(field => { if (!field.value.trim()) { field.style.borderColor = '#e74c3c'; isValid = false; } else { field.style.borderColor = '#e9ecef'; } }); if (isValid) { // Simulate form submission const submitBtn = this.querySelector('button[type="submit"]'); const originalText = submitBtn.textContent; submitBtn.textContent = 'Отправка...'; submitBtn.disabled = true; setTimeout(() => { alert('Заявка успешно отправлена! Мы свяжемся с вами в ближайшее время.'); this.reset(); submitBtn.textContent = originalText; submitBtn.disabled = false; }, 2000); } else { alert('Пожалуйста, заполните все обязательные поля.'); } }); } // File input styling const fileInputs = document.querySelectorAll('input[type="file"]'); fileInputs.forEach(input => { input.addEventListener('change', function () { const fileName = this.files[0]?.name || 'Файл не выбран'; const label = this.nextElementSibling || this.parentElement.querySelector('label'); if (label) { label.textContent = fileName; } }); }); } // Countdown functionality for competition function initCountdown() { const countdownElement = document.getElementById('countdown'); if (countdownElement) { // Set target date (January 31, 2025) const targetDate = new Date('2025-01-31T23:59:59').getTime(); function updateCountdown() { const now = new Date().getTime(); const distance = targetDate - now; if (distance > 0) { const days = Math.floor(distance / (1000 * 60 * 60 * 24)); countdownElement.textContent = `${days} дней`; } else { countdownElement.textContent = 'Прием заявок завершен'; } } updateCountdown(); setInterval(updateCountdown, 1000 * 60 * 60); // Update every hour } } // Load more functionality function initLoadMore() { const loadMoreBtns = document.querySelectorAll('.load-more .btn'); loadMoreBtns.forEach(btn => { btn.addEventListener('click', function () { const container = this.closest('section').querySelector('.materials-grid, .residents-grid, .albums-grid'); if (container) { // Simulate loading more content this.textContent = 'Загрузка...'; this.disabled = true; setTimeout(() => { // In a real application, you would load actual content here this.textContent = 'Загрузить еще'; this.disabled = false; // Hide button if no more content // this.style.display = 'none'; }, 1500); } }); }); } // Initialize countdown and load more when DOM is ready document.addEventListener('DOMContentLoaded', function () { initCountdown(); initLoadMore(); }); // Utility functions function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } function throttle(func, limit) { let inThrottle; return function () { const args = arguments; const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // Performance optimization window.addEventListener('load', function () { // Lazy load images const images = document.querySelectorAll('img[loading="lazy"]'); if ('IntersectionObserver' in window) { const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src || img.src; img.classList.remove('lazy'); imageObserver.unobserve(img); } }); }); images.forEach(img => imageObserver.observe(img)); } }); // Error handling window.addEventListener('error', function (e) { console.error('JavaScript error:', e.error); }); // Service worker registration (for future PWA features) if ('serviceWorker' in navigator) { window.addEventListener('load', function () { // navigator.serviceWorker.register('/sw.js') // .then(registration => console.log('SW registered')) // .catch(error => console.log('SW registration failed')); }); }