// Main JavaScript для VPN сервиса document.addEventListener('DOMContentLoaded', function() { // Инициализация tooltips Bootstrap var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); // Инициализация popovers Bootstrap var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); var popoverList = popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl); }); // Плавная прокрутка для якорных ссылок document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // Анимация появления элементов при прокрутке 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)'; } }); }, observerOptions); // Наблюдение за элементами с классом fade-in document.querySelectorAll('.fade-in').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); }); // Обработка форм с валидацией const forms = document.querySelectorAll('.needs-validation'); forms.forEach(form => { form.addEventListener('submit', function(event) { if (!form.checkValidity()) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }); }); // Копирование в буфер обмена document.querySelectorAll('.copy-btn').forEach(button => { button.addEventListener('click', function() { const textToCopy = this.getAttribute('data-copy'); if (textToCopy) { navigator.clipboard.writeText(textToCopy).then(function() { // Показываем уведомление об успешном копировании showNotification('Скопировано в буфер обмена!', 'success'); }).catch(function(err) { console.error('Ошибка копирования: ', err); showNotification('Ошибка копирования', 'error'); }); } }); }); // Функция показа уведомлений function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `alert alert-${type === 'error' ? 'danger' : type} alert-dismissible fade show position-fixed`; notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;'; notification.innerHTML = ` ${message} `; document.body.appendChild(notification); // Автоматически скрываем уведомление через 3 секунды setTimeout(() => { if (notification.parentNode) { notification.remove(); } }, 3000); } // Обработка модальных окон document.querySelectorAll('.modal').forEach(modal => { modal.addEventListener('hidden.bs.modal', function () { // Очищаем форму при закрытии модального окна const form = this.querySelector('form'); if (form) { form.reset(); form.classList.remove('was-validated'); } }); }); // Автоматическое скрытие алертов document.querySelectorAll('.alert').forEach(alert => { if (alert.classList.contains('alert-success') || alert.classList.contains('alert-info')) { setTimeout(() => { const bsAlert = new bootstrap.Alert(alert); bsAlert.close(); }, 5000); } }); // Обработка табов document.querySelectorAll('.nav-tabs .nav-link').forEach(tab => { tab.addEventListener('click', function(e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { // Показываем соответствующий контент document.querySelectorAll('.tab-content .tab-pane').forEach(pane => { pane.classList.remove('show', 'active'); }); target.classList.add('show', 'active'); // Обновляем активную вкладку document.querySelectorAll('.nav-tabs .nav-link').forEach(link => { link.classList.remove('active'); }); this.classList.add('active'); } }); }); // Обработка кнопок "Показать/Скрыть пароль" document.querySelectorAll('.toggle-password').forEach(button => { button.addEventListener('click', function() { const input = this.parentNode.querySelector('input'); const icon = this.querySelector('i'); if (input.type === 'password') { input.type = 'text'; icon.classList.remove('fa-eye'); icon.classList.add('fa-eye-slash'); } else { input.type = 'password'; icon.classList.remove('fa-eye-slash'); icon.classList.add('fa-eye'); } }); }); // Инициализация карусели (если есть) const carousels = document.querySelectorAll('.carousel'); carousels.forEach(carousel => { new bootstrap.Carousel(carousel, { interval: 5000, wrap: true }); }); // Обработка событий для мобильного меню const navbarToggler = document.querySelector('.navbar-toggler'); const navbarCollapse = document.querySelector('.navbar-collapse'); if (navbarToggler && navbarCollapse) { // Закрываем мобильное меню при клике на ссылку navbarCollapse.querySelectorAll('.nav-link').forEach(link => { link.addEventListener('click', () => { if (navbarCollapse.classList.contains('show')) { navbarToggler.click(); } }); }); } console.log('VPN Service JavaScript загружен успешно!'); });