PageSourceSearch

https://humgod.vercel.app/script.js?v=7.0-force-deploy-1735471000

js humgod.vercel.app collected 2026-10-03 07:05:37 UTC 13,510 bytes, 447 lines download raw bytes

1// HumGod Landing Page JavaScript
2// Interactive elements, animations, and smooth functionality
3
4document.addEventListener('DOMContentLoaded', function() {
5    // Initialize all functionality
6    initNavigation();
7    initScrollEffects();
8    initTestimonials();
9    initFormTabs();
10    initAnimations();
11    initSmoothScrolling();
12    initParallaxEffects();
13});
14
15// Navigation functionality
16function initNavigation() {
17    const navToggle = document.querySelector('.nav-toggle');
18    const navMenu = document.querySelector('.nav-menu');
19    const navLinks = document.querySelectorAll('.nav-link');
20
21    // Mobile menu toggle
22    if (navToggle) {
23        navToggle.addEventListener('click', function() {
24            navToggle.classList.toggle('active');
25            navMenu.classList.toggle('active');
26        });
27    }
28
29    // Close mobile menu when clicking on links
30    navLinks.forEach(link => {
31        link.addEventListener('click', function() {
32            navMenu.classList.remove('active');
33            navToggle.classList.remove('active');
34        });
35    });
36
37    // Navbar background on scroll
38    window.addEventListener('scroll', function() {
39        const navbar = document.querySelector('.navbar');
40        if (window.scrollY > 100) {
41            navbar.style.background = 'rgba(10, 10, 10, 0.98)';
42        } else {
43            navbar.style.background = 'rgba(10, 10, 10, 0.95)';
44        }
45    });
46}
47
48// Scroll effects and animations
49function initScrollEffects() {
50    const observerOptions = {
51        threshold: 0.1,
52        rootMargin: '0px 0px -50px 0px'
53    };
54
55    const observer = new IntersectionObserver(function(entries) {
56        entries.forEach(entry => {
57            if (entry.isIntersecting) {
58                entry.target.style.opacity = '1';
59                entry.target.style.transform = 'translateY(0)';
60            }
61        });
62    }, observerOptions);
63
64    // Observe elements for scroll animations
65    const animatedElements = document.querySelectorAll('.step, .feature-card, .pricing-card, .testimonial');
66    animatedElements.forEach(el => {
67        el.style.opacity = '0';
68        el.style.transform = 'translateY(30px)';
69        el.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)';
70        observer.observe(el);
71    });
72}
73
74// Testimonials carousel
75function initTestimonials() {
76    const testimonials = document.querySelectorAll('.testimonial');
77    const dots = document.querySelectorAll('.dot');
78    let currentTestimonial = 0;
79
80    function showTestimonial(index) {
81        // Hide all testimonials
82        testimonials.forEach(testimonial => {
83            testimonial.classList.remove('active');
84        });
85
86        // Remove active class from all dots
87        dots.forEach(dot => {
88            dot.classList.remove('active');
89        });
90
91        // Show current testimonial
92        if (testimonials[index]) {
93            testimonials[index].classList.add('active');
94        }
95
96        // Add active class to current dot
97        if (dots[index]) {
98            dots[index].classList.add('active');
99        }
100    }
101
102    // Dot click handlers
103    dots.forEach((dot, index) => {
104        dot.addEventListener('click', function() {
105            currentTestimonial = index;
106            showTestimonial(currentTestimonial);
107        });
108    });
109
110    // Auto-rotate testimonials
111    setInterval(function() {
112        currentTestimonial = (currentTestimonial + 1) % testimonials.length;
113        showTestimonial(currentTestimonial);
114    }, 5000);
115}
116
117// Form tabs functionality
118function initFormTabs() {
119    const tabBtns = document.querySelectorAll('.tab-btn');
120    const forms = document.querySelectorAll('.form');
121
122    tabBtns.forEach(btn => {
123        btn.addEventListener('click', function() {
124            const targetTab = this.getAttribute('data-tab');
125
126            // Remove active class from all tabs and forms
127            tabBtns.forEach(tab => tab.classList.remove('active'));
128            forms.forEach(form => form.classList.remove('active'));
129
130            // Add active class to clicked tab
131            this.classList.add('active');
132
133            // Show corresponding form
134            const targetForm = document.getElementById(targetTab + 'Form');
135            if (targetForm) {
136                targetForm.classList.add('active');
137            }
138        });
139    });
140
141    // Form submission handlers
142    const signupForm = document.getElementById('signupForm');
143    const loginForm = document.getElementById('loginForm');
144
145    if (signupForm) {
146        signupForm.addEventListener('submit', function(e) {
147            e.preventDefault();
148            handleFormSubmission('signup');
149        });
150    }
151
152    if (loginForm) {
153        loginForm.addEventListener('submit', function(e) {
154            e.preventDefault();
155            handleFormSubmission('login');
156        });
157    }
158}
159
160// Form submission handler
161function handleFormSubmission(type) {
162    const form = document.getElementById(type + 'Form');
163    const inputs = form.querySelectorAll('input[required]');
164    let isValid = true;
165
166    // Basic validation
167    inputs.forEach(input => {
168        if (!input.value.trim()) {
169            isValid = false;
170            input.style.borderColor = '#ff4444';
171            setTimeout(() => {
172                input.style.borderColor = '';
173            }, 3000);
174        }
175    });
176
177    if (isValid) {
178        // Show loading state
179        const submitBtn = form.querySelector('button[type="submit"]');
180        const originalText = submitBtn.innerHTML;
181        submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Processing...';
182        submitBtn.disabled = true;
183
184        // Simulate API call
185        setTimeout(() => {
186            submitBtn.innerHTML = '<i class="fas fa-check"></i> Success!';
187            submitBtn.style.background = '#4CAF50';
188            
189            setTimeout(() => {
190                submitBtn.innerHTML = originalText;
191                submitBtn.disabled = false;
192                submitBtn.style.background = '';
193                form.reset();
194            }, 2000);
195        }, 2000);
196    }
197}
198
199// General animations
200function initAnimations() {
201    // Button hover effects
202    const buttons = document.querySelectorAll('.btn');
203    buttons.forEach(btn => {
204        btn.addEventListener('mouseenter', function() {
205            this.style.transform = 'translateY(-2px) scale(1.02)';
206        });
207
208        btn.addEventListener('mouseleave', function() {
209            this.style.transform = 'translateY(0) scale(1)';
210        });
211    });
212
213    // Card hover effects
214    const cards = document.querySelectorAll('.feature-card, .pricing-card, .step');
215    cards.forEach(card => {
216        card.addEventListener('mouseenter', function() {
217            this.style.transform = 'translateY(-10px) scale(1.02)';
218        });
219
220        card.addEventListener('mouseleave', function() {
221            this.style.transform = 'translateY(0) scale(1)';
222        });
223    });
224
225    // Floating notes animation
226    const notes = document.querySelectorAll('.note');
227    notes.forEach((note, index) => {
228        note.addEventListener('mouseenter', function() {
229            this.style.transform = 'translateY(-30px) rotate(15deg) scale(1.2)';
230            this.style.color = '#ff8c5a';
231        });
232
233        note.addEventListener('mouseleave', function() {
234            this.style.transform = '';
235            this.style.color = '';
236        });
237    });
238}
239
240// Smooth scrolling for navigation links
241function initSmoothScrolling() {
242    const navLinks = document.querySelectorAll('a[href^="#"]');
243    
244    navLinks.forEach(link => {
245        link.addEventListener('click', function(e) {
246            e.preventDefault();
247            
248            const targetId = this.getAttribute('href');
249            const targetSection = document.querySelector(targetId);
250            
251            if (targetSection) {
252                const offsetTop = targetSection.offsetTop - 80; // Account for fixed navbar
253                
254                window.scrollTo({
255                    top: offsetTop,
256                    behavior: 'smooth'
257                });
258            }
259        });
260    });
261
262    // Hero CTA buttons
263    const heroButtons = document.querySelectorAll('.hero-buttons .btn');
264    heroButtons.forEach(btn => {
265        btn.addEventListener('click', function(e) {
266            e.preventDefault();
267            
268            if (this.textContent.includes('Start Creating')) {
269                // Scroll to signup section
270                const signupSection = document.querySelector('#signup');
271                if (signupSection) {
272                    signupSection.scrollIntoView({ behavior: 'smooth' });
273                }
274            } else if (this.textContent.includes('Sign Up')) {
275                // Scroll to signup section
276                const signupSection = document.querySelector('#signup');
277                if (signupSection) {
278                    signupSection.scrollIntoView({ behavior: 'smooth' });
279                }
280            }
281        });
282    });
283}
284
285// Parallax effects
286function initParallaxEffects() {
287    window.addEventListener('scroll', function() {
288        const scrolled = window.pageYOffset;
289        const parallaxElements = document.querySelectorAll('.wave, .note');
290        
291        parallaxElements.forEach((element, index) => {
292            const speed = 0.5 + (index * 0.1);
293            element.style.transform = `translateY(${scrolled * speed}px)`;
294        });
295    });
296}
297
298// Utility functions
299function debounce(func, wait) {
300    let timeout;
301    return function executedFunction(...args) {
302        const later = () => {
303            clearTimeout(timeout);
304            func(...args);
305        };
306        clearTimeout(timeout);
307        timeout = setTimeout(later, wait);
308    };
309}
310
311// Loading animation for page
312window.addEventListener('load', function() {
313    document.body.style.opacity = '0';
314    document.body.style.transition = 'opacity 0.5s ease-in-out';
315    
316    setTimeout(() => {
317        document.body.style.opacity = '1';
318    }, 100);
319});
320
321// Keyboard navigation support
322document.addEventListener('keydown', function(e) {
323    // ESC key closes mobile menu
324    if (e.key === 'Escape') {
325        const navMenu = document.querySelector('.nav-menu');
326        const navToggle = document.querySelector('.nav-toggle');
327        
328        if (navMenu && navMenu.classList.contains('active')) {
329            navMenu.classList.remove('active');
330            navToggle.classList.remove('active');
331        }
332    }
333});
334
335// Intersection Observer for scroll-triggered animations
336const scrollObserver = new IntersectionObserver((entries) => {
337    entries.forEach(entry => {
338        if (entry.isIntersecting) {
339            entry.target.classList.add('animate-in');
340        }
341    });
342}, {
343    threshold: 0.1,
344    rootMargin: '0px 0px -100px 0px'
345});
346
347// Observe elements for animation
348document.querySelectorAll('.step, .feature-card, .pricing-card').forEach(el => {
349    scrollObserver.observe(el);
350});
351
352// Add CSS for animation classes
353const style = document.createElement('style');
354style.textContent = `
355    .animate-in {
356        animation: slideInUp 0.6s ease-out forwards;
357    }
358    
359    @keyframes slideInUp {
360        from {
361            opacity: 0;
362            transform: translateY(30px);
363        }
364        to {
365            opacity: 1;
366            transform: translateY(0);
367        }
368    }
369`;
370document.head.appendChild(style);
371
372// Performance optimization: Throttle scroll events
373const throttledScrollHandler = debounce(function() {
374    // Handle scroll events here if needed
375}, 16); // ~60fps
376
377window.addEventListener('scroll', throttledScrollHandler);
378
379// Add ripple effect to buttons
380function addRippleEffect() {
381    const buttons = document.querySelectorAll('.btn');
382    
383    buttons.forEach(button => {
384        button.addEventListener('click', function(e) {
385            const ripple = document.createElement('span');
386            const rect = this.getBoundingClientRect();
387            const size = Math.max(rect.width, rect.height);
388            const x = e.clientX - rect.left - size / 2;
389            const y = e.clientY - rect.top - size / 2;
390            
391            ripple.style.width = ripple.style.height = size + 'px';
392            ripple.style.left = x + 'px';
393            ripple.style.top = y + 'px';
394            ripple.classList.add('ripple');
395            
396            this.appendChild(ripple);
397            
398            setTimeout(() => {
399                ripple.remove();
400            }, 600);
401        });
402    });
403}
404
405// Initialize ripple effects
406addRippleEffect();
407
408// Add CSS for ripple effect
409const rippleStyle = document.createElement('style');
410rippleStyle.textContent = `
411    .btn {
412        position: relative;
413        overflow: hidden;
414    }
415    
416    .ripple {
417        position: absolute;
418        border-radius: 50%;
419        background: rgba(255, 255, 255, 0.3);
420        transform: scale(0);
421        animation: ripple 0.6s linear;
422        pointer-events: none;
423    }
424    
425    @keyframes ripple {
426        to {
427            transform: scale(4);
428            opacity: 0;
429        }
430    }
431`;
432document.head.appendChild(rippleStyle);
433
434// Console welcome message
435console.log(`
436🎵 Welcome to HumGod! 🎵
437Transform your musical ideas into reality with AI.
438Built with ❤️ for musicians everywhere.
439`);
440
441// Service Worker registration (for future PWA features)
442if ('serviceWorker' in navigator) {
443    window.addEventListener('load', function() {
444        // Service worker will be added in future updates
445        console.log('Service Worker support detected');
446    });
447}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.