// QuickQ Website JavaScript // Performance optimized with lazy loading and SEO enhancements // Wait for DOM to be fully loaded document.addEventListener('DOMContentLoaded', function() { console.log('QuickQ website loaded - SEO optimized for Bing'); // Mobile menu toggle const mobileMenuToggle = document.querySelector('.mobile-menu-toggle'); const navMenu = document.querySelector('.nav-menu'); if (mobileMenuToggle) { mobileMenuToggle.addEventListener('click', function() { navMenu.style.display = navMenu.style.display === 'flex' ? 'none' : 'flex'; if (navMenu.style.display === 'flex') { navMenu.style.flexDirection = 'column'; navMenu.style.position = 'absolute'; navMenu.style.top = '100%'; navMenu.style.left = '0'; navMenu.style.right = '0'; navMenu.style.backgroundColor = 'white'; navMenu.style.padding = '2rem'; navMenu.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.1)'; navMenu.style.gap = '1rem'; // Add animation navMenu.style.animation = 'slideDown 0.3s ease forwards'; } }); } // Smooth scroll for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); if (targetId === '#') return; const targetElement = document.querySelector(targetId); if (targetElement) { window.scrollTo({ top: targetElement.offsetTop - 100, behavior: 'smooth' }); // Update URL without page reload history.pushState(null, null, targetId); } }); }); // Lazy load images 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.classList.add('loaded'); observer.unobserve(img); } }); }); document.querySelectorAll('img[data-src]').forEach(img => { imageObserver.observe(img); }); } // Download card animations const downloadCards = document.querySelectorAll('.download-card'); downloadCards.forEach(card => { card.addEventListener('mouseenter', function() { this.style.transform = 'translateY(-5px) scale(1.02)'; }); card.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0) scale(1)'; }); }); // Feature card animations const featureCards = document.querySelectorAll('.feature-card'); featureCards.forEach(card => { card.addEventListener('mouseenter', function() { const icon = this.querySelector('.feature-icon'); if (icon) { icon.style.transform = 'rotate(5deg) scale(1.1)'; } }); card.addEventListener('mouseleave', function() { const icon = this.querySelector('.feature-icon'); if (icon) { icon.style.transform = 'rotate(0) scale(1)'; } }); }); // Performance monitoring window.addEventListener('load', function() { // Send performance data to analytics if ('performance' in window) { const perfData = window.performance.timing; const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart; const domReadyTime = perfData.domComplete - perfData.domLoading; console.log('Page load time:', pageLoadTime, 'ms'); console.log('DOM ready time:', domReadyTime, 'ms'); // Log performance for SEO optimization if (pageLoadTime < 2000) { console.log('✅ Page load time is good for SEO'); } else { console.log('⚠️ Page load time could be improved'); } } }); // Form handling (for contact page) const contactForm = document.getElementById('contactForm'); if (contactForm) { contactForm.addEventListener('submit', function(e) { e.preventDefault(); // Simple validation const name = this.querySelector('input[name="name"]'); const email = this.querySelector('input[name="email"]'); const message = this.querySelector('textarea[name="message"]'); let isValid = true; [name, email, message].forEach(field => { if (!field.value.trim()) { field.style.borderColor = '#ff6b6b'; isValid = false; } else { field.style.borderColor = ''; } }); if (isValid) { // Show success message const successMessage = document.createElement('div'); successMessage.className = 'form-success'; successMessage.innerHTML = ` Thank you! Your message has been sent successfully. `; successMessage.style.cssText = ` background: #4CAF50; color: white; padding: 1rem; border-radius: 4px; margin-top: 1rem; display: flex; align-items: center; gap: 0.5rem; `; contactForm.appendChild(successMessage); // Reset form contactForm.reset(); // Remove message after 5 seconds setTimeout(() => { successMessage.remove(); }, 5000); } }); } // FAQ accordion functionality const faqItems = document.querySelectorAll('.faq-item'); faqItems.forEach(item => { const question = item.querySelector('h3'); const answer = item.querySelector('p'); if (question && answer) { // Create toggle button const toggleBtn = document.createElement('button'); toggleBtn.className = 'faq-toggle'; toggleBtn.innerHTML = ''; toggleBtn.setAttribute('aria-label', 'Toggle answer'); toggleBtn.style.cssText = ` background: none; border: none; cursor: pointer; font-size: 1rem; color: #666; position: absolute; right: 1rem; top: 1rem; `; question.style.position = 'relative'; question.style.paddingRight = '2rem'; question.appendChild(toggleBtn); // Initially hide answer answer.style.display = 'none'; answer.style.opacity = '0'; answer.style.maxHeight = '0'; answer.style.overflow = 'hidden'; answer.style.transition = 'all 0.3s ease'; toggleBtn.addEventListener('click', function() { const isExpanded = answer.style.maxHeight !== '0px'; if (isExpanded) { answer.style.maxHeight = '0'; answer.style.opacity = '0'; answer.style.paddingTop = '0'; this.innerHTML = ''; } else { answer.style.maxHeight = answer.scrollHeight + 'px'; answer.style.opacity = '1'; answer.style.paddingTop = '1rem'; this.innerHTML = ''; } }); // Also allow clicking the whole question question.style.cursor = 'pointer'; question.addEventListener('click', () => toggleBtn.click()); } }); // Real-time download stats animation function animateStats() { const statNumbers = document.querySelectorAll('.stat-number'); statNumbers.forEach(stat => { const target = parseInt(stat.textContent); if (isNaN(target)) return; let current = 0; const increment = target / 50; // 50 frames const interval = 20; // 20ms per frame const timer = setInterval(() => { current += increment; if (current >= target) { current = target; clearInterval(timer); } stat.textContent = Math.round(current) + (stat.textContent.includes('%') ? '%' : '+'); }, interval); }); } // Start animation when stats are in viewport if ('IntersectionObserver' in window) { const statsObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { animateStats(); statsObserver.unobserve(entry.target); } }); }, { threshold: 0.5 }); const statsSection = document.querySelector('.hero-stats'); if (statsSection) { statsObserver.observe(statsSection); } } // Add CSS animation for mobile menu const style = document.createElement('style'); style.textContent = ` @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } /* Print styles */ @media print { .mobile-menu-toggle, .btn-download, .btn-primary, .btn-secondary { display: none !important; } } /* Reduced motion */ @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } `; document.head.appendChild(style); // Track download button clicks for analytics document.querySelectorAll('.btn-download, .download-card').forEach(button => { button.addEventListener('click', function(e) { const platform = this.textContent.includes('Windows') ? 'windows' : this.textContent.includes('Mac') ? 'mac' : this.textContent.includes('Android') ? 'android' : 'ios'; // In production, send to analytics console.log(`Download clicked for ${platform} platform`); // You can send this to your analytics service // gtag('event', 'download_click', { 'platform': platform }); }); }); }); // Add service worker for PWA features (optional) if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js').then(registration => { console.log('ServiceWorker registered: ', registration.scope); }).catch(error => { console.log('ServiceWorker registration failed: ', error); }); }); }