PageSourceSearch

https://sisanjuan.gob.ar/modules/mod_news_pro_gk5/tmpl/portal_modes/apple_stories/script.jquery.js

js sisanjuan.gob.ar collected 2026-10-02 10:19:19 UTC 4,617 bytes, 107 lines download raw bytes

1/**
2 * Apple Stories Portal Mode Script
3 * Maneja la navegación basada en JS con Scroll-Snap.
4 * Usamos Vanilla JS moderno (ES6 compatible con navegadores de 2026).
5 */
6document.addEventListener('DOMContentLoaded', () => {
7    
8    // Inicializar cada módulo en caso de haber varios publicados en la página
9    document.querySelectorAll('.gkNspPM-AppleStories').forEach(module => {
10        if (module.dataset.initialized) return;
11        module.dataset.initialized = 'true';
12        
13        const scrollContainer = module.querySelector('.applestories-cards-scroll');
14        const cards = Array.from(module.querySelectorAll('.applestories-card'));
15        const btnPrev = module.querySelector('.applestories-btn-prev');
16        const btnNext = module.querySelector('.applestories-btn-next');
17        const dots = Array.from(module.querySelectorAll('.applestories-dot'));
18        
19        if (!scrollContainer || cards.length === 0) return;
20        
21        let activeIdx = 0;
22
23        // --- 2. Sincronización visual (Active States) ---
24        const updateControls = () => {
25            let minDiff = Infinity;
26            
27            // Detectar cuál es la tarjeta más visible según el scroll map
28            cards.forEach((card, idx) => {
29                const diff = Math.abs((card.offsetLeft - scrollContainer.offsetLeft) - scrollContainer.scrollLeft);
30                if (diff < minDiff) {
31                    minDiff = diff;
32                    activeIdx = idx;
33                }
34            });
35            
36            // Habilitar/deshabilitar botones de dirección
37            if (btnPrev && btnNext) {
38                btnPrev.disabled = activeIdx === 0;
39                
40                // Si llegamos al final, el botón NEXT NO se deshabilita si tiene link
41                const hitEnd = (scrollContainer.scrollLeft + scrollContainer.clientWidth) >= (scrollContainer.scrollWidth - 10);
42                const hasLink = btnNext.dataset.link && btnNext.dataset.link !== '';
43                
44                if (hitEnd && hasLink) {
45                    btnNext.disabled = false;
46                    btnNext.classList.add('is-cta');
47                } else {
48                    btnNext.disabled = hitEnd;
49                    btnNext.classList.remove('is-cta');
50                }
51            }
52
53            // Sincronizar classes de los dots
54            dots.forEach((dot, idx) => {
55                if(idx === activeIdx) {
56                    dot.classList.add('is-active');
57                } else {
58                    dot.classList.remove('is-active');
59                }
60            });
61        };
62
63        // Escuchar el evento scroll usando rAF para óptimo rendimiento sin afectar batería
64        let isScrolling;
65        scrollContainer.addEventListener('scroll', () => {
66            if (isScrolling) cancelAnimationFrame(isScrolling);
67            isScrolling = requestAnimationFrame(updateControls);
68        }, { passive: true });
69        
70        // --- 3. Arrow Navigation ---
71        if (btnPrev && btnNext) {
72            btnPrev.addEventListener('click', () => {
73                // Cálculo dinámico para mayor precisión
74                const cardWidth = cards[0].offsetWidth + parseInt(getComputedStyle(scrollContainer).gap || 0);
75                scrollContainer.scrollBy({ left: -cardWidth, behavior: 'smooth' });
76            });
77            
78            btnNext.addEventListener('click', () => {
79                const cardWidth = cards[0].offsetWidth + parseInt(getComputedStyle(scrollContainer).gap || 0);
80                const hitEnd = (scrollContainer.scrollLeft + scrollContainer.clientWidth) >= (scrollContainer.scrollWidth - 10);
81                const link = btnNext.dataset.link;
82                
83                if (hitEnd && link) {
84                    // Si estamos al final y hay link, navegamos
85                    window.location.href = link;
86                } else {
87                    // Si no, scrolleamos exactamente una tarjeta
88                    scrollContainer.scrollBy({ left: cardWidth, behavior: 'smooth' });
89                }
90            });
91        }
92        
93        // --- 4. Dot Navigation ---
94        dots.forEach((dot, idx) => {
95            dot.addEventListener('click', () => {
96                const targetCard = cards[idx];
97                scrollContainer.scrollTo({
98                    left: targetCard.offsetLeft - scrollContainer.offsetLeft,
99                    behavior: 'smooth'
100                });
101            });
102        });
103        
104        // Ejecución Inicial para activar el state del dot número 1
105        updateControls();
106    });
107});

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.