222 lines
8.4 KiB
JavaScript
222 lines
8.4 KiB
JavaScript
/**
|
|
* Main JavaScript file for argobox.com
|
|
* Handles navigation, animations, and interactivity
|
|
*/
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Update current year in footer
|
|
const yearElement = document.getElementById('current-year');
|
|
if (yearElement) {
|
|
yearElement.textContent = new Date().getFullYear();
|
|
}
|
|
|
|
// Mobile menu toggle
|
|
const menuToggle = document.querySelector('.mobile-menu-btn');
|
|
const navLinks = document.querySelector('.nav-links');
|
|
|
|
if (menuToggle && navLinks) {
|
|
menuToggle.addEventListener('click', function() {
|
|
navLinks.classList.toggle('active');
|
|
});
|
|
}
|
|
|
|
// Set active navigation links based on scroll position
|
|
const sections = document.querySelectorAll('section');
|
|
const navItems = document.querySelectorAll('.nav-link');
|
|
|
|
function updateActiveLink() {
|
|
let currentSection = '';
|
|
|
|
sections.forEach(section => {
|
|
const sectionTop = section.offsetTop - 100;
|
|
const sectionHeight = section.offsetHeight;
|
|
|
|
if (window.scrollY >= sectionTop && window.scrollY < sectionTop + sectionHeight) {
|
|
currentSection = section.getAttribute('id');
|
|
}
|
|
});
|
|
|
|
navItems.forEach(link => {
|
|
link.classList.remove('active');
|
|
if (link.getAttribute('href') === `#${currentSection}`) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
window.addEventListener('scroll', updateActiveLink);
|
|
updateActiveLink();
|
|
|
|
// Handle navbar style change on scroll
|
|
const navbar = document.querySelector('.navbar');
|
|
|
|
function updateNavbarStyle() {
|
|
if (window.scrollY > 50) {
|
|
navbar?.classList.add('scrolled');
|
|
} else {
|
|
navbar?.classList.remove('scrolled');
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', updateNavbarStyle);
|
|
updateNavbarStyle();
|
|
|
|
// Form submission handling
|
|
const contactForm = document.getElementById('contact-form');
|
|
|
|
if (contactForm) {
|
|
contactForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
// In a real implementation, you would send the form data to a backend service
|
|
// For now, we'll just simulate a successful submission
|
|
|
|
const formData = new FormData(contactForm);
|
|
const formValues = Object.fromEntries(formData.entries());
|
|
|
|
console.log('Form submission:', formValues);
|
|
|
|
// Show success message
|
|
alert('Thank you for your message! I will get back to you soon.');
|
|
|
|
// Reset form
|
|
contactForm.reset();
|
|
});
|
|
}
|
|
|
|
// Initialize and animate the hero terminal
|
|
const typingElement = document.querySelector('.typing-effect');
|
|
if (typingElement) {
|
|
// The animation is handled by CSS, nothing to do here
|
|
console.log('Terminal typing animation initialized');
|
|
}
|
|
|
|
// Create animated data streams in the dashboard
|
|
function createDataStreamAnimation() {
|
|
// Look for either class name that might be in the HTML
|
|
const dataStreamContainer = document.querySelector('.data-stream') ||
|
|
document.querySelector('.hero-visual .tech-dashboard .data-stream');
|
|
|
|
console.log('Data stream container found:', !!dataStreamContainer);
|
|
|
|
if (!dataStreamContainer) return;
|
|
|
|
// Clear existing lines
|
|
const existingLines = dataStreamContainer.querySelectorAll('.data-line');
|
|
existingLines.forEach(line => line.remove());
|
|
|
|
// Create new random lines
|
|
for (let i = 0; i < 10; i++) {
|
|
const line = document.createElement('div');
|
|
line.classList.add('data-line');
|
|
|
|
// Random positioning and animation
|
|
const left = Math.random() * 90 + 5; // 5-95%
|
|
const width = Math.random() * 40 + 10; // 10-50%
|
|
const duration = Math.random() * 3 + 2; // 2-5s
|
|
|
|
line.style.left = `${left}%`;
|
|
line.style.width = `${width}%`;
|
|
line.style.animationDuration = `${duration}s`;
|
|
|
|
dataStreamContainer.appendChild(line);
|
|
console.log('Added data line:', i);
|
|
}
|
|
}
|
|
|
|
// Try to initialize the data stream animation (with retry for race conditions)
|
|
setTimeout(createDataStreamAnimation, 100);
|
|
|
|
// Refresh data streams periodically
|
|
setInterval(createDataStreamAnimation, 8000);
|
|
|
|
// Update terminal output with random status messages
|
|
function updateTerminalOutput() {
|
|
const terminalOutput = document.querySelector('.terminal-output');
|
|
if (!terminalOutput) return;
|
|
|
|
const statusMessages = [
|
|
{ text: 'All systems operational', type: '' },
|
|
{ text: 'Backup completed successfully', type: 'terminal-success' },
|
|
{ text: 'Security scan in progress', type: 'terminal-info' },
|
|
{ text: 'New updates available', type: 'terminal-warning' },
|
|
{ text: 'Optimizing database performance', type: 'terminal-info' }
|
|
];
|
|
|
|
// Randomly update one of the lines
|
|
const lineIndex = Math.floor(Math.random() * 2) + 4; // Only update the last few lines
|
|
const lineToUpdate = terminalOutput.children[lineIndex];
|
|
|
|
if (lineToUpdate) {
|
|
const randomMessage = statusMessages[Math.floor(Math.random() * statusMessages.length)];
|
|
lineToUpdate.textContent = `> ${randomMessage.text}`;
|
|
lineToUpdate.className = 'terminal-line';
|
|
if (randomMessage.type) {
|
|
lineToUpdate.classList.add(randomMessage.type);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Periodically update the terminal with new messages
|
|
setInterval(updateTerminalOutput, 5000);
|
|
|
|
// Simulated live metrics - randomly update values periodically
|
|
function updateMetrics() {
|
|
function updateMetricIfExists(selector, minValue, maxValue) {
|
|
const valueElement = document.querySelector(selector + ' .metric-value') ||
|
|
document.querySelector(selector + ' .metric-header .metric-value');
|
|
|
|
const barElement = document.querySelector(selector + ' .metric-progress');
|
|
|
|
if (valueElement && barElement) {
|
|
const newValue = Math.floor(Math.random() * (maxValue - minValue)) + minValue;
|
|
valueElement.textContent = `${newValue}%`;
|
|
barElement.style.width = `${newValue}%`;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Try different selectors to find the metrics
|
|
// First attempt with nth-child
|
|
let found = updateMetricIfExists('.metric:nth-child(1)', 20, 50);
|
|
if (!found) {
|
|
// Alternative approach - try by unique class or attribute
|
|
updateMetricIfExists('[data-metric="cpu"]', 20, 50);
|
|
}
|
|
|
|
updateMetricIfExists('.metric:nth-child(2)', 45, 65) ||
|
|
updateMetricIfExists('[data-metric="memory"]', 45, 65);
|
|
|
|
updateMetricIfExists('.metric:nth-child(3)', 60, 65) ||
|
|
updateMetricIfExists('[data-metric="storage"]', 60, 65);
|
|
|
|
updateMetricIfExists('.metric:nth-child(4)', 15, 45) ||
|
|
updateMetricIfExists('[data-metric="network"]', 15, 45);
|
|
}
|
|
|
|
// Update metrics every 5 seconds
|
|
setInterval(updateMetrics, 5000);
|
|
|
|
// Trigger an initial metrics update
|
|
setTimeout(updateMetrics, 500);
|
|
|
|
// Debug info - help determine if there are any issues
|
|
console.log('Script loaded successfully');
|
|
console.log('Sections found:', sections.length);
|
|
console.log('Nav links found:', navItems.length);
|
|
|
|
// Check if dashboard elements exist
|
|
console.log('Data stream container exists:',
|
|
!!document.querySelector('.data-stream') ||
|
|
!!document.querySelector('.tech-dashboard .data-stream'));
|
|
|
|
console.log('Metrics containers exist:',
|
|
!!document.querySelector('.metric'));
|
|
|
|
// Add some diagnostic info in case we're having issues
|
|
if (!document.querySelector('.data-stream') &&
|
|
!document.querySelector('.tech-dashboard .data-stream')) {
|
|
console.warn('Data stream container not found - visualizations may not appear');
|
|
}
|
|
}); |