1document.addEventListener('DOMContentLoaded', function () { 2 3 const breakpoints = { 4 tablet: 768, 5 desktop: 1024 6 }; 7 8 const carousels = document.querySelectorAll('.zenite-carousel'); 9 10 carousels.forEach(function (carousel) { 11 12 const track = carousel.querySelector('.zc-track'); 13 const btnNext = carousel.querySelector('.zc-next'); 14 const btnPrev = carousel.querySelector('.zc-prev'); 15 16 let originalSlides = Array.from(track.children); 17 if (originalSlides.length <= 1) return; 18 19 const slidesConfig = carousel.dataset.slides.split('|').map(n => parseInt(n, 10)); 20 21 let slidesPerView = 1; 22 let index = 0; 23 let autoplay = parseInt(carousel.dataset.autoplay, 10) || 0; 24 let interval = null; 25 26 let slides = []; 27 let isDragging = false; 28 let startX = 0; 29 let isHovered = false; 30 let isVisible = true; 31 32 function getSlidesPerView() { 33 const w = window.innerWidth; 34 35 if (w >= breakpoints.desktop) return slidesConfig[2] || slidesConfig[1] || slidesConfig[0]; 36 if (w >= breakpoints.tablet) return slidesConfig[1] || slidesConfig[0]; 37 return slidesConfig[0]; 38 } 39 40 function setup() { 41 track.innerHTML = ''; 42 originalSlides.forEach(el => track.appendChild(el)); 43 44 slidesPerView = getSlidesPerView(); 45 const totalOriginal = originalSlides.length; 46 47 const clonesBefore = []; 48 const clonesAfter = []; 49 50 for (let i = 0; i < slidesPerView; i++) { 51 clonesBefore.push(originalSlides[totalOriginal - 1 - i].cloneNode(true)); 52 clonesAfter.push(originalSlides[i].cloneNode(true)); 53 } 54 55 clonesBefore.reverse().forEach(clone => track.insertBefore(clone, track.firstChild)); 56 clonesAfter.forEach(clone => track.appendChild(clone)); 57 58 slides = Array.from(track.children); 59 index = slidesPerView; 60 61 updateSlideWidths(); 62 jumpTo(index, false); 63 64 // ð¥ preload inicial 65 preloadSlide(index + 1); 66 } 67 68 function updateSlideWidths() { 69 const width = 100 / slidesPerView;
70 slides.forEach(slide => slide.style.width = width + '%'); 71 } 72 73 function setTransition(enable = true) { 74 track.style.transition = enable 75 ? 'transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1)' 76 : 'none'; 77 } 78 79 function moveTo(i) { 80 index = i; 81 setTransition(true); 82 track.style.transform = `translateX(-${(100 / slidesPerView) * index}%)`; 83 } 84 85 function jumpTo(i, animate = false) { 86 index = i; 87 setTransition(animate); 88 track.style.transform = `translateX(-${(100 / slidesPerView) * index}%)`; 89 } 90 91 function next() { 92 preloadSlide(index + 1); 93 moveTo(index + 1); 94 } 95 96 function prev() { 97 preloadSlide(index - 1); 98 moveTo(index - 1); 99 } 100 101 track.addEventListener('transitionend', function () { 102 const totalOriginal = originalSlides.length; 103 104 if (index >= totalOriginal + slidesPerView) { 105 jumpTo(slidesPerView); 106 } 107 108 if (index < slidesPerView) { 109 jumpTo(totalOriginal + slidesPerView - 1); 110 } 111 }); 112 113 // ð¥ PRELOAD 114 function preloadSlide(i) { 115 if (!slides[i]) return; 116 117 const img = slides[i].querySelector('img'); 118 if (!img) return; 119 120 const src = img.getAttribute('src'); 121 if (!src) return; 122 123 const preloader = new Image(); 124 preloader.src = src; 125 } 126 127 function canAutoplay() { 128 return autoplay > 0 && !isHovered && isVisible; 129 } 130 131 function startAutoplay() { 132 stopAutoplay(); 133 if (canAutoplay()) { 134 interval = setInterval(next, autoplay); 135 } 136 } 137 138 function stopAutoplay() { 139 if (interval) clearInterval(interval); 140 } 141 142 function restartAutoplayDelayed() { 143 stopAutoplay(); 144 if (autoplay > 0) { 145 setTimeout(startAutoplay, 4000); 146 } 147 } 148 149 function getX(e) { 150 return e.type.includes('mouse') ? e.pageX : e.touches[0].clientX; 151 } 152 153 function dragStart(e) { 154 isDragging = true; 155 startX = getX(e); 156 stopAutoplay(); 157 setTransition(false); 158 } 159 160 function dragMove(e) { 161 if (!isDragging) return; 162 163 const currentX = getX(e); 164 const diff = currentX - startX; 165 166 track.style.transform = `translateX(calc(-${(100 / slidesPerView) * index}% + ${diff}px))`; 167 } 168 169 function dragEnd(e) { 170 if (!isDragging) return; 171 172 isDragging = false; 173 174 const endX = getX(e); 175 const diff = endX - startX; 176 const threshold = carousel.offsetWidth * 0.1; 177 178 if (diff > threshold) prev(); 179 else if (diff < -threshold) next(); 180 else moveTo(index); 181 182 restartAutoplayDelayed(); 183 } 184 185 // swipe 186 track.addEventListener('mousedown', dragStart); 187 window.addEventListener('mousemove', dragMove); 188 window.addEventListener('mouseup', dragEnd); 189 190 track.addEventListener('touchstart', dragStart, { passive: true }); 191 track.addEventListener('touchmove', dragMove, { passive: true }); 192 track.addEventListener('touchend', dragEnd); 193 194 // botões 195 if (btnNext) btnNext.addEventListener('click', () => { next(); restartAutoplayDelayed(); }); 196 if (btnPrev) btnPrev.addEventListener('click', () => { prev(); restartAutoplayDelayed(); }); 197 198 // hover 199 carousel.addEventListener('mouseenter', () => { 200 isHovered = true; 201 stopAutoplay(); 202 }); 203 204 carousel.addEventListener('mouseleave', () => { 205 isHovered = false; 206 startAutoplay(); 207 }); 208 209 // viewport 210 const observer = new IntersectionObserver(entries => {
211 entries.forEach(entry => { 212 isVisible = entry.isIntersecting; 213 if (isVisible) startAutoplay(); 214 else stopAutoplay(); 215 }); 216 }, { threshold: 0.3 }); 217 218 observer.observe(carousel); 219 220 // resize 221 let resizeTimeout; 222 window.addEventListener('resize', function () { 223 clearTimeout(resizeTimeout); 224 resizeTimeout = setTimeout(setup, 200); 225 }); 226 227 // init 228 setup(); 229 startAutoplay(); 230 231 }); 232 233});
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.