PageSourceSearch

https://caffe-toninho-v4.vercel.app/js/product-slider.js?v=5

js caffe-toninho-v4.vercel.app collected 2026-10-03 06:20:33 UTC 5,601 bytes, 148 lines download raw bytes

1/* Slider collezione nelle pagine prodotto: slider custom, volutamente scollegato
2   dal modulo slider di Webflow (il markup non usa piu le classi w-slider*,
3   cosi il bundle Webflow non lo inizializza e non va in conflitto con doppie
4   animazioni). Lo spostamento usa le posizioni reali delle slide (offsetLeft),
5   non percentuali fisse: le card hanno larghezza fluida (23,4% desktop,
6   48,6% tablet, 100% mobile) e un translate percentuale sfalsa la
7   visualizzazione. */
8(function () {
9  'use strict';
10
11  document.addEventListener('DOMContentLoaded', function () {
12    var slider = document.querySelector('.products-slider');
13    if (!slider) return;
14    var mask = slider.querySelector('.slider-mask');
15    if (!mask) return;
16    var slides = Array.prototype.slice.call(mask.querySelectorAll('.product-slide'));
17    /* Le frecce sono sorelle dello slider (figlie del container), non figlie
18       dirette: cerca prima dentro, poi nel contenitore genitore, poi in pagina. */
19    var scope = slider.parentElement || document;
20    var left = slider.querySelector('.left-arrow')
21      || scope.querySelector('.left-arrow')
22      || document.querySelector('.products-slider ~ .left-arrow, .product-left-arrow');
23    var right = slider.querySelector('.right-arrow')
24      || scope.querySelector('.right-arrow')
25      || document.querySelector('.products-slider ~ .right-arrow, .product-arrow');
26    if (!slides.length || !left || !right) return;
27
28    /* indice della slide allineata a sinistra */
29    var index = 0;
30    var TRANSITION = 'transform 1.2s cubic-bezier(0.45, 0, 0.25, 1)';
31
32    /* Su mobile la collezione e una lista verticale completa (frecce nascoste
33       via CSS): niente translate, niente swipe, niente riallineamenti. */
34    var mobileQuery = window.matchMedia ? window.matchMedia('(max-width: 767px)') : null;
35    function isMobileList() {
36      return !!(mobileQuery && mobileQuery.matches);
37    }
38    function resetMobile() {
39      mask.style.transition = 'none';
40      mask.style.transform = 'none';
41      index = 0;
42      /* Cintura + bretelle: nasconde le frecce anche se il CSS fosse vecchio */
43      left.style.display = 'none';
44      right.style.display = 'none';
45    }
46    function restoreDesktop() {
47      left.style.display = '';
48      right.style.display = '';
49    }
50
51    mask.style.transition = TRANSITION;
52    if (!mask.style.transform) mask.style.transform = 'translateX(0px)';
53
54    function slideWidth() {
55      return (slides[0] && slides[0].offsetWidth) || slider.clientWidth;
56    }
57
58    /* quante card entrano nel contenitore */
59    function pageSize() {
60      var w = slider.clientWidth;
61      var sw = slideWidth() || w;
62      return Math.max(1, Math.floor((w + 1) / sw));
63    }
64
65    /* ultima posizione senza lasciare buchi vuoti a destra */
66    function maxIndex() {
67      return Math.max(0, slides.length - pageSize());
68    }
69
70    function goTo(i) {
71      if (isMobileList()) { resetMobile(); return; }
72      index = Math.max(0, Math.min(maxIndex(), i));
73      mask.style.transform = 'translateX(-' + slides[index].offsetLeft + 'px)';
74    }
75
76    right.addEventListener('click', function () {
77      if (isMobileList()) return;
78      if (index >= maxIndex()) { goTo(0); return; }
79      goTo(index + pageSize());
80    });
81
82    left.addEventListener('click', function () {
83      if (isMobileList()) return;
84      if (index <= 0) { goTo(maxIndex()); return; }
85      goTo(index - pageSize());
86    });
87
88    /* Swipe touch (mobile): segue il dito e scatta di una pagina oltre soglia */
89    var startX = null;
90    var baseX = 0;
91    var deltaX = 0;
92
93    mask.addEventListener('touchstart', function (e) {
94      if (isMobileList() || e.touches.length !== 1) return;
95      startX = e.touches[0].clientX;
96      baseX = slides[index] ? slides[index].offsetLeft : 0;
97      deltaX = 0;
98      mask.style.transition = 'none';
99    }, { passive: true });
100
101    mask.addEventListener('touchmove', function (e) {
102      if (isMobileList() || startX === null) return;
103      deltaX = e.touches[0].clientX - startX;
104      mask.style.transform = 'translateX(' + (-baseX + deltaX) + 'px)';
105    }, { passive: true });
106
107    mask.addEventListener('touchend', function () {
108      if (isMobileList() || startX === null) return;
109      startX = null;
110      mask.style.transition = TRANSITION;
111      var threshold = Math.min(80, slideWidth() * 0.25);
112      if (deltaX <= -threshold) {
113        if (index >= maxIndex()) { goTo(0); } else { goTo(index + pageSize()); }
114      } else if (deltaX >= threshold) {
115        if (index <= 0) { goTo(maxIndex()); } else { goTo(index - pageSize()); }
116      } else {
117        goTo(index);
118      }
119    });
120
121    /* Riallinea su resize (le larghezze delle card cambiano col breakpoint) */
122    var rt = null;
123    window.addEventListener('resize', function () {
124      clearTimeout(rt);
125      rt = setTimeout(function () {
126        if (isMobileList()) { resetMobile(); return; }
127        /* ricalcola mantenendo la slide corrente allineata */
128        mask.style.transition = 'none';
129        goTo(index);
130        setTimeout(function () {
131          mask.style.transition = TRANSITION;
132        }, 50);
133      }, 150);
134    });
135
136    if (mobileQuery) {
137      var onBpChange = function () {
138        if (isMobileList()) { resetMobile(); return; }
139        restoreDesktop();
140        mask.style.transition = TRANSITION;
141        goTo(index);
142      };
143      if (mobileQuery.addEventListener) mobileQuery.addEventListener('change', onBpChange);
144      else if (mobileQuery.addListener) mobileQuery.addListener(onBpChange);
145    }
146    if (isMobileList()) resetMobile();
147  });
148})();

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.