188 lines
6.0 KiB
JavaScript
188 lines
6.0 KiB
JavaScript
/**
|
|
* 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');
|
|
|
|
if (menuToggle && navMenu) {
|
|
menuToggle.addEventListener('click', () => {
|
|
navMenu.classList.toggle('show');
|
|
const icon = menuToggle.querySelector('i');
|
|
if (navMenu.classList.contains('show')) {
|
|
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');
|
|
const navLinks = document.querySelectorAll('.nav-link');
|
|
|
|
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();
|
|
}
|
|
|
|
/**
|
|
* Create animated background particles
|
|
*/
|
|
function createBackgroundParticles() {
|
|
const particlesContainer = document.getElementById('particles-container');
|
|
|
|
if (!particlesContainer) return;
|
|
|
|
// Clear existing particles
|
|
particlesContainer.innerHTML = '';
|
|
|
|
// Create particles
|
|
for (let i = 0; i < 50; 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();
|
|
}
|
|
}
|
|
|
|
// 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 = '<i class="fas fa-spinner fa-spin"></i> 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('/functions/contact', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json();
|
|
throw new Error(errorData.error || 'Failed to send email');
|
|
}
|
|
|
|
// Show success message
|
|
const successMessage = document.createElement('div');
|
|
successMessage.className = 'alert alert-success';
|
|
successMessage.innerHTML = '<i class="fas fa-check-circle"></i> 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);
|
|
|
|
} catch (error) {
|
|
console.error('Error sending email:', error);
|
|
|
|
// Show error message
|
|
const errorMessage = document.createElement('div');
|
|
errorMessage.className = 'alert alert-error';
|
|
errorMessage.innerHTML = '<i class="fas fa-exclamation-circle"></i> ' + error.message;
|
|
contactForm.insertBefore(errorMessage, submitButton);
|
|
|
|
// Remove error message after 5 seconds
|
|
setTimeout(() => {
|
|
errorMessage.remove();
|
|
}, 5000);
|
|
|
|
} finally {
|
|
submitButton.disabled = false;
|
|
submitButton.innerHTML = originalButtonText;
|
|
}
|
|
});
|
|
} |