PageSourceSearch

https://citrus-burn.com/js/main.js

js citrus-burn.com collected 2026-10-02 01:25:40 UTC 5,302 bytes, 152 lines download raw bytes

1// CitrusBurn Review - Main JavaScript
2// Handles navigation, FAQ accordions, smooth scrolling, and header effects
3
4document.addEventListener('DOMContentLoaded', function() {
5    
6    // Mobile Navigation Toggle
7    const hamburger = document.getElementById('hamburger');
8    const navMobile = document.getElementById('nav-mobile');
9    
10    if (hamburger && navMobile) {
11        hamburger.addEventListener('click', function() {
12            hamburger.classList.toggle('active');
13            navMobile.classList.toggle('active');
14        });
15        
16        // Close mobile nav when clicking a link
17        const mobileLinks = navMobile.querySelectorAll('a');
18        mobileLinks.forEach(link => {
19            link.addEventListener('click', function() {
20                hamburger.classList.remove('active');
21                navMobile.classList.remove('active');
22            });
23        });
24    }
25    
26    // Header Scroll Effect
27    const header = document.getElementById('header');
28    let lastScroll = 0;
29    
30    window.addEventListener('scroll', function() {
31        const currentScroll = window.pageYOffset;
32        
33        if (currentScroll > 100) {
34            header.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
35        } else {
36            header.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
37        }
38        
39        lastScroll = currentScroll;
40    });
41    
42    // Smooth Scrolling for Anchor Links
43    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
44        anchor.addEventListener('click', function(e) {
45            e.preventDefault();
46            const targetId = this.getAttribute('href');
47            
48            if (targetId === '#') return;
49            
50            const targetElement = document.querySelector(targetId);
51            
52            if (targetElement) {
53                const headerOffset = 80;
54                const elementPosition = targetElement.getBoundingClientRect().top;
55                const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
56                
57                window.scrollTo({
58                    top: offsetPosition,
59                    behavior: 'smooth'
60                });
61            }
62        });
63    });
64    
65    // FAQ Accordion
66    const faqItems = document.querySelectorAll('.faq-item');
67    
68    faqItems.forEach(item => {
69        const question = item.querySelector('.faq-question');
70        
71        if (question) {
72            question.addEventListener('click', function() {
73                const isActive = item.classList.contains('active');
74                
75                // Close all other FAQs in the same category
76                const category = item.closest('.faq-category');
77                if (category) {
78                    category.querySelectorAll('.faq-item').forEach(faq => {
79                        faq.classList.remove('active');
80                    });
81                }
82                
83                // Toggle current FAQ
84                if (!isActive) {
85                    item.classList.add('active');
86                }
87            });
88        }
89    });
90    
91    // Lazy Loading Images (fallback for browsers without native support)
92    if ('loading' in HTMLImageElement.prototype) {
93        // Native lazy loading supported
94        const images = document.querySelectorAll('img[loading="lazy"]');
95        images.forEach(img => {
96            if (img.dataset.src) {
97                img.src = img.dataset.src;
98            }
99        });
100    } else {
101        // Fallback for older browsers
102        const script = document.createElement('script');
103        script.src = 'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/lazysizes.min.js';
104        document.body.appendChild(script);
105    }
106    
107    // Track CTA Clicks (for analytics)
108    const ctaButtons = document.querySelectorAll('a[href="order.html"]');
109    ctaButtons.forEach(btn => {
110        btn.addEventListener('click', function() {
111            // Track click event if analytics is available
112            if (typeof gtag !== 'undefined') {
113                gtag('event', 'click', {
114                    'event_category': 'CTA',
115                    'event_label': this.textContent.trim(),
116                    'transport_type': 'beacon'
117                });
118            }
119        });
120    });
121    
122    // Intersection Observer for Animations
123    const observerOptions = {
124        root: null,
125        rootMargin: '0px',
126        threshold: 0.1
127    };
128    
129    const observer = new IntersectionObserver((entries) => {
130        entries.forEach(entry => {
131            if (entry.isIntersecting) {
132                entry.target.style.opacity = '1';
133                entry.target.style.transform = 'translateY(0)';
134            }
135        });
136    }, observerOptions);
137    
138    // Observe elements for fade-in animation
139    const animateElements = document.querySelectorAll('.summary-card, .step-card, .ingredient-card, .testimonial-card, .pricing-card');
140    animateElements.forEach(el => {
141        el.style.opacity = '0';
142        el.style.transform = 'translateY(20px)';
143        el.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
144        observer.observe(el);
145    });
146    
147});
148
149// Utility function to format numbers
150function formatNumber(num) {
151    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
152}

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.