hantalanding/src/js/main.js
2025-08-04 11:38:17 +05:00

1329 lines
47 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ===== LOADING PROGRESS BAR =====
function initLoadingProgress() {
const loadingProgress = document.getElementById('loading-progress');
if (!loadingProgress) return;
// Simple loading with delay
setTimeout(() => {
loadingProgress.classList.add('hidden');
setTimeout(() => {
loadingProgress.style.display = 'none';
initPageAnimations();
}, 500);
}, 1500); // Show loading for 1.5 seconds
}
// ===== SKELETON LOADING =====
function initSkeletonLoading() {
const skeletonElements = document.querySelectorAll('.skeleton');
// Show skeleton while content loads
skeletonElements.forEach(element => {
element.style.display = 'block';
});
// Hide skeleton when content is ready
window.addEventListener('load', () => {
setTimeout(() => {
skeletonElements.forEach(element => {
element.style.display = 'none';
});
}, 1000);
});
}
// ===== ENHANCED PAGE ANIMATIONS =====
function initPageAnimations() {
// Intersection Observer for sections
const sections = document.querySelectorAll('section');
const sectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('in-view');
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
});
sections.forEach(section => {
sectionObserver.observe(section);
});
// Parallax effect for background elements
const parallaxElements = document.querySelectorAll('.parallax-shape');
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
parallaxElements.forEach((element, index) => {
const speed = 0.5 + (index * 0.1);
const yPos = -(scrolled * speed);
element.style.transform = `translateY(${yPos}px) rotate(${scrolled * 0.1}deg)`;
});
ticking = false;
}
function requestParallaxTick() {
if (!ticking) {
requestAnimationFrame(updateParallax);
ticking = true;
}
}
window.addEventListener('scroll', requestParallaxTick, { passive: true });
}
// ===== ENHANCED MOBILE GESTURES =====
function initMobileGestures() {
// Swipe gestures for carousel
let touchStartX = 0;
let touchEndX = 0;
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer) {
carouselContainer.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, { passive: true });
carouselContainer.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
}, { passive: true });
function handleSwipe() {
const swipeThreshold = 50;
const diff = touchStartX - touchEndX;
if (Math.abs(diff) > swipeThreshold) {
if (diff > 0) {
// Swipe left - next
console.log('Swipe left - next card');
// Add your carousel next logic here
} else {
// Swipe right - previous
console.log('Swipe right - previous card');
// Add your carousel previous logic here
}
}
}
}
// Pull-to-refresh functionality
let pullStartY = 0;
let pullDistance = 0;
const pullThreshold = 100;
document.addEventListener('touchstart', (e) => {
if (window.pageYOffset === 0) {
pullStartY = e.touches[0].clientY;
}
}, { passive: true });
document.addEventListener('touchmove', (e) => {
if (window.pageYOffset === 0 && pullStartY > 0) {
pullDistance = e.touches[0].clientY - pullStartY;
if (pullDistance > 0) {
e.preventDefault();
document.body.style.transform = `translateY(${Math.min(pullDistance * 0.5, pullThreshold)}px)`;
}
}
}, { passive: false });
document.addEventListener('touchend', () => {
if (pullDistance > pullThreshold) {
// Trigger refresh
console.log('Pull-to-refresh triggered');
location.reload();
}
// Reset
document.body.style.transform = '';
pullStartY = 0;
pullDistance = 0;
}, { passive: true });
// Enhanced touch feedback
const touchElements = document.querySelectorAll('.btn, .click-button, .accordion-header, .carousel-nav, .mobile-nav-link');
touchElements.forEach(element => {
element.addEventListener('touchstart', function() {
this.style.transform = 'scale(0.95)';
}, { passive: true });
element.addEventListener('touchend', function() {
this.style.transform = 'scale(1)';
}, { passive: true });
});
}
// Initialize all enhancements
document.addEventListener('DOMContentLoaded', () => {
initLoadingProgress();
initSkeletonLoading();
initMobileGestures();
initPurpleGlowSpots();
});
// Optimized Custom Cursor with throttling
const cursor = document.querySelector('.cursor');
if (cursor) {
let mouseMoveThrottled = false;
document.addEventListener('mousemove', (e) => {
if (!mouseMoveThrottled) {
requestAnimationFrame(() => {
cursor.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`;
mouseMoveThrottled = false;
});
mouseMoveThrottled = true;
}
}, { passive: true });
document.addEventListener('mousedown', () => {
cursor.style.transform += ' scale(0.8)';
}, { passive: true });
document.addEventListener('mouseup', () => {
cursor.style.transform = cursor.style.transform.replace(' scale(0.8)', '');
}, { passive: true });
}
// Auto-animate stats section when in viewport
document.addEventListener('DOMContentLoaded', () => {
const statsSection = document.querySelector('.stats-section');
const statCards = document.querySelectorAll('.stat-card');
if (statsSection && statCards.length > 0) {
// Set card indices for staggered animation
statCards.forEach((card, index) => {
card.style.setProperty('--card-index', index);
});
// Create Intersection Observer for stats section
const statsObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Add animation class when section comes into view
entry.target.classList.add('in-view');
// Unobserve after animation is triggered
statsObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.2, // Trigger when 20% of section is visible
rootMargin: '0px 0px -100px 0px'
});
// Start observing the stats section
statsObserver.observe(statsSection);
}
});
// Accordion functionality
document.addEventListener('DOMContentLoaded', () => {
const accordionItems = document.querySelectorAll('.accordion-item');
accordionItems.forEach(item => {
const header = item.querySelector('.accordion-header');
header.addEventListener('click', () => {
const isActive = item.classList.contains('active');
// Close all other accordion items
accordionItems.forEach(otherItem => {
if (otherItem !== item) {
otherItem.classList.remove('active');
}
});
// Toggle current item
if (isActive) {
item.classList.remove('active');
} else {
item.classList.add('active');
}
});
});
});
// Click Button Ripple Effect and Scroll
document.addEventListener('DOMContentLoaded', () => {
const clickButton = document.querySelector('.click-button');
if (clickButton) {
// Функция создания эффекта кругов при клике
function createClickRipple(e) {
// Предотвращаем стандартное поведение ссылки
e.preventDefault();
const rippleContainer = document.createElement('div');
rippleContainer.className = 'click-ripple';
// Создаем 4 больших круга без задержек но разных размеров
for (let i = 0; i < 4; i++) {
const circle = document.createElement('div');
circle.className = 'ripple-circle';
circle.style.animationDelay = '0s'; // Все круги начинаются сразу
circle.style.borderColor = `rgba(255, 255, 255, ${0.9 - i * 0.15})`;
circle.style.borderWidth = `${4 - i}px`;
// Разные финальные размеры для каждого круга
circle.style.setProperty('--final-size', `${200 + i * 50}px`);
rippleContainer.appendChild(circle);
}
clickButton.appendChild(rippleContainer);
// Удаляем эффект через 2 секунды
setTimeout(() => {
if (rippleContainer.parentNode) {
rippleContainer.remove();
}
}, 2000);
// Скролл к форме после завершения анимации
setTimeout(() => {
const contactSection = document.querySelector('#contact');
if (contactSection) {
contactSection.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}, 800); // Скролл начинается через 0.8 секунды
}
// Добавляем обработчик клика
clickButton.addEventListener('click', createClickRipple);
}
});
// Optimized Header scroll effect with throttling
const header = document.querySelector('.header');
if (header) {
let scrollThrottled = false;
window.addEventListener('scroll', () => {
if (!scrollThrottled) {
requestAnimationFrame(() => {
if (window.scrollY > 100) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
scrollThrottled = false;
});
scrollThrottled = true;
}
}, { passive: true });
}
// Intersection Observer for Animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -30px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-slide-up');
// Handle elements with delay
const delay = entry.target.getAttribute('data-delay');
if (delay) {
entry.target.style.animationDelay = `${delay}ms`;
}
// Animate numbers if it's a stat number or trust number
if (entry.target.classList.contains('stat-number') || entry.target.classList.contains('trust-number')) {
animateNumber(entry.target);
}
// Unobserve element after animation to save performance
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe elements - убираем .stat-number из наблюдателя для новых карточек
document.querySelectorAll('.animate-slide-up, .method-card, .exam-card, .success-card, .trust-number').forEach(el => {
observer.observe(el);
});
// Number Animation
function animateNumber(element) {
const target = parseInt(element.getAttribute('data-target'));
// Если нет data-target атрибута, не анимируем
if (!target || isNaN(target)) {
return;
}
const duration = 2000; // 2 seconds
const step = target / (duration / 16); // 60fps
let current = 0;
const updateNumber = () => {
current += step;
if (current < target) {
element.textContent = Math.round(current);
requestAnimationFrame(updateNumber);
} else {
element.textContent = target;
}
};
updateNumber();
}
// Mobile Navigation
const navToggle = document.getElementById('navToggle');
const navLinks = document.querySelector('.nav-links');
if (navToggle && navLinks) {
navToggle.addEventListener('click', () => {
navLinks.classList.toggle('active');
});
}
// Close mobile menu when clicking outside
document.addEventListener('click', (e) => {
if (navLinks && !e.target.closest('.nav-container')) {
navLinks.classList.remove('active');
}
});
// Smooth Scrolling (except click-button)
document.querySelectorAll('a[href^="#"]:not(.click-button)').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
if (navLinks) {
navLinks.classList.remove('active');
}
const href = this.getAttribute('href');
if (href && href !== '#') {
const target = document.querySelector(href);
if (target) {
const headerOffset = 80;
const elementPosition = target.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}
}
});
});
// Form Animations
const formInputs = document.querySelectorAll('.animate-input');
formInputs.forEach(input => {
input.addEventListener('focus', () => {
input.parentElement.classList.add('focused');
});
input.addEventListener('blur', () => {
if (!input.value) {
input.parentElement.classList.remove('focused');
}
});
});
// Phone number formatting
const phoneInput = document.querySelector('input[type="tel"]');
if (phoneInput) {
phoneInput.addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
if (value.length > 0) {
if (value.length <= 1) {
value = '+7 (' + value;
} else if (value.length <= 4) {
value = '+7 (' + value.substring(1);
} else if (value.length <= 7) {
value = '+7 (' + value.substring(1, 4) + ') ' + value.substring(4);
} else if (value.length <= 9) {
value = '+7 (' + value.substring(1, 4) + ') ' + value.substring(4, 7) + '-' + value.substring(7);
} else {
value = '+7 (' + value.substring(1, 4) + ') ' + value.substring(4, 7) + '-' + value.substring(7, 9) + '-' + value.substring(9, 11);
}
}
e.target.value = value;
});
}
// Contact Form Submission
const contactForm = document.querySelector('#contactForm');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
const button = this.querySelector('.submit-btn');
const originalContent = button.innerHTML;
// Get form data
const firstName = this.querySelector('#firstName').value;
const lastName = this.querySelector('#lastName').value;
const phone = this.querySelector('#phone').value;
// Add loading state
if (button) {
button.disabled = true;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> <span>Sending...</span>';
}
// Simulate form submission (replace with actual API call)
setTimeout(() => {
if (button) {
button.innerHTML = '<i class="fas fa-check"></i> <span>Message Sent!</span>';
button.style.background = 'linear-gradient(135deg, #10b981, #059669)';
// Reset form after delay
setTimeout(() => {
this.reset();
if (button) {
button.disabled = false;
button.innerHTML = originalContent;
button.style.background = 'linear-gradient(135deg, var(--primary-color), #4f46e5)';
}
}, 3000);
}
}, 2000);
});
}
// Active Navigation Link on Scroll
const sections = document.querySelectorAll('section');
const navItems = document.querySelectorAll('.nav-links a');
function setActiveNavItem() {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (window.pageYOffset >= sectionTop - 200) {
current = section.getAttribute('id');
}
});
navItems.forEach(item => {
item.classList.remove('active');
if (item.getAttribute('href') === `#${current}`) {
item.classList.add('active');
}
});
}
window.addEventListener('scroll', setActiveNavItem);
window.addEventListener('load', setActiveNavItem);
// Hover Animations for Cards
document.querySelectorAll('.method-card, .exam-card, .success-card').forEach(card => {
card.addEventListener('mouseenter', () => {
card.style.transform = 'translateY(-10px)';
card.style.boxShadow = 'var(--shadow-lg)';
});
card.addEventListener('mouseleave', () => {
card.style.transform = 'translateY(0)';
card.style.boxShadow = 'var(--shadow)';
});
});
// Add animation classes
document.addEventListener('DOMContentLoaded', () => {
// Animate title on load
const mainTitle = document.querySelector('.main-title');
if (mainTitle) {
mainTitle.classList.add('animate-in');
}
// Animate university logos
const logos = document.querySelectorAll('.university-logos img');
logos.forEach((logo, index) => {
setTimeout(() => {
logo.style.opacity = '1';
}, index * 200);
});
});
// Language switcher functionality is now handled by i18n.js
// Parallax Effect for Hero Section
const heroContent = document.querySelector('.hero-content');
const shapes = document.querySelectorAll('.shape');
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
if (heroContent) {
heroContent.style.transform = `translateY(${scrolled * 0.3}px)`;
}
shapes.forEach(shape => {
shape.style.transform = `translateY(${scrolled * 0.4}px)`;
});
});
// Service Card Hover Effect
document.querySelectorAll('.service-card').forEach(card => {
card.addEventListener('mouseenter', (e) => {
const icon = card.querySelector('.card-icon i');
if (icon) {
icon.style.transform = 'scale(1.2) rotate(10deg)';
}
});
card.addEventListener('mouseleave', (e) => {
const icon = card.querySelector('.card-icon i');
if (icon) {
icon.style.transform = 'scale(1) rotate(0deg)';
}
});
});
// Carousel functionality moved to inline script in HTML
// Exam links functionality - открытие аккордеонов
const examLinks = document.querySelectorAll('.exam-link');
examLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href').substring(1);
const targetAccordion = document.getElementById(targetId);
if (targetAccordion) {
// Скролл к секции
targetAccordion.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
// Закрыть все аккордеоны
const allAccordions = document.querySelectorAll('.accordion-item');
allAccordions.forEach(accordion => {
accordion.classList.remove('active');
});
// Открыть целевой аккордеон
setTimeout(() => {
targetAccordion.classList.add('active');
}, 500);
}
});
});
// Logo click functionality - скролл к началу страницы
const logo = document.querySelector('.logo');
if (logo) {
logo.addEventListener('click', function(e) {
e.preventDefault();
// Плавный скролл к началу страницы
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
// Mobile Navigation Functionality
let mobileMenuBtn, mobileNav, mobileOverlay, mobileCloseBtn, mobileNavLinks, mobileNavLogo;
function openMobileMenu() {
console.log('Opening mobile menu...');
if (mobileMenuBtn) {
mobileMenuBtn.classList.add('active');
console.log('Menu button activated');
}
if (mobileNav) {
mobileNav.classList.add('active');
// FORCE FIX CSS WHEN OPENING
mobileNav.style.setProperty('backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('background', 'linear-gradient(135deg, rgba(55, 48, 163, 0.98) 0%, rgba(79, 70, 229, 0.98) 100%)', 'important');
mobileNav.style.setProperty('z-index', '10001', 'important');
mobileNav.style.setProperty('pointer-events', 'auto', 'important');
// FORCE FIX ALL ELEMENTS INSIDE MENU
const allMenuElements = mobileNav.querySelectorAll('*');
allMenuElements.forEach(element => {
element.style.setProperty('pointer-events', 'auto', 'important');
element.style.setProperty('z-index', '10002', 'important');
});
// SPECIFIC FIXES FOR CRITICAL ELEMENTS
const navLinks = mobileNav.querySelectorAll('.mobile-nav-link');
navLinks.forEach(link => {
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10003', 'important');
link.style.setProperty('position', 'relative', 'important');
link.style.setProperty('cursor', 'pointer', 'important');
});
const closeBtn = mobileNav.querySelector('.mobile-close-btn');
if (closeBtn) {
closeBtn.style.setProperty('pointer-events', 'auto', 'important');
closeBtn.style.setProperty('z-index', '10003', 'important');
closeBtn.style.setProperty('cursor', 'pointer', 'important');
}
const langLinks = mobileNav.querySelectorAll('.mobile-lang-switch a');
langLinks.forEach(link => {
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10003', 'important');
link.style.setProperty('cursor', 'pointer', 'important');
});
// FORCE RE-ACTIVATE ALL EVENT LISTENERS AFTER MENU OPENS
setTimeout(() => {
console.log('Re-activating event listeners for menu elements...');
// Simple approach: just force all elements to be clickable
const allClickableElements = mobileNav.querySelectorAll('a, button');
allClickableElements.forEach(element => {
element.style.setProperty('pointer-events', 'auto', 'important');
element.style.setProperty('z-index', '10003', 'important');
element.style.setProperty('cursor', 'pointer', 'important');
element.style.setProperty('position', 'relative', 'important');
// Add click handler if not already present
if (!element.hasAttribute('data-click-handler-added')) {
element.setAttribute('data-click-handler-added', 'true');
element.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('🎯 ELEMENT CLICKED:', this.textContent || this.className);
// Handle navigation links
if (this.classList.contains('mobile-nav-link')) {
const targetId = this.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
closeMobileMenu();
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
}
// Handle language switcher
if (this.closest('.mobile-lang-switch')) {
const lang = this.textContent.toLowerCase();
console.log('Switching language to:', lang);
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
document.documentElement.lang = lang;
}
closeMobileMenu();
}
// Handle close button
if (this.classList.contains('mobile-close-btn')) {
closeMobileMenu();
}
});
element.addEventListener('touchstart', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('🎯 ELEMENT TOUCHED:', this.textContent || this.className);
// Same logic as click
if (this.classList.contains('mobile-nav-link')) {
const targetId = this.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
closeMobileMenu();
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
}
if (this.closest('.mobile-lang-switch')) {
const lang = this.textContent.toLowerCase();
console.log('Switching language to:', lang);
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
document.documentElement.lang = lang;
}
closeMobileMenu();
}
if (this.classList.contains('mobile-close-btn')) {
closeMobileMenu();
}
}, { passive: false });
}
});
console.log('✅ Event listeners re-activated for', allClickableElements.length, 'elements');
}, 100);
console.log('Mobile nav activated with forced CSS fixes');
}
if (mobileOverlay) {
mobileOverlay.classList.add('active');
mobileOverlay.style.setProperty('z-index', '10000', 'important');
mobileOverlay.style.setProperty('pointer-events', 'auto', 'important');
console.log('Overlay activated');
}
document.body.style.overflow = 'hidden';
console.log('Mobile menu opened successfully');
}
function closeMobileMenu() {
console.log('Closing mobile menu...');
if (mobileMenuBtn) {
mobileMenuBtn.classList.remove('active');
console.log('Menu button deactivated');
}
if (mobileNav) {
mobileNav.classList.remove('active');
console.log('Mobile nav deactivated');
}
if (mobileOverlay) {
mobileOverlay.classList.remove('active');
mobileOverlay.style.setProperty('pointer-events', 'none', 'important');
console.log('Overlay deactivated');
}
document.body.style.overflow = '';
console.log('Mobile menu closed successfully');
}
// Initialize mobile menu functionality
function initMobileMenu() {
mobileMenuBtn = document.querySelector('.mobile-menu-btn');
mobileNav = document.querySelector('.mobile-nav');
mobileOverlay = document.querySelector('.mobile-overlay');
mobileCloseBtn = document.querySelector('.mobile-close-btn');
mobileNavLinks = document.querySelectorAll('.mobile-nav-link');
mobileNavLogo = document.querySelector('.mobile-logo');
console.log('Mobile menu elements found:', {
btn: !!mobileMenuBtn,
nav: !!mobileNav,
overlay: !!mobileOverlay,
closeBtn: !!mobileCloseBtn,
links: mobileNavLinks.length
});
// FORCE FIX CSS STYLES
if (mobileNav) {
// Force remove backdrop-filter and fix styles
mobileNav.style.setProperty('backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('background', 'linear-gradient(135deg, rgba(55, 48, 163, 0.98) 0%, rgba(79, 70, 229, 0.98) 100%)', 'important');
mobileNav.style.setProperty('z-index', '10001', 'important');
mobileNav.style.setProperty('pointer-events', 'auto', 'important');
console.log('✅ Forced CSS fixes applied to mobile-nav');
}
if (mobileOverlay) {
mobileOverlay.style.setProperty('z-index', '10000', 'important');
mobileOverlay.style.setProperty('pointer-events', 'none', 'important');
console.log('✅ Forced CSS fixes applied to mobile-overlay');
}
// Event listeners for mobile menu button - multiple event types for better compatibility
if (mobileMenuBtn) {
// Click event
mobileMenuBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile menu button clicked');
openMobileMenu();
});
// Touch events for better mobile compatibility
mobileMenuBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile menu button touched');
openMobileMenu();
}, { passive: false });
// Mouse events as fallback
mobileMenuBtn.addEventListener('mousedown', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile menu button mousedown');
openMobileMenu();
});
}
if (mobileCloseBtn) {
mobileCloseBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile close button clicked');
closeMobileMenu();
});
mobileCloseBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile close button touched');
closeMobileMenu();
}, { passive: false });
}
if (mobileOverlay) {
mobileOverlay.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile overlay clicked');
closeMobileMenu();
});
mobileOverlay.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile overlay touched');
closeMobileMenu();
}, { passive: false });
}
// Close mobile menu when clicking on nav links
mobileNavLinks.forEach(link => {
// FORCE FIX CSS FOR LINKS
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10002', 'important');
link.style.setProperty('position', 'relative', 'important');
link.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile nav link clicked:', link.getAttribute('href'));
closeMobileMenu();
// Smooth scroll to section
const targetId = link.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
});
// Touch events for links
link.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile nav link touched:', link.getAttribute('href'));
closeMobileMenu();
const targetId = link.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
}, { passive: false });
});
// Mobile logo click
if (mobileNavLogo) {
// FORCE FIX CSS FOR LOGO
mobileNavLogo.style.setProperty('pointer-events', 'auto', 'important');
mobileNavLogo.style.setProperty('z-index', '10002', 'important');
mobileNavLogo.style.setProperty('position', 'relative', 'important');
mobileNavLogo.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Mobile logo clicked');
closeMobileMenu();
setTimeout(() => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}, 300);
});
mobileNavLogo.addEventListener('touchstart', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Mobile logo touched');
closeMobileMenu();
setTimeout(() => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}, 300);
}, { passive: false });
}
// FIX LANGUAGE SWITCHER
const mobileLangSwitch = document.querySelector('.mobile-lang-switch');
if (mobileLangSwitch) {
console.log('Mobile language switcher found');
// FORCE FIX CSS FOR LANGUAGE SWITCHER
mobileLangSwitch.style.setProperty('pointer-events', 'auto', 'important');
mobileLangSwitch.style.setProperty('z-index', '10002', 'important');
mobileLangSwitch.style.setProperty('position', 'relative', 'important');
const langLinks = mobileLangSwitch.querySelectorAll('a');
langLinks.forEach(link => {
// FORCE FIX CSS FOR EACH LANGUAGE LINK
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10003', 'important');
link.style.setProperty('position', 'relative', 'important');
link.style.setProperty('cursor', 'pointer', 'important');
link.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Language link clicked:', this.textContent);
// Remove active class from all links
langLinks.forEach(l => l.classList.remove('active'));
// Add active class to clicked link
this.classList.add('active');
// Switch language
const lang = this.textContent.toLowerCase();
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
console.log('i18n not available, manual language switch');
// Manual language switch fallback
document.documentElement.lang = lang;
}
closeMobileMenu();
});
link.addEventListener('touchstart', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Language link touched:', this.textContent);
// Remove active class from all links
langLinks.forEach(l => l.classList.remove('active'));
// Add active class to clicked link
this.classList.add('active');
// Switch language
const lang = this.textContent.toLowerCase();
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
console.log('i18n not available, manual language switch');
// Manual language switch fallback
document.documentElement.lang = lang;
}
closeMobileMenu();
}, { passive: false });
});
}
}
// Close mobile menu on escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeMobileMenu();
}
});
// Close mobile menu on window resize
window.addEventListener('resize', function() {
if (window.innerWidth > 992) {
closeMobileMenu();
}
});
// Enhanced mobile functionality
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM Content Loaded - Initializing mobile functionality...');
// Initialize mobile menu
initMobileMenu();
// Additional check for mobile menu elements
setTimeout(() => {
const btn = document.querySelector('.mobile-menu-btn');
const nav = document.querySelector('.mobile-nav');
const overlay = document.querySelector('.mobile-overlay');
console.log('Mobile menu elements check after 100ms:', {
button: btn,
nav: nav,
overlay: overlay,
buttonVisible: btn ? window.getComputedStyle(btn).display !== 'none' : false,
navVisible: nav ? window.getComputedStyle(nav).display !== 'none' : false
});
// Test click simulation
if (btn) {
console.log('Mobile menu button found, testing click simulation...');
// Simulate a click to test if it works
setTimeout(() => {
console.log('Simulating click on mobile menu button...');
btn.click();
setTimeout(() => {
console.log('Menu state after simulated click:', {
buttonActive: btn.classList.contains('active'),
navActive: nav ? nav.classList.contains('active') : false,
overlayActive: overlay ? overlay.classList.contains('active') : false
});
// Close menu after test
closeMobileMenu();
}, 100);
}, 200);
}
}, 100);
// Touch gesture support for mobile
let touchStartY = 0;
let touchEndY = 0;
document.addEventListener('touchstart', (e) => {
touchStartY = e.changedTouches[0].screenY;
}, { passive: true });
document.addEventListener('touchend', (e) => {
touchEndY = e.changedTouches[0].screenY;
handleSwipe();
}, { passive: true });
function handleSwipe() {
const swipeThreshold = 50;
const diff = touchStartY - touchEndY;
// Swipe up to close mobile menu
if (diff > swipeThreshold && mobileNav && mobileNav.classList.contains('active')) {
closeMobileMenu();
}
}
// Improved mobile scrolling performance
let ticking = false;
function updateOnScroll() {
// Add scroll-based animations for mobile
const scrolled = window.pageYOffset;
const parallax = document.querySelectorAll('.floating-shapes .shape');
parallax.forEach((shape, index) => {
const speed = 0.5 + (index * 0.1);
const yPos = -(scrolled * speed);
shape.style.transform = `translateY(${yPos}px)`;
});
ticking = false;
}
function requestTick() {
if (!ticking) {
requestAnimationFrame(updateOnScroll);
ticking = true;
}
}
window.addEventListener('scroll', requestTick, { passive: true });
// Mobile-specific optimizations
if (window.innerWidth <= 768) {
// Reduce animation complexity on mobile
document.body.classList.add('mobile-device');
// Optimize images for mobile
const images = document.querySelectorAll('img');
images.forEach(img => {
if (img.dataset.mobileSrc) {
img.src = img.dataset.mobileSrc;
}
});
// Add mobile-specific event listeners
const touchElements = document.querySelectorAll('.btn, .click-button, .accordion-header');
touchElements.forEach(element => {
element.addEventListener('touchstart', function() {
this.style.transform = 'scale(0.95)';
}, { passive: true });
element.addEventListener('touchend', function() {
this.style.transform = 'scale(1)';
}, { passive: true });
});
}
// Lazy loading for mobile
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) {
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
}
});
});
const lazyImages = document.querySelectorAll('img[data-src]');
lazyImages.forEach(img => imageObserver.observe(img));
}
// Mobile form improvements
const formInputs = document.querySelectorAll('input, textarea');
formInputs.forEach(input => {
// Prevent zoom on focus for iOS
input.addEventListener('focus', function() {
if (window.innerWidth <= 768) {
this.style.fontSize = '16px';
}
});
input.addEventListener('blur', function() {
if (window.innerWidth <= 768) {
this.style.fontSize = '';
}
});
});
// Mobile carousel improvements
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer && window.innerWidth <= 768) {
let startX = 0;
let currentX = 0;
let isDragging = false;
carouselContainer.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
isDragging = true;
}, { passive: true });
carouselContainer.addEventListener('touchmove', (e) => {
if (!isDragging) return;
currentX = e.touches[0].clientX;
const diff = startX - currentX;
if (Math.abs(diff) > 50) {
if (diff > 0) {
// Swipe left - next
document.querySelector('.carousel-next')?.click();
} else {
// Swipe right - previous
document.querySelector('.carousel-prev')?.click();
}
isDragging = false;
}
}, { passive: true });
carouselContainer.addEventListener('touchend', () => {
isDragging = false;
}, { passive: true });
}
});
// ===== PURPLE GLOW SPOTS ANIMATION =====
function initPurpleGlowSpots() {
const whiteSections = document.querySelectorAll('.white-section');
whiteSections.forEach(section => {
// Create additional random spots
for (let i = 0; i < 3; i++) {
const spot = document.createElement('div');
spot.className = 'glow-spot';
// Random position and size
const size = Math.random() * 150 + 100;
const x = Math.random() * 80 + 10;
const y = Math.random() * 80 + 10;
const delay = Math.random() * 10;
const duration = Math.random() * 10 + 15;
spot.style.cssText = `
width: ${size}px;
height: ${size}px;
left: ${x}%;
top: ${y}%;
animation-delay: -${delay}s;
animation-duration: ${duration}s;
`;
const spotsContainer = section.querySelector('.purple-glow-spots');
if (spotsContainer) {
spotsContainer.appendChild(spot);
}
}
});
// Add subtle mouse interaction
document.addEventListener('mousemove', (e) => {
const spots = document.querySelectorAll('.glow-spot');
const mouseX = e.clientX / window.innerWidth;
const mouseY = e.clientY / window.innerHeight;
spots.forEach((spot, index) => {
const speed = (index + 1) * 0.5;
const x = (mouseX - 0.5) * speed * 20;
const y = (mouseY - 0.5) * speed * 20;
spot.style.transform = `translate(${x}px, ${y}px)`;
});
}, { passive: true });
}