Download script.js from thetwistedpixie/neonnexus-agency: direct link, hf CLI and curl.
- Browser
- Download file 14.8 kB
-
https://huggingface.co/spaces/thetwistedpixie/neonnexus-agency/resolve/main/script.js
- Command line
-
hf download hf://spaces/thetwistedpixie/neonnexus-agency/script.js
-
curl -L -o script.js https://huggingface.co/spaces/thetwistedpixie/neonnexus-agency/resolve/main/script.js
14.8 kB
| // Theme Management | |
| class ThemeManager { | |
| constructor() { | |
| this.themeToggle = document.getElementById('theme-toggle'); | |
| this.htmlElement = document.documentElement; | |
| this.currentTheme = localStorage.getItem('theme') || 'dark'; | |
| this.init(); | |
| } | |
| init() { | |
| this.applyTheme(this.currentTheme); | |
| this.themeToggle.addEventListener('click', () => this.toggleTheme()); | |
| } | |
| applyTheme(theme) { | |
| if (theme === 'light') { | |
| this.htmlElement.classList.remove('dark-mode'); | |
| this.htmlElement.classList.add('light-mode'); | |
| document.body.classList.add('light-mode'); | |
| } else { | |
| this.htmlElement.classList.remove('light-mode'); | |
| this.htmlElement.classList.add('dark-mode'); | |
| document.body.classList.remove('light-mode'); | |
| } | |
| localStorage.setItem('theme', theme); | |
| this.updateIcons(theme); | |
| } | |
| toggleTheme() { | |
| const newTheme = this.currentTheme === 'dark' ? 'light' : 'dark'; | |
| this.currentTheme = newTheme; | |
| this.applyTheme(newTheme); | |
| this.themeToggle.classList.add('animate-pulse-custom'); | |
| setTimeout(() => this.themeToggle.classList.remove('animate-pulse-custom'), 500); | |
| } | |
| updateIcons(theme) { | |
| const darkIcon = this.themeToggle.querySelector('.dark-icon'); | |
| const lightIcon = this.themeToggle.querySelector('.light-icon'); | |
| if (theme === 'light') { | |
| darkIcon.classList.remove('hidden'); | |
| lightIcon.classList.add('hidden'); | |
| } else { | |
| darkIcon.classList.add('hidden'); | |
| lightIcon.classList.remove('hidden'); | |
| } | |
| } | |
| } | |
| // Loading Screen | |
| class LoadingManager { | |
| constructor() { | |
| this.loadingScreen = document.getElementById('loading-screen'); | |
| this.init(); | |
| } | |
| init() { | |
| window.addEventListener('load', () => { | |
| setTimeout(() => { | |
| this.loadingScreen.style.opacity = '0'; | |
| setTimeout(() => { | |
| this.loadingScreen.style.display = 'none'; | |
| }, 500); | |
| }, 1000); | |
| }); | |
| } | |
| } | |
| // Smooth Scrolling | |
| class SmoothScroll { | |
| constructor() { | |
| this.links = document.querySelectorAll('a[href^="#"]'); | |
| this.init(); | |
| } | |
| init() { | |
| this.links.forEach(link => { | |
| link.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| const targetId = link.getAttribute('href'); | |
| const targetSection = document.querySelector(targetId); | |
| if (targetSection) { | |
| targetSection.scrollIntoView({ | |
| behavior: 'smooth', | |
| block: 'start' | |
| }); | |
| } | |
| }); | |
| }); | |
| } | |
| } | |
| // Intersection Observer for Animations | |
| class ScrollAnimations { | |
| constructor() { | |
| this.sections = document.querySelectorAll('section'); | |
| this.init(); | |
| } | |
| init() { | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| entry.target.classList.add('section-visible'); | |
| entry.target.classList.remove('section-hidden'); | |
| } | |
| }); | |
| }, { | |
| threshold: 0.15, | |
| rootMargin: '0px 0px -100px 0px' | |
| }); | |
| this.sections.forEach(section => { | |
| section.classList.add('section-hidden'); | |
| observer.observe(section); | |
| }); | |
| } | |
| } | |
| // Contact Form Handler | |
| class ContactForm { | |
| constructor() { | |
| this.form = document.getElementById('contact-form'); | |
| this.init(); | |
| } | |
| init() { | |
| if (this.form) { | |
| this.form.addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| this.handleSubmit(); | |
| }); | |
| } | |
| } | |
| async handleSubmit() { | |
| const formData = new FormData(this.form); | |
| const data = Object.fromEntries(formData); | |
| // Show loading state | |
| const submitButton = this.form.querySelector('button[type="submit"]'); | |
| const originalText = submitButton.innerHTML; | |
| submitButton.innerHTML = '<i data-feather="loader" class="w-5 h-5 animate-spin inline-block"></i> Sending...'; | |
| feather.replace(); | |
| try { | |
| // Simulate API call | |
| await new Promise(resolve => setTimeout(resolve, 2000)); | |
| // Show success message | |
| this.showSuccess(); | |
| this.form.reset(); | |
| } catch (error) { | |
| console.error('Form submission error:', error); | |
| } finally { | |
| submitButton.innerHTML = originalText; | |
| } | |
| } | |
| showSuccess() { | |
| const successDiv = document.createElement('div'); | |
| successDiv.className = 'success-message show'; | |
| successDiv.innerHTML = '๐ Message sent successfully! We\'ll get back to you soon.'; | |
| this.form.appendChild(successDiv); | |
| setTimeout(() => { | |
| successDiv.classList.remove('show'); | |
| setTimeout(() => successDiv.remove(), 300); | |
| }, 5000); | |
| } | |
| } | |
| // Portfolio Data Loader | |
| class PortfolioLoader { | |
| constructor() { | |
| this.grid = document.getElementById('portfolio-grid'); | |
| this.init(); | |
| } | |
| init() { | |
| // Using static.photos for consistent placeholder images | |
| const portfolioItems = [ | |
| { | |
| title: "E-Commerce Revolution", | |
| category: "Web Development", | |
| image: "http://static.photos/technology/640x360/42", | |
| description: "Built a scalable e-commerce platform with 300% conversion increase" | |
| }, | |
| { | |
| title: "Brand Identity Suite", | |
| category: "Design", | |
| image: "http://static.photos/workspace/640x360/133", | |
| description: "Complete brand redesign for a Fortune 500 company" | |
| }, | |
| { | |
| title: "Mobile Banking App", | |
| category: "Mobile Development", | |
| image: "http://static.photos/abstract/640x360/99", | |
| description: "Secure, intuitive banking app with biometric authentication" | |
| }, | |
| { | |
| title: "AI Dashboard", | |
| category: "Data Visualization", | |
| image: "http://static.photos/industry/640x360/77", | |
| description: "Real-time analytics dashboard powered by machine learning" | |
| }, | |
| { | |
| title: "Social Campaign", | |
| category: "Marketing", | |
| image: "http://static.photos/people/640x360/21", | |
| description: "Viral marketing campaign reaching 10M+ impressions" | |
| }, | |
| { | |
| title: "Secure Cloud Migration", | |
| category: "Cybersecurity", | |
| image: "http://static.photos/network/640x360/55", | |
| description: "Zero-downtime migration with enhanced security protocols" | |
| } | |
| ]; | |
| this.renderPortfolio(portfolioItems); | |
| } | |
| renderPortfolio(items) { | |
| items.forEach((item, index) => { | |
| const portfolioElement = document.createElement('portfolio-item'); | |
| portfolioElement.setAttribute('title', item.title); | |
| portfolioElement.setAttribute('category', item.category); | |
| portfolioElement.setAttribute('image', item.image); | |
| portfolioElement.setAttribute('description', item.description); | |
| // Stagger animation | |
| setTimeout(() => { | |
| this.grid.appendChild(portfolioElement); | |
| }, index * 100); | |
| }); | |
| } | |
| } | |
| // Testimonials Loader | |
| class TestimonialsLoader { | |
| constructor() { | |
| this.container = document.getElementById('testimonials-slider'); | |
| this.currentIndex = 0; | |
| this.testimonials = []; | |
| this.init(); | |
| } | |
| async init() { | |
| try { | |
| // Fetch real testimonials from JSONPlaceholder | |
| const response = await fetch('https://jsonplaceholder.typicode.com/comments?_limit=5'); | |
| const data = await response.json(); | |
| this.testimonials = data.slice(0, 5).map(comment => ({ | |
| name: comment.name.split(' ').map(word => | |
| word.charAt(0).toUpperCase() + word.slice(1) | |
| ).join(' '), | |
| text: comment.body.charAt(0).toUpperCase() + comment.body.slice(1), | |
| role: ['CEO', 'Founder', 'CTO', 'Director', 'Product Manager'][Math.floor(Math.random() * 5)], | |
| company: ['TechCorp', 'StartupX', 'Digital Dreams', 'FutureLabs', 'Innovate Inc'][Math.floor(Math.random() * 5)] | |
| })); | |
| this.renderTestimonials(); | |
| this.startAutoSlide(); | |
| } catch (error) { | |
| console.error('Failed to load testimonials:', error); | |
| this.renderFallbackTestimonials(); | |
| } | |
| } | |
| renderTestimonials() { | |
| const testimonialHTML = this.testimonials.map((t, index) => ` | |
| <div class="testimonial-slide ${index === 0 ? 'active' : ''} bg-gray-800 p-8 rounded-2xl shadow-xl"> | |
| <div class="flex items-center mb-6"> | |
| <div class="w-16 h-16 bg-gradient-to-br from-primary-500 to-secondary-500 rounded-full flex items-center justify-center text-white font-bold text-xl mr-4"> | |
| ${t.name.split(' ').map(n => n[0]).join('')} | |
| </div> | |
| <div> | |
| <h4 class="font-bold text-lg">${t.name}</h4> | |
| <p class="text-primary-400 text-sm">${t.role} at ${t.company}</p> | |
| </div> | |
| </div> | |
| <blockquote class="text-gray-300 text-lg italic"> | |
| <i data-feather="quote" class="w-8 h-8 text-primary-500 mb-4"></i> | |
| "${t.text}" | |
| </blockquote> | |
| <div class="flex mt-6"> | |
| ${Array(5).fill().map(() => '<i data-feather="star" class="w-5 h-5 text-yellow-400 fill-current"></i>').join('')} | |
| </div> | |
| </div> | |
| `).join(''); | |
| this.container.innerHTML = ` | |
| <div class="relative"> | |
| ${testimonialHTML} | |
| <div class="flex justify-center mt-8 space-x-4"> | |
| ${this.testimonials.map((_, index) => ` | |
| <button class="testimonial-dot w-4 h-4 rounded-full transition-all duration-300 ${index === 0 ? 'bg-primary-500' : 'bg-gray-600 hover:bg-gray-500'}" data-index="${index}"></button> | |
| `).join('')} | |
| </div> | |
| </div> | |
| `; | |
| this.attachDotListeners(); | |
| feather.replace(); | |
| } | |
| renderFallbackTestimonials() { | |
| const fallback = [ | |
| { | |
| name: "Sarah Johnson", | |
| role: "CEO", | |
| company: "TechVenture", | |
| text: "NeonNexus transformed our digital presence completely. The results exceeded all expectations!" | |
| } | |
| ]; | |
| this.testimonials = fallback; | |
| this.renderTestimonials(); | |
| } | |
| attachDotListeners() { | |
| const dots = this.container.querySelectorAll('.testimonial-dot'); | |
| dots.forEach(dot => { | |
| dot.addEventListener('click', (e) => { | |
| this.showTestimonial(parseInt(e.target.dataset.index)); | |
| }); | |
| }); | |
| } | |
| showTestimonial(index) { | |
| const slides = this.container.querySelectorAll('.testimonial-slide'); | |
| const dots = this.container.querySelectorAll('.testimonial-dot'); | |
| slides.forEach(slide => slide.classList.remove('active')); | |
| dots.forEach(dot => { | |
| dot.classList.remove('bg-primary-500'); | |
| dot.classList.add('bg-gray-600'); | |
| }); | |
| slides[index].classList.add('active'); | |
| dots[index].classList.remove('bg-gray-600'); | |
| dots[index].classList.add('bg-primary-500'); | |
| this.currentIndex = index; | |
| } | |
| startAutoSlide() { | |
| setInterval(() => { | |
| this.currentIndex = (this.currentIndex + 1) % this.testimonials.length; | |
| this.showTestimonial(this.currentIndex); | |
| }, 5000); | |
| } | |
| } | |
| // Mobile Menu Handler | |
| class MobileMenuHandler { | |
| constructor() { | |
| this.isOpen = false; | |
| this.init(); | |
| } | |
| init() { | |
| // This will be called from the navbar component | |
| window.addEventListener('mobile-menu-toggle', (e) => { | |
| this.isOpen = e.detail.isOpen; | |
| document.body.style.overflow = this.isOpen ? 'hidden' : ''; | |
| }); | |
| } | |
| } | |
| // Custom Cursor | |
| class CustomCursor { | |
| constructor() { | |
| this.cursor = document.createElement('div'); | |
| this.cursor.className = 'custom-cursor'; | |
| this.init(); | |
| } | |
| init() { | |
| document.body.appendChild(this.cursor); | |
| document.addEventListener('mousemove', (e) => { | |
| this.cursor.style.left = e.clientX + 'px'; | |
| this.cursor.style.top = e.clientY + 'px'; | |
| }); | |
| document.addEventListener('mousedown', () => { | |
| this.cursor.style.transform = 'scale(0.8)'; | |
| }); | |
| document.addEventListener('mouseup', () => { | |
| this.cursor.style.transform = 'scale(1)'; | |
| }); | |
| // Hide on touch devices | |
| if ('ontouchstart' in window) { | |
| this.cursor.style.display = 'none'; | |
| } | |
| } | |
| } | |
| // Initialize everything when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Core managers | |
| new ThemeManager(); | |
| new LoadingManager(); | |
| new SmoothScroll(); | |
| new ScrollAnimations(); | |
| new ContactForm(); | |
| new MobileMenuHandler(); | |
| // Data loaders | |
| new PortfolioLoader(); | |
| new TestimonialsLoader(); | |
| // Optional features | |
| new CustomCursor(); | |
| // Add some interactive elements | |
| initializeInteractiveEffects(); | |
| }); | |
| function initializeInteractiveEffects() { | |
| // Add parallax effect to hero elements | |
| window.addEventListener('scroll', () => { | |
| const scrolled = window.pageYOffset; | |
| const parallaxElements = document.querySelectorAll('.animate-float'); | |
| parallaxElements.forEach((element, index) => { | |
| const speed = 0.5 + (index * 0.1); | |
| element.style.transform = `translateY(${scrolled * speed}px) rotate(${scrolled * 0.05}deg)`; | |
| }); | |
| }); | |
| // Add click ripple effect to buttons | |
| document.querySelectorAll('button, .btn-primary').forEach |