PageSourceSearch

https://topropebelts.com/wp-content/themes/trb/inc/js/product-gallery.js?ver=406247

js topropebelts.com collected 2026-10-03 00:09:43 UTC 5,002 bytes, 170 lines download raw bytes

1/**
2 * Product Gallery Swiper Initialization
3 * Creates a main gallery swiper with thumbnail navigation
4 */
5
6(function ($) {
7  'use strict';
8
9  // Initialize product gallery when document is ready
10  $(document).ready(function () {
11    // Small delay to ensure layout is fully calculated
12    const timeout = setTimeout(function () {
13      clearTimeout(timeout);
14      initProductGallery();
15    }, 100);
16  });
17
18  // Also initialize on window load to ensure all assets are loaded
19  $(window).on('load', function () {
20    const timeout = setTimeout(function () {
21      clearTimeout(timeout);
22      initProductGallery();
23    }, 50);
24  });
25
26  // Reinitialize on window resize to handle layout changes
27  let resizeTimeout;
28  $(window).on('resize', function () {
29    clearTimeout(resizeTimeout);
30    resizeTimeout = setTimeout(function () {
31      // Destroy existing swipers and reinitialize
32      destroyProductGalleries();
33      const timeout = setTimeout(function () {
34        clearTimeout(timeout);
35        initProductGallery();
36      }, 100);
37    }, 250);
38  });
39
40  function destroyProductGalleries() {
41    const galleryContainers = document.querySelectorAll('.product-images-section.gallery-initialized');
42
43    galleryContainers.forEach(function (container) {
44      // Find and destroy any existing Swiper instances
45      const mainSwiperEl = container.querySelector('.product-gallery-swiper');
46      const thumbsSwiperEl = container.querySelector('.product-thumbnails-swiper');
47
48      if (mainSwiperEl && mainSwiperEl.swiper) {
49        mainSwiperEl.swiper.destroy(true, true);
50      }
51      if (thumbsSwiperEl && thumbsSwiperEl.swiper) {
52        thumbsSwiperEl.swiper.destroy(true, true);
53      }
54
55      container.classList.remove('gallery-initialized');
56    });
57  }
58
59  // Also initialize on dynamic content load (for AJAX-loaded content)
60  $(document).on('content-loaded', function () {
61    initProductGallery();
62  });
63
64  function initProductGallery() {
65    // Only initialize if Swiper is available and we have gallery elements
66    if (typeof Swiper === 'undefined') {
67      console.warn('SwiperJS not loaded, product gallery will not function');
68      return;
69    }
70
71    const galleryContainers = document.querySelectorAll('.product-images-section');
72
73    galleryContainers.forEach(function (container) {
74      // Check if already initialized
75      if (container.classList.contains('gallery-initialized')) {
76        return;
77      }
78
79      const mainSwiperEl = container.querySelector('.product-gallery-swiper');
80      const thumbsSwiperEl = container.querySelector('.product-thumbnails-swiper');
81
82      if (!mainSwiperEl || !thumbsSwiperEl) {
83        return;
84      }
85
86      // Initialize thumbnail swiper first
87      const thumbsSwiper = new Swiper(thumbsSwiperEl, {
88        spaceBetween: 10,
89        slidesPerView: 'auto',
90        freeMode: true,
91        watchSlidesProgress: true,
92        centeredSlides: false,
93        slideToClickedSlide: true,
94        loop: true,
95        breakpoints: {
96          768: {
97            slidesPerView: 4,
98            spaceBetween: 10
99          },
100          480: {
101            slidesPerView: 3,
102            spaceBetween: 8
103          }
104        }
105      });
106
107      // Initialize main gallery swiper
108      const mainSwiper = new Swiper(mainSwiperEl, {
109        spaceBetween: 10,
110        navigation: {
111          nextEl: '.swiper-button-next',
112          prevEl: '.swiper-button-prev',
113        },
114        thumbs: {
115          swiper: thumbsSwiper,
116        },
117        effect: 'fade',
118        fadeEffect: {
119          crossFade: true
120        },
121        autoplay: {
122          delay: 5000,
123          disableOnInteraction: true,
124        },
125        loop: true,
126        grabCursor: true,
127        keyboard: {
128          enabled: true,
129        },
130        // Disable autoplay on mobile for better UX
131        breakpoints: {
132          768: {
133            autoplay: false
134          }
135        }
136      });
137
138      // Mark as initialized
139      container.classList.add('gallery-initialized');
140
141      // Add click handler for thumbnails to update main swiper
142      thumbsSwiper.slides.forEach(function (slide, index) {
143        slide.addEventListener('click', function () {
144          mainSwiper.slideTo(index);
145        });
146      });
147
148      // Optional: Add zoom functionality on click
149      mainSwiper.slides.forEach(function (slide) {
150        const img = slide.querySelector('.product-gallery-image');
151        if (img) {
152          img.addEventListener('click', function () {
153            // Simple zoom toggle (you can enhance this with a modal)
154            if (img.style.transform === 'scale(1.2)') {
155              img.style.transform = 'scale(1)';
156              img.style.cursor = 'zoom-in';
157            } else {
158              img.style.transform = 'scale(1.2)';
159              img.style.cursor = 'zoom-out';
160            }
161          });
162        }
163      });
164    });
165  }
166
167  // Expose function globally for manual initialization if needed
168  window.initProductGallery = initProductGallery;
169
170})(jQuery);

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.