1const transformationTiles = document.querySelectorAll('.transformation-card'); 2const transformationDots = document.querySelectorAll('.transformation-dot'); 3const carouselTrack = document.querySelector('.carousel-track'); 4let currentIndex = 0; 5let autoPlayInterval; 6let isHovering = false; 7 8/* âââ Helper: detect mobile âââ */ 9function isMobile() { 10 return window.matchMedia('(max-width: 768px)').matches; 11} 12 13/* âââ Desktop: fade-based carousel âââ */ 14function showTile(index) { 15 transformationTiles.forEach((tile, i) => { 16 tile.classList.remove('active'); 17 if (i === index) tile.classList.add('active'); 18 }); 19 20 transformationDots.forEach((dot, i) => { 21 dot.classList.remove('active'); 22 if (i === index) dot.classList.add('active'); 23 }); 24 25 currentIndex = index; 26} 27 28function nextTile() { 29 const next = (currentIndex + 1) % transformationTiles.length; 30 showTile(next); 31} 32 33function startAutoPlay() { 34 autoPlayInterval = setInterval(() => { 35 if (!isHovering) nextTile(); 36 }, 5000); 37} 38 39function stopAutoPlay() { 40 clearInterval(autoPlayInterval); 41} 42 43/* âââ Mobile: scroll-based carousel âââ */ 44function syncDotsToScroll() { 45 if (!isMobile()) return; 46 47 const trackRect = carouselTrack.getBoundingClientRect(); 48 let closestIndex = 0; 49 let closestDist = Infinity; 50 51 transformationTiles.forEach((tile, i) => { 52 const tileRect = tile.getBoundingClientRect(); 53 const tileCenter = tileRect.left + tileRect.width / 2; 54 const trackCenter = trackRect.left + trackRect.width / 2; 55 const dist = Math.abs(tileCenter - trackCenter); 56 if (dist < closestDist) { 57 closestDist = dist; 58 closestIndex = i; 59 } 60 }); 61 62 transformationDots.forEach((dot, i) => { 63 dot.classList.toggle('active', i === closestIndex); 64 }); 65 66 currentIndex = closestIndex; 67} 68 69function scrollToTile(index) { 70 if (!isMobile()) return; 71 transformationTiles[index].scrollIntoView({ 72 behavior: 'smooth', 73 block: 'nearest', 74 inline: 'center', 75 }); 76} 77 78/* âââ Dot click âââ */ 79transformationDots.forEach((dot, index) => { 80 dot.addEventListener('click', () => { 81 if (isMobile()) { 82 scrollToTile(index); 83 } else { 84 stopAutoPlay(); 85 showTile(index); 86 startAutoPlay(); 87 } 88 }); 89}); 90 91/* âââ Desktop tile hover / click âââ */ 92transformationTiles.forEach(tile => { 93 tile.addEventListener('mouseenter', () => { 94 if (isMobile()) return; 95 isHovering = true; 96 tile.classList.add('clickable'); 97 }); 98 99 tile.addEventListener('mouseleave', () => { 100 if (isMobile()) return; 101 isHovering = false; 102 tile.classList.remove('clickable'); 103 }); 104 105 tile.addEventListener('click', () => { 106 if (!isMobile() && tile.classList.contains('active')) { 107 console.log('Tile clicked:', tile.querySelector('h2').textContent); 108 alert('Tile clicked: ' + tile.querySelector('h2').textContent); 109 } 110 }); 111}); 112 113/* âââ Mobile: sync dots on scroll âââ */ 114carouselTrack.addEventListener('scroll', syncDotsToScroll, { passive: true }); 115 116/* âââ Init âââ */ 117function init() { 118 if (isMobile()) { 119 stopAutoPlay(); 120 // Ensure all cards are visible (CSS handles this, but reset any JS state) 121 transformationTiles.forEach(tile => tile.classList.remove('active')); 122 syncDotsToScroll(); 123 } else { 124 showTile(0); 125 startAutoPlay(); 126 } 127} 128 129/* âââ Re-init on resize crossing the breakpoint âââ */ 130let wasMobile = isMobile(); 131window.addEventListener('resize', () => { 132 const nowMobile = isMobile(); 133 if (nowMobile !== wasMobile) { 134 wasMobile = nowMobile; 135 stopAutoPlay(); 136 init(); 137 } 138}); 139 140/* âââ Page visibility âââ */ 141document.addEventListener('visibilitychange', () => { 142 if (isMobile()) return; 143 if (document.hidden) stopAutoPlay(); 144 else startAutoPlay(); 145}); 146 147init();
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.