PageSourceSearch

https://fpt.vn/frontend_layout_2025_vibecode/assets/plugin/swiper/categories-swiper.js?v=v1.50.16

js fpt.vn collected 2026-09-24 09:39:08 UTC 4,075 bytes, 140 lines download raw bytes

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.