Spaces:
Running
Running
// Main JavaScript functionality for Unity Fleet website | |
document.addEventListener('DOMContentLoaded', function() { | |
// Initialize animations and interactions | |
initScrollAnimations(); | |
initAccordion(); | |
initParallaxEffect(); | |
initHeroAnimation(); | |
// Mobile navigation toggle | |
const navLinks = document.querySelector('.nav-links'); | |
const mobileNavToggle = document.createElement('div'); | |
mobileNavToggle.className = 'mobile-nav-toggle'; | |
mobileNavToggle.innerHTML = '<i class="fas fa-bars"></i>'; | |
document.querySelector('nav').appendChild(mobileNavToggle); | |
mobileNavToggle.addEventListener('click', function() { | |
navLinks.classList.toggle('active'); | |
this.innerHTML = navLinks.classList.contains('active') | |
? '<i class="fas fa-times"></i>' | |
: '<i class="fas fa-bars"></i>'; | |
}); | |
}); | |
// Scroll animations for elements | |
function initScrollAnimations() { | |
const animatedElements = document.querySelectorAll('.section-header, .feature-item, .subscription-card, .impact-metric, .token-diagram, .rural-content, .timeline-item'); | |
const observer = new IntersectionObserver((entries) => { | |
entries.forEach(entry => { | |
if (entry.isIntersecting) { | |
entry.target.classList.add('animate'); | |
observer.unobserve(entry.target); | |
} | |
}); | |
}, { | |
threshold: 0.1 | |
}); | |
animatedElements.forEach(element => { | |
element.classList.add('pre-animation'); | |
observer.observe(element); | |
}); | |
// Add CSS for animations | |
const style = document.createElement('style'); | |
style.textContent = ` | |
.pre-animation { | |
opacity: 0; | |
transform: translateY(30px); | |
transition: opacity 0.6s ease, transform 0.6s ease; | |
} | |
.animate { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
.subscription-card.pre-animation { | |
transform: translateY(50px); | |
transition-delay: calc(var(--animation-order, 0) * 0.1s); | |
} | |
.feature-item.pre-animation { | |
transform: translateX(-30px); | |
transition-delay: calc(var(--animation-order, 0) * 0.1s); | |
} | |
.timeline-item.pre-animation { | |
transform: translateX(-30px); | |
transition-delay: calc(var(--animation-order, 0) * 0.15s); | |
} | |
`; | |
document.head.appendChild(style); | |
// Set animation order for staggered animations | |
document.querySelectorAll('.subscription-card').forEach((card, index) => { | |
card.style.setProperty('--animation-order', index); | |
}); | |
document.querySelectorAll('.feature-item').forEach((item, index) => { | |
item.style.setProperty('--animation-order', index); | |
}); | |
document.querySelectorAll('.timeline-item').forEach((item, index) => { | |
item.style.setProperty('--animation-order', index); | |
}); | |
} | |
// Accordion functionality for grant proposal section | |
function initAccordion() { | |
const accordionItems = document.querySelectorAll('.accordion-item'); | |
accordionItems.forEach(item => { | |
const header = item.querySelector('.accordion-header'); | |
const content = item.querySelector('.accordion-content'); | |
header.addEventListener('click', () => { | |
// Close all other accordion items | |
accordionItems.forEach(otherItem => { | |
if (otherItem !== item && otherItem.classList.contains('active')) { | |
otherItem.classList.remove('active'); | |
otherItem.querySelector('.accordion-content').style.maxHeight = '0px'; | |
} | |
}); | |
// Toggle current item | |
item.classList.toggle('active'); | |
if (item.classList.contains('active')) { | |
content.style.display = 'block'; | |
content.style.maxHeight = content.scrollHeight + 'px'; | |
} else { | |
content.style.maxHeight = '0px'; | |
setTimeout(() => { | |
content.style.display = 'none'; | |
}, 300); | |
} | |
}); | |
}); | |
// Open first accordion item by default | |
if (accordionItems.length > 0) { | |
accordionItems[0].classList.add('active'); | |
const firstContent = accordionItems[0].querySelector('.accordion-content'); | |
firstContent.style.display = 'block'; | |
firstContent.style.maxHeight = firstContent.scrollHeight + 'px'; | |
} | |
// Add CSS for accordion animations | |
const style = document.createElement('style'); | |
style.textContent = ` | |
.accordion-content { | |
max-height: 0; | |
overflow: hidden; | |
transition: max-height 0.3s ease; | |
} | |
`; | |
document.head.appendChild(style); | |
} | |
// Parallax effect for sections | |
function initParallaxEffect() { | |
window.addEventListener('scroll', () => { | |
const scrollPosition = window.pageYOffset; | |
// Parallax for hero section | |
const heroImage = document.querySelector('.hero-image'); | |
if (heroImage) { | |
heroImage.style.transform = `translateY(${scrollPosition * 0.4}px)`; | |
} | |
// Subtle parallax for section backgrounds | |
document.querySelectorAll('.section-gradient').forEach(section => { | |
const sectionTop = section.offsetTop; | |
const sectionHeight = section.offsetHeight; | |
const sectionMiddle = sectionTop + sectionHeight / 2; | |
const distanceFromMiddle = scrollPosition - sectionMiddle; | |
const parallaxValue = distanceFromMiddle * 0.05; | |
section.style.backgroundPosition = `center ${50 + parallaxValue}%`; | |
}); | |
}); | |
} | |
// Hero section animations | |
function initHeroAnimation() { | |
const heroContent = document.querySelector('.hero-content'); | |
const heroElements = heroContent.querySelectorAll('h1, h2, p, .cta-buttons'); | |
// Add CSS for hero animations | |
const style = document.createElement('style'); | |
style.textContent = ` | |
@keyframes fadeInUp { | |
from { | |
opacity: 0; | |
transform: translateY(30px); | |
} | |
to { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
} | |
.hero-animate { | |
animation: fadeInUp 0.8s forwards; | |
opacity: 0; | |
} | |
`; | |
document.head.appendChild(style); | |
// Apply staggered animations to hero elements | |
heroElements.forEach((element, index) => { | |
element.classList.add('hero-animate'); | |
element.style.animationDelay = `${0.3 + (index * 0.2)}s`; | |
}); | |
// Add hover effect to CTA buttons | |
document.querySelectorAll('.cta-buttons .btn').forEach(button => { | |
button.addEventListener('mouseenter', function() { | |
this.style.transform = 'translateY(-5px)'; | |
this.style.boxShadow = '0 15px 30px rgba(0, 224, 255, 0.3)'; | |
}); | |
button.addEventListener('mouseleave', function() { | |
this.style.transform = ''; | |
this.style.boxShadow = ''; | |
}); | |
}); | |
} | |
// Add smooth scrolling for navigation links | |
document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
anchor.addEventListener('click', function(e) { | |
e.preventDefault(); | |
const targetId = this.getAttribute('href'); | |
const targetElement = document.querySelector(targetId); | |
if (targetElement) { | |
// Close mobile navigation if open | |
document.querySelector('.nav-links').classList.remove('active'); | |
document.querySelector('.mobile-nav-toggle').innerHTML = '<i class="fas fa-bars"></i>'; | |
// Scroll to target | |
window.scrollTo({ | |
top: targetElement.offsetTop - 80, // Offset for fixed header | |
behavior: 'smooth' | |
}); | |
} | |
}); | |
}); | |
// Add fixed navigation on scroll | |
window.addEventListener('scroll', function() { | |
const nav = document.querySelector('nav'); | |
if (window.scrollY > 100) { | |
nav.classList.add('nav-scrolled'); | |
} else { | |
nav.classList.remove('nav-scrolled'); | |
} | |
}); | |
// Add CSS for fixed navigation | |
const navStyle = document.createElement('style'); | |
navStyle.textContent = ` | |
.nav-scrolled { | |
position: fixed; | |
background: rgba(11, 11, 15, 0.9); | |
backdrop-filter: blur(10px); | |
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3); | |
animation: slideDown 0.3s forwards; | |
} | |
@keyframes slideDown { | |
from { | |
transform: translateY(-100%); | |
} | |
to { | |
transform: translateY(0); | |
} | |
} | |
@media (max-width: 768px) { | |
.mobile-nav-toggle { | |
display: block; | |
font-size: 1.5rem; | |
cursor: pointer; | |
color: var(--accent-color-1); | |
} | |
.nav-links { | |
position: absolute; | |
top: 100%; | |
left: 0; | |
width: 100%; | |
background: rgba(11, 11, 15, 0.95); | |
flex-direction: column; | |
padding: 1rem 0; | |
clip-path: polygon(0 0, 100% 0, 100% 0, 0 0); | |
transition: clip-path 0.4s ease; | |
} | |
.nav-links.active { | |
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); | |
} | |
.nav-links a { | |
padding: 1rem 2rem; | |
} | |
} | |
`; | |
document.head.appendChild(navStyle); | |
// Add token orbit animation | |
const orbitStyle = document.createElement('style'); | |
orbitStyle.textContent = ` | |
.orbit-item { | |
transition: transform 0.3s ease, background 0.3s ease; | |
} | |
.orbit-item:hover { | |
transform: scale(1.2) !important; | |
background: var(--accent-color-1); | |
color: var(--bg-color); | |
} | |
`; | |
document.head.appendChild(orbitStyle); | |
// Add hover effects to image cards | |
document.querySelectorAll('.image-card').forEach(card => { | |
card.addEventListener('mouseenter', function() { | |
this.querySelector('img').style.transform = 'scale(1.05)'; | |
this.querySelector('.image-overlay').style.opacity = '1'; | |
}); | |
card.addEventListener('mouseleave', function() { | |
this.querySelector('img').style.transform = 'scale(1)'; | |
this.querySelector('.image-overlay').style.opacity = '0.8'; | |
}); | |
}); | |
// Add CSS for image card hover effects | |
const imageCardStyle = document.createElement('style'); | |
imageCardStyle.textContent = ` | |
.image-card img { | |
transition: transform 0.5s ease; | |
} | |
.image-overlay { | |
opacity: 0.8; | |
transition: opacity 0.3s ease; | |
} | |
`; | |
document.head.appendChild(imageCardStyle); | |