1/* =========================================== 2 SWIPER - PRODUCT CATEGORIES 3 Desktop (â¥1024px): Show 2 large cards 4 Mobile/Tablet (â¤1023px): Enable drag carousel 5 Categories sá» dụng Swiper thuần, KHÃNG dùng Embla 6 =========================================== */ 7 8document.addEventListener('DOMContentLoaded', function() { 9 const categoriesSwipers = document.querySelectorAll('.swiper-categories'); 10 let swiperInstances = []; 11 let lastWidth = window.innerWidth; 12 13 function prepareStructure(swiperEl) { 14 // Categories chá» dùng .swiper-wrapper, KHÃNG dùng .embla-package__container 15 let wrapper = swiperEl.querySelector('.swiper-wrapper'); 16 17 if (!wrapper) { 18 // Nếu HTML Äang dùng .embla-package__container, Äá»i thà nh .swiper-wrapper 19 const emblaContainer = swiperEl.querySelector('.embla-package__container'); 20 if (emblaContainer) { 21 emblaContainer.className = 'swiper-wrapper'; 22 wrapper = emblaContainer; 23 console.log('Categories: Converted embla-package__container to swiper-wrapper'); 24 } 25 } 26 27 return wrapper; 28 } 29 30 function initSwipers() { 31 categoriesSwipers.forEach(function(swiperEl) { 32 // Prepare structure 33 const wrapper = prepareStructure(swiperEl); 34 35 if (!wrapper) { 36 console.error('Categories Swiper: No wrapper found'); 37 return; 38 } 39 40 try { 41 // Config varies by screen size 42 const isDesktop = window.innerWidth >= 1024; 43 44 const swiper = new Swiper(swiperEl, { 45 slidesPerView: 'auto', 46 47 // Enable drag/swipe 48 freeMode: !isDesktop, // Desktop: normal swipe, Mobile: free mode 49 grabCursor: true, 50 51 // Smooth scrolling 52 mousewheel: { 53 forceToAxis: true, 54 }, 55 56 // Touch gestures 57 touchRatio: 1, 58 touchAngle: 45, 59 60 // Resistance at edges 61 resistance: true, 62 resistanceRatio: 0.85, 63 64 speed: 400, 65 66 // Loop for desktop (2 cards per view) 67 loop: isDesktop && wrapper.children.length > 2, 68
69 // Breakpoints for different sizes 70 breakpoints: { 71 320: { 72 spaceBetween: 16, 73 }, 74 480: { 75 spaceBetween: 16, 76 }, 77 768: { 78 spaceBetween: 16, 79 }, 80 820: { 81 // slidesPerView: 4,s 82 spaceBetween: 16, 83 }, 84 1024: { 85 slidesPerView: 6, 86 spaceBetween: 18, 87 freeMode: false, 88 }, 89 1366: { 90 slidesPerView: 6, 91 spaceBetween: 24, 92 freeMode: false, 93 } 94 } 95 }); 96 swiperInstances.push(swiper); 97 // console.log('Categories Swiper: Initialized for ' + (isDesktop ? 'desktop' : 'mobile/tablet')); 98 } catch(e) { 99 console.error('Categories Swiper: Init failed', e); 100 } 101 }); 102 } 103 104 function destroySwipers() { 105 // Destroy swiper instances 106 swiperInstances.forEach(function(swiper) { 107 if (swiper) { 108 try { 109 swiper.destroy(true, true); 110 } catch(e) { 111 console.error('Categories Swiper: Destroy failed', e); 112 } 113 } 114 }); 115 swiperInstances = []; 116 console.log('Categories Swiper: Destroyed'); 117 } 118 119 // Initialize on load 120 setTimeout(initSwipers, 100); // Small delay to ensure DOM is ready 121 122 // Reinitialize when crossing the 1024px breakpoint 123 let resizeTimer; 124 window.addEventListener('resize', function() { 125 clearTimeout(resizeTimer); 126 resizeTimer = setTimeout(function() { 127 const currentWidth = window.innerWidth; 128 129 // Reinit if crossing the breakpoint to change config 130 if ((lastWidth > 1023 && currentWidth <= 1023) || 131 (lastWidth <= 1023 && currentWidth > 1023)) { 132 console.log('Categories Swiper: Breakpoint crossed, reinitializing...'); 133 destroySwipers(); 134 initSwipers(); 135 } 136 137 lastWidth = currentWidth; 138 }, 250); 139 }); 140});
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.