Spaces:
Running
Running
| // Initialize everything when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize mobile menu | |
| initMobileMenu(); | |
| // Initialize smooth scrolling | |
| initSmoothScroll(); | |
| // Initialize form handling | |
| initSignupForm(); | |
| // Initialize scroll animations | |
| initScrollAnimations(); | |
| // Initialize parallax effects | |
| initParallaxEffects(); | |
| }); | |
| // Mobile menu functionality | |
| function initMobileMenu() { | |
| const mobileMenuBtn = document.getElementById('mobileMenuBtn'); | |
| const nav = document.querySelector('nav'); | |
| if (mobileMenuBtn) { | |
| mobileMenuBtn.addEventListener('click', function() { | |
| // Toggle mobile menu | |
| const mobileMenu = document.createElement('div'); | |
| mobileMenu.className = 'fixed inset-0 bg-white z-40 mobile-menu-enter'; | |
| mobileMenu.innerHTML = ` | |
| <div class="p-6"> | |
| <div class="flex justify-between items-center mb-8"> | |
| <span class="text-2xl font-bold text-gradient">StartupLaunch Pro</span> | |
| <button id="closeMobileMenu" class="p-2"> | |
| <i data-feather="x"></i> | |
| </button> | |
| </div> | |
| <div class="flex flex-col space-y-4"> | |
| <a href="#features" class="text-lg text-gray-700 hover:text-purple-600 transition">Features</a> | |
| <a href="#solution" class="text-lg text-gray-700 hover:text-purple-600 transition">Solution</a> | |
| <a href="#team" class="text-lg text-gray-700 hover:text-purple-600 transition">Team</a> | |
| <a href="#press" class="text-lg text-gray-700 hover:text-purple-600 transition">Press</a> | |
| <button class="bg-gradient-to-r from-purple-600 to-indigo-600 text-white px-6 py-3 rounded-full hover:shadow-lg transition mt-4"> | |
| Get Started | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| document.body.appendChild(mobileMenu); | |
| feather.replace(); | |
| // Close menu functionality | |
| document.getElementById('closeMobileMenu').addEventListener('click', function() { | |
| mobileMenu.remove(); | |
| }); | |
| // Close on link click | |
| mobileMenu.querySelectorAll('a').forEach(link => { | |
| link.addEventListener('click', function() { | |
| mobileMenu.remove(); | |
| }); | |
| }); | |
| }); | |
| } | |
| } | |
| // Smooth scrolling for anchor links | |
| function initSmoothScroll() { | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| anchor.addEventListener('click', function (e) { | |
| e.preventDefault(); | |
| const target = document.querySelector(this.getAttribute('href')); | |
| if (target) { | |
| const offset = 80; // Account for fixed header | |
| const targetPosition = target.offsetTop - offset; | |
| window.scrollTo({ | |
| top: targetPosition, | |
| behavior: 'smooth' | |
| }); | |
| } | |
| }); | |
| }); | |
| } | |
| // Email signup form handling | |
| function initSignupForm() { | |
| const signupForm = document.getElementById('signupForm'); | |
| const emailInput = document.getElementById('emailInput'); | |
| const successMessage = document.getElementById('successMessage'); | |
| if (signupForm) { | |
| signupForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const email = emailInput.value; | |
| // Validate email | |
| if (!validateEmail(email)) { | |
| showError('Please enter a valid email address'); | |
| return; | |
| } | |
| // Simulate API call | |
| const button = signupForm.querySelector('button[type="submit"]'); | |
| const originalText = button.textContent; | |
| button.textContent = 'Sending...'; | |
| button.disabled = true; | |
| setTimeout(() => { | |
| // Show success message | |
| successMessage.classList.remove('hidden'); | |
| emailInput.value = ''; | |
| button.textContent = originalText; | |
| button.disabled = false; | |
| // Hide success message after 5 seconds | |
| setTimeout(() => { | |
| successMessage.classList.add('hidden'); | |
| }, 5000); | |
| // Store email (in real app, this would be sent to backend) | |
| console.log('Email signed up:', email); | |
| }, 1500); | |
| }); | |
| } | |
| } | |
| // Email validation helper | |
| function validateEmail(email) { | |
| const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | |
| return re.test(email); | |
| } | |
| // Show error message | |
| function showError(message) { | |
| const errorDiv = document.createElement('div'); | |
| errorDiv.className = 'fixed top-20 right-6 bg-red-500 text-white px-6 py-3 rounded-lg shadow-lg z-50'; | |
| errorDiv.textContent = message; | |
| document.body.appendChild(errorDiv); | |
| setTimeout(() => { | |
| errorDiv.remove(); | |
| }, 3000); | |
| } | |
| // Scroll animations | |
| function initScrollAnimations() { | |
| // Add animation to elements when they come into view | |
| const observerOptions = { | |
| threshold: 0.1, | |
| rootMargin: '0px 0px -100px 0px' | |
| }; | |
| const observer = new IntersectionObserver(function(entries) { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| entry.target.style.opacity = '1'; | |
| entry.target.style.transform = 'translateY(0)'; | |
| } | |
| }); | |
| }, observerOptions); | |
| // Observe elements with animation | |
| document.querySelectorAll('[data-aos]').forEach(el => { | |
| el.style.opacity = '0'; | |
| el.style.transform = 'translateY(20px)'; | |
| el.style.transition = 'all 0.6s ease-out'; | |
| observer.observe(el); | |
| }); | |
| } | |
| // Parallax effects | |
| function initParallaxEffects() { | |
| let ticking = false; | |
| function updateParallax() { | |
| const scrolled = window.pageYOffset; | |
| const parallaxElements = document.querySelectorAll('.float-animation'); | |
| parallaxElements.forEach(el => { | |
| const speed = 0.5; | |
| const yPos = -(scrolled * speed); | |
| el.style.transform = `translateY(${yPos}px)`; | |
| }); | |
| ticking = false; | |
| } | |
| function requestTick() { | |
| if (!ticking) { | |
| window.requestAnimationFrame(updateParallax); | |
| ticking = true; | |
| } | |
| } | |
| window.addEventListener('scroll', requestTick); | |
| } | |
| // Add number counter animation | |
| function animateCounter(element, target, duration = 2000) { | |
| let start = 0; | |
| const increment = target / (duration / 16); | |
| const timer = setInterval(() => { | |
| start += increment; | |
| if (start >= target) { | |
| element.textContent = target.toLocaleString(); | |
| clearInterval(timer); | |
| } else { | |
| element.textContent = Math.floor(start).toLocaleString(); | |
| } | |
| }, 16); | |
| } | |
| // Lazy load images | |
| function lazyLoadImages() { | |
| const images = document.querySelectorAll('img[data-src]'); | |
| const imageObserver = new IntersectionObserver((entries, observer) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| const img = entry.target; | |
| img.src = img.dataset.src; | |
| img.classList.remove('lazy-image'); | |
| img.classList.add('loaded'); | |
| imageObserver.unobserve(img); | |
| } | |
| }); | |
| }); | |
| images.forEach(img => { | |
| img.classList.add('lazy-image'); | |
| imageObserver.observe(img); | |
| }); | |
| } | |
| // Add hover effect to cards | |
| document.querySelectorAll('.hover-lift').forEach(card => { | |
| card.addEventListener('mouseenter', function() { | |
| this.style.transform = 'translateY(-10px) scale(1.02)'; | |
| }); | |
| card.addEventListener('mouseleave', function() { | |
| this.style.transform = 'translateY(0) scale(1)'; | |
| }); | |
| }); | |
| // Add typing effect to hero text | |
| function typeWriter(element, text, speed = 50) { | |
| let i = 0; | |
| element.textContent = ''; | |
| function type() { | |
| if (i < text.length) { | |
| element.textContent += text.charAt(i); | |
| i++; | |
| setTimeout(type, speed); | |
| } | |
| } | |
| type(); | |
| } | |
| // Initialize on scroll progress bar | |
| function initScrollProgress() { | |
| const progressBar = document.createElement('div'); | |
| progressBar.className = 'fixed top-0 left-0 w-full h-1 bg-gradient-to-r from-purple-600 to-indigo-600 z-50 transform origin-left'; | |
| progressBar.style.transform = 'scaleX(0)'; | |
| progressBar.style.transition = 'transform 0.1s'; | |
| document.body.appendChild(progressBar); | |
| window.addEventListener('scroll', () => { | |
| const scrolled = window.pageYOffset; | |
| const maxScroll = document.documentElement.scrollHeight - window.innerHeight; | |
| const progress = scrolled / maxScroll; | |
| progressBar.style.transform = `scaleX(${progress})`; | |
| }); | |
| } | |
| // Initialize all features | |
| window.addEventListener('load', () => { | |
| lazyLoadImages(); | |
| initScrollProgress(); | |
| // Add loading animation removal | |
| document.body.classList.add('loaded'); | |
| }); |