/** * Main JavaScript file for argobox.com * Handles animations, interactions, and dynamic content */ document.addEventListener('DOMContentLoaded', function() { // Initialize all website functionality initNavigation(); initParticlesAndIcons(); initTerminalTyping(); updateYear(); }); /** * Set up navigation functionality - mobile menu and scroll spy */ function initNavigation() { const menuToggle = document.querySelector('.menu-toggle'); const navMenu = document.querySelector('.nav-menu'); const navLinks = document.querySelectorAll('.nav-link'); if (menuToggle && navMenu) { // Toggle mobile menu menuToggle.addEventListener('click', () => { toggleMobileMenu(); }); // Close mobile menu when clicking outside document.addEventListener('click', (e) => { if (navMenu.classList.contains('show') && !navMenu.contains(e.target) && !menuToggle.contains(e.target)) { toggleMobileMenu(); } }); // Close mobile menu when link is clicked navLinks.forEach(link => { link.addEventListener('click', () => { if (window.innerWidth <= 768 && navMenu.classList.contains('show')) { toggleMobileMenu(); } }); }); // Handle resize events window.addEventListener('resize', () => { if (window.innerWidth > 768 && navMenu.classList.contains('show')) { navMenu.classList.remove('show'); updateMenuIcon(false); } }); } // Toggle function for mobile menu function toggleMobileMenu() { navMenu.classList.toggle('show'); updateMenuIcon(navMenu.classList.contains('show')); // Prevent body scrolling when menu is open if (navMenu.classList.contains('show')) { document.body.style.overflow = 'hidden'; } else { document.body.style.overflow = ''; } } // Update menu icon based on menu state function updateMenuIcon(isOpen) { const icon = menuToggle.querySelector('i'); if (isOpen) { icon.classList.remove('fa-bars'); icon.classList.add('fa-times'); } else { icon.classList.remove('fa-times'); icon.classList.add('fa-bars'); } } // Scroll spy for navigation window.addEventListener('scroll', () => { const sections = document.querySelectorAll('section'); let current = ''; sections.forEach(section => { const sectionTop = section.offsetTop; if (window.scrollY >= sectionTop - 100) { current = section.getAttribute('id'); } }); navLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('href').substring(1) === current) { link.classList.add('active'); } }); }); } /** * Create background particles and floating tech icons */ function initParticlesAndIcons() { createBackgroundParticles(); createFloatingIcons(); } /** * Optimize images for better mobile performance */ function optimizeImagesForMobile() { if (window.innerWidth <= 768) { // Reduce particles count on mobile for better performance createBackgroundParticles(15); // Fewer particles } else { createBackgroundParticles(50); // Normal number of particles } } /** * Create animated background particles */ function createBackgroundParticles(count = 50) { const particlesContainer = document.getElementById('particles-container'); if (!particlesContainer) return; // Clear existing particles particlesContainer.innerHTML = ''; // Create particles for (let i = 0; i < count; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); // Random size between 2 and 6px const size = Math.random() * 4 + 2; particle.style.width = `${size}px`; particle.style.height = `${size}px`; // Random position particle.style.left = `${Math.random() * 100}%`; particle.style.top = `${Math.random() * 100}%`; // Random opacity between 0.1 and 0.3 particle.style.opacity = (Math.random() * 0.2 + 0.1).toString(); // Animation properties particle.style.animation = `float-particle ${Math.random() * 20 + 10}s linear infinite`; particle.style.animationDelay = `${Math.random() * 10}s`; particlesContainer.appendChild(particle); } } /** * Initialize terminal typing animation */ function initTerminalTyping() { const cursor = document.querySelector('.cursor'); if (cursor) { setInterval(() => { cursor.style.opacity = cursor.style.opacity === '0' ? '1' : '0'; }, 600); } } /** * Update copyright year in the footer */ function updateYear() { const yearElement = document.getElementById('current-year'); if (yearElement) { yearElement.textContent = new Date().getFullYear(); } } /** * Create and initialize floating icons in the hero section */ function createFloatingIcons() { // Implemented if needed for mobile } // Initialize responsive behaviors window.addEventListener('resize', () => { optimizeImagesForMobile(); }); // Call once on page load optimizeImagesForMobile(); // Contact Form Handler const contactForm = document.getElementById('contact-form'); if (contactForm) { contactForm.addEventListener('submit', async (e) => { e.preventDefault(); const submitButton = contactForm.querySelector('button[type="submit"]'); const originalButtonText = submitButton.innerHTML; try { submitButton.disabled = true; submitButton.innerHTML = ' Sending...'; const formData = new FormData(contactForm); const data = { name: formData.get('name'), email: formData.get('email'), subject: formData.get('subject'), message: formData.get('message') }; const response = await fetch('/contact', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); const result = await response.json(); if (response.ok) { // Show success message const successMessage = document.createElement('div'); successMessage.className = 'alert alert-success'; successMessage.innerHTML = ' Message sent successfully! We\'ll get back to you soon.'; contactForm.insertBefore(successMessage, submitButton); contactForm.reset(); // Remove success message after 5 seconds setTimeout(() => { successMessage.remove(); }, 5000); } else { throw new Error(result.error || 'Failed to send message'); } } catch (error) { console.error('Error sending email:', error); // Show error message const errorMessage = document.createElement('div'); errorMessage.className = 'alert alert-error'; errorMessage.innerHTML = ' Failed to send message. Please try again later.'; contactForm.insertBefore(errorMessage, submitButton); // Remove error message after 5 seconds setTimeout(() => { errorMessage.remove(); }, 5000); } finally { submitButton.disabled = false; submitButton.innerHTML = originalButtonText; } }); }