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.