PageSourceSearch

https://www.accademiamoda.it/wp-content/themes/iuad-theme/src/js/custom/dipartimenti-mobile.js?ver=1.0.0

js accademiamoda.it collected 2026-10-04 13:23:52 UTC 7,427 bytes, 172 lines download raw bytes

1/**
2 * Dipartimenti Block Mobile - Scroll Animation & Interaction
3 * SEQUENZA:
4 * 1. Testo "Dipartimenti" sale dal basso
5 * 2. Testo si blocca in alto (pin)
6 * 3. Durante il pin, le card appaiono dal basso
7 * 4. Click su card: naviga direttamente al link
8 */
9(function() {
10    'use strict';
11
12    document.addEventListener('DOMContentLoaded', () => {
13        const dipartimentiBlockMobile = document.querySelector('.dipartimenti-block-mobile');
14        
15        if (!dipartimentiBlockMobile) return;
16        
17        // Verifica che l'elemento sia visibile (non nascosto da display:none)
18        const isVisible = window.getComputedStyle(dipartimentiBlockMobile).display !== 'none';
19        if (!isVisible) {
20            // Se non è visibile, aspetta che diventi visibile (per template responsive dinamici)
21            const checkVisibility = () => {
22                const checkVisible = window.getComputedStyle(dipartimentiBlockMobile).display !== 'none';
23                if (checkVisible) {
24                    initDipartimentiMobileAnimation();
25                } else {
26                    setTimeout(checkVisibility, 100);
27                }
28            };
29            checkVisibility();
30            return;
31        }
32
33        initDipartimentiMobileAnimation();
34    });
35    
36    function initDipartimentiMobileAnimation() {
37        const dipartimentiBlockMobile = document.querySelector('.dipartimenti-block-mobile');
38        if (!dipartimentiBlockMobile) return;
39        
40        // Verifica nuovamente la visibilità prima di inizializzare
41        if (window.getComputedStyle(dipartimentiBlockMobile).display === 'none') {
42            return;
43        }
44
45        const titleWrapper = dipartimentiBlockMobile.querySelector('.dipartimenti-block-mobile__title-wrapper');
46        const cardsWrapper = dipartimentiBlockMobile.querySelector('.dipartimenti-block-mobile__cards');
47        const cards = dipartimentiBlockMobile.querySelectorAll('.dipartimento-card-mobile');
48        
49        if (!titleWrapper || !cardsWrapper || cards.length === 0) return;
50
51        // Registra ScrollTrigger plugin
52        gsap.registerPlugin(ScrollTrigger);
53
54        // === SETUP: Calcola le posizioni ===
55        const viewportHeight = window.innerHeight;
56        const cardHeight = 305; // Altezza fissa di ogni card
57        const gapBetweenCards = 10; // Gap tra le card
58        const totalCardSpace = cardHeight + gapBetweenCards; // 315px per card
59        const numCards = cards.length;
60        
61        // Calcolo altezza totale delle card impilate
62        // 4 card = (305 * 4) + (10 * 3) = 1220 + 30 = 1250px
63        const totalCardsHeight = (cardHeight * numCards) + (gapBetweenCards * (numCards - 1));
64        
65        // Verifica se siamo su mobile
66        const isMobile = window.innerWidth <= 768;
67        const container = dipartimentiBlockMobile.querySelector('.dipartimenti-block-mobile__container');
68        
69        // === STATO INIZIALE ===
70        // Testo: posizionato direttamente nel contenitore (nessuna animazione di ingresso)
71        gsap.set(titleWrapper, { 
72            y: 20,
73            opacity: 1
74        });
75
76        // Il wrapper delle card parte sotto il container
77        // Le card dentro sono in layout normale (relative) quindi mantengono i gap automaticamente
78        gsap.set(cardsWrapper, { 
79            y: viewportHeight,
80            opacity: 1
81        });
82
83        if (isMobile) {
84            // === ANIMAZIONE MOBILE: Sezione si blocca (pin) e card salgono con velocità pari allo scroll ===
85            const cardsWrapperTargetY = 20;
86            const cardsWrapperTravel = viewportHeight - cardsWrapperTargetY;
87            
88            // Calcola la distanza di scroll necessaria per far salire tutte le card
89            const scrollDistance = viewportHeight * 1.5; // Distanza di scroll per completare l'animazione
90            
91            // Timeline principale con pin per bloccare la sezione e tenere fissa la scritta "Dipartimenti"
92            const mainTimeline = gsap.timeline({
93                scrollTrigger: {
94                    trigger: dipartimentiBlockMobile,
95                    start: 'top top', // Inizia quando il top del blocco arriva al top del viewport
96                    end: `+=${scrollDistance}px`, // Pin dura per tutta la distanza di scroll necessaria
97                    pin: true, // Blocca la sezione per tenere fissa la scritta
98                    scrub: true, // Segue immediatamente lo scroll senza lag (true = 0 lag)
99                    anticipatePin: 1,
100                    // markers: true, // Debug
101                    onLeave: () => {
102                        // Quando il pin finisce, permetti overflow normale
103                        if (container) container.classList.add('animation-complete');
104                    },
105                    onEnterBack: () => {
106                        // Quando torni indietro, riattiva overflow hidden
107                        if (container) container.classList.remove('animation-complete');
108                    }
109                }
110            });
111            
112            // Animazione delle card che sale in modo continuo e reattivo
113            // Le card iniziano a salire immediatamente quando inizia il pin
114            mainTimeline.to(cardsWrapper, {
115                y: `-=${cardsWrapperTravel}`,
116                ease: 'none', // Nessun easing per seguire perfettamente lo scroll
117                duration: 1, // Durata della timeline (1 = 100% della durata del pin)
118            }, 0); // Inizia immediatamente (time 0) quando inizia il pin
119        } else {
120            // === ANIMAZIONE DESKTOP: Mantiene il comportamento originale con pin ===
121            const pinDuration = `+=${(numCards * 30) + 30}%`;
122            
123            const mainTimeline = gsap.timeline({
124                scrollTrigger: {
125                    trigger: dipartimentiBlockMobile,
126                    start: 'top top',
127                    end: pinDuration,
128                    pin: true,
129                    scrub: 1,
130                    anticipatePin: 1,
131                    // markers: true, // Debug
132                    onLeave: () => {
133                        if (container) container.classList.add('animation-complete');
134                    },
135                    onEnterBack: () => {
136                        if (container) container.classList.remove('animation-complete');
137                    }
138                }
139            });
140
141            const cardsWrapperTargetY = 20;
142            const cardsWrapperTravel = viewportHeight - cardsWrapperTargetY;
143            const animationDuration = 0.1;
144            
145            mainTimeline.to(cardsWrapper, 
146                {
147                    y: `-=${cardsWrapperTravel}`,
148                    duration: animationDuration,
149                    ease: 'none',
150                },
151                0
152            );
153        }
154        
155        // Dopo il pin (onLeave callback), overflow diventa visible
156        // Le card rimanenti possono essere viste scrollando normalmente la pagina
157
158        // === INTERAZIONE: Click naviga direttamente al link ===
159        cards.forEach((card) => {
160            const href = card.dataset.href;
161            if (href) {
162                card.addEventListener('click', () => {
163                    window.location.href = href;
164                });
165            }
166        });
167
168        //console.log('Dipartimenti block mobile initialized:', cards.length, 'cards');
169    }
170
171})();
172

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.