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.