PageSourceSearch

https://softmedia.ai/js/scripts.js

js softmedia.ai collected 2026-10-05 15:50:57 UTC 8,355 bytes, 229 lines download raw bytes

1document.addEventListener('DOMContentLoaded', function() {
2    // Mobile menu toggle
3    const mobileMenuButton = document.getElementById('mobile-menu-button');
4    const mobileMenu = document.getElementById('mobile-menu');
5
6    if (mobileMenuButton && mobileMenu) {
7        mobileMenuButton.addEventListener('click', function() {
8            mobileMenu.classList.toggle('hidden');
9            
10            // Změna ikony menu
11            const iconContainer = this.querySelector('.icon-container');
12            const isOpen = !mobileMenu.classList.contains('hidden');
13            
14            if (iconContainer) {
15                if (isOpen) {
16                    // Změna na křížek (X)
17                    iconContainer.innerHTML = `
18                        <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
19                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
20                        </svg>
21                    `;
22                } else {
23                    // Změna zpět na hamburger menu
24                    iconContainer.innerHTML = `
25                        <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
26                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
27                        </svg>
28                    `;
29                }
30            }
31        });
32    }
33
34    // Mobile submenu toggles
35    const submenuToggles = document.querySelectorAll('.mobile-submenu-toggle');
36    
37    submenuToggles.forEach(toggle => {
38        toggle.addEventListener('click', function(e) {
39            e.preventDefault();
40            const targetId = this.getAttribute('data-target');
41            const submenu = document.getElementById(targetId);
42            const arrow = document.getElementById(targetId.split('-')[0] + '-arrow');
43            
44            if (submenu && arrow) {
45                submenu.classList.toggle('hidden');
46                arrow.classList.toggle('rotate-180');
47            }
48        });
49    });
50
51    // Sticky header on scroll
52    const header = document.getElementById('main-header');
53
54    if (header) {
55        window.addEventListener('scroll', function() {
56            if (window.scrollY > 50) {
57                header.classList.add('scrolled', 'bg-white/95', 'backdrop-blur-sm', 'shadow-md');
58            } else {
59                header.classList.remove('scrolled', 'bg-white/95', 'backdrop-blur-sm', 'shadow-md');
60            }
61        });
62
63        // Trigger scroll event on load to handle page refreshes
64        window.dispatchEvent(new Event('scroll'));
65    }
66
67    // Scroll indicator click handler
68    const scrollIndicator = document.querySelector('.scroll-indicator');
69
70    if (scrollIndicator) {
71        scrollIndicator.addEventListener('click', function() {
72            const nextSection = document.querySelector('#sluzby, #produkty, #proc-my');
73
74            if (nextSection) {
75                nextSection.scrollIntoView({
76                    behavior: 'smooth',
77                    block: 'start'
78                });
79            }
80        });
81    }
82
83    // Smooth scroll for anchor links
84    document.querySelectorAll('a[href^="#"]').forEach(anchor => {
85        anchor.addEventListener('click', function(e) {
86            const targetId = this.getAttribute('href');
87
88            if (targetId === '#') return;
89
90            const targetElement = document.querySelector(targetId);
91
92            if (targetElement) {
93                e.preventDefault();
94
95                window.scrollTo({
96                    top: targetElement.offsetTop - 100,
97                    behavior: 'smooth'
98                });
99
100                // Close mobile menu if open
101                if (mobileMenu && !mobileMenu.classList.contains('hidden')) {
102                    mobileMenu.classList.add('hidden');
103                }
104            }
105        });
106    });
107
108    // Typing animation pro hlavní nadpis(y)
109    const typingElements = document.querySelectorAll('.typing');
110    let animationsCompleted = 0;
111
112    typingElements.forEach(element => {
113        const text = element.textContent;
114        element.textContent = '';
115
116        let charIndex = 0;
117        const typeInterval = setInterval(() => {
118            if (charIndex < text.length) {
119                element.textContent += text.charAt(charIndex);
120                charIndex++;
121            } else {
122                clearInterval(typeInterval);
123                element.classList.remove('typing');
124                animationsCompleted++;
125                // Pokud jsou všechny animace hotové, dispatchni vlastní událost
126                if (animationsCompleted === typingElements.length) {
127                    document.dispatchEvent(new Event('headlineAnimationDone'));
128                }
129            }
130        }, 100);
131    });
132
133
134    // Animation on scroll
135    const animatedElements = document.querySelectorAll('.fade-in-up');
136
137    function checkIfInView() {
138        const windowHeight = window.innerHeight;
139        const windowTopPosition = window.scrollY;
140        const windowBottomPosition = windowTopPosition + windowHeight;
141
142        animatedElements.forEach(element => {
143            const elementHeight = element.offsetHeight;
144            const elementTopPosition = element.offsetTop;
145            const elementBottomPosition = elementTopPosition + elementHeight;
146
147            // Check if element is in view with buffer
148            if (
149                (elementBottomPosition >= windowTopPosition - 100) &&
150                (elementTopPosition <= windowBottomPosition + 100)
151            ) {
152                element.classList.add('visible');
153            }
154        });
155    }
156
157    // Run on load
158    checkIfInView();
159
160    // Run on scroll
161    window.addEventListener('scroll', checkIfInView);
162
163    // Run on resize
164    window.addEventListener('resize', checkIfInView);
165
166    // FAQ accordions (if present)
167    const faqButtons = document.querySelectorAll('.faq-question');
168
169    if (faqButtons.length > 0) {
170        faqButtons.forEach(button => {
171            button.addEventListener('click', function() {
172                const answer = this.nextElementSibling;
173                const icon = this.querySelector('svg');
174
175                answer.classList.toggle('hidden');
176                icon.classList.toggle('rotate-180');
177
178                // Close other open FAQs
179                faqButtons.forEach(otherButton => {
180                    if (otherButton !== button) {
181                        const otherAnswer = otherButton.nextElementSibling;
182                        const otherIcon = otherButton.querySelector('svg');
183
184                        if (!otherAnswer.classList.contains('hidden')) {
185                            otherAnswer.classList.add('hidden');
186                            otherIcon.classList.remove('rotate-180');
187                        }
188                    }
189                });
190            });
191        });
192    }
193
194    // Handle testimonial sliders if present
195    const testimonialSliders = document.querySelectorAll('.testimonial-slider');
196
197    if (testimonialSliders.length > 0) {
198        testimonialSliders.forEach(slider => {
199            const slides = slider.querySelectorAll('.testimonial-slide');
200            const nextButton = slider.querySelector('.next-slide');
201            const prevButton = slider.querySelector('.prev-slide');
202            let currentSlide = 0;
203
204            function showSlide(index) {
205                slides.forEach((slide, i) => {
206                    slide.classList.toggle('hidden', i !== index);
207                    slide.setAttribute('aria-hidden', i !== index);
208                });
209            }
210
211            if (nextButton) {
212                nextButton.addEventListener('click', () => {
213                    currentSlide = (currentSlide + 1) % slides.length;
214                    showSlide(currentSlide);
215                });
216            }
217
218            if (prevButton) {
219                prevButton.addEventListener('click', () => {
220                    currentSlide = (currentSlide - 1 + slides.length) % slides.length;
221                    showSlide(currentSlide);
222                });
223            }
224
225            // Initialize
226            showSlide(0);
227        });
228    }
229});

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.