PageSourceSearch

https://shop.picklebums.com/wp-content/plugins/kadence-shop-kit/li…/js/kadence-product-gallery.js?ver=3.0.8

js picklebums.com collected 2026-09-24 10:28:35 UTC 36,571 bytes, 1,181 lines download raw bytes

1/*global jQuery*/
2/*global kadence_pg*/
3/*global Splide*/
4/*global GLightbox*/
5jQuery(function ($) {
6	var KadenceProductGalleryisMobile = {
7		Android: function () {
8			return navigator.userAgent.match(/Android/i);
9		},
10		BlackBerry: function () {
11			return navigator.userAgent.match(/BlackBerry/i);
12		},
13		iOS: function () {
14			return navigator.userAgent.match(/iPhone|iPad|iPod/i);
15		},
16		Opera: function () {
17			return navigator.userAgent.match(/Opera Mini/i);
18		},
19		Windows: function () {
20			return navigator.userAgent.match(/IEMobile/i);
21		},
22		any: function () {
23			return (
24				KadenceProductGalleryisMobile.Android() ||
25				KadenceProductGalleryisMobile.BlackBerry() ||
26				KadenceProductGalleryisMobile.iOS() ||
27				KadenceProductGalleryisMobile.Opera() ||
28				KadenceProductGalleryisMobile.Windows()
29			);
30		},
31	};
32	/**
33	 * Product gallery class.
34	 */
35	var KadenceProductGallery = function ($gallery) {
36		const self = this;
37		self.$gallery = $gallery;
38		var splide_speed = $gallery.data("speed"),
39			product_id = $gallery.data("product-id"),
40			splide_animation = $gallery.data("animation"),
41			splide_animation_speed = $gallery.data("animation-speed"),
42			slick_arrows = $gallery.data("arrows"),
43			slick_pagination = $gallery.data("pagination"),
44			layout = $gallery.data("layout"),
45			mdLayout = $gallery.data("md-layout"),
46			smLayout = $gallery.data("sm-layout"),
47			items_count = $gallery.data("gallery-items"),
48			splide_thumbs_show = $gallery.data("thumb-show"),
49			splide_thumbs_tablet_show = $gallery.data("md-thumb-show"),
50			splide_thumbs_mobile_show = $gallery.data("sm-thumb-show"),
51			splide_thumbs_width = $gallery.data("thumb-width"),
52			splide_thumbs_tablet_width = $gallery.data("md-thumb-width"),
53			splide_thumbs_mobile_width = $gallery.data("sm-thumb-width"),
54			splide_thumbs_gap = $gallery.data("thumb-gap"),
55			splide_thumbs_tablet_gap = $gallery.data("md-thumb-gap"),
56			splide_thumbs_mobile_gap = $gallery.data("sm-thumb-gap"),
57			splide_thumbs_center = $gallery.data("thumb-center"),
58			splide_auto = $gallery.data("auto"),
59			splide_auto_height = $gallery.data("auto-height"),
60			visible_captions = $gallery.data("visible-captions"),
61			$zoom = $gallery.data("zoom-active"),
62			$zoom_type = $gallery.data("zoom-type"),
63			splide_thumbs_on_hover = $gallery.data("thumb-hover"),
64			splide_loop = $gallery.data("loop"),
65			maintain_slide_index = $gallery.data("maintain-index") === true,
66			swipe_threshold = $gallery.data("swipe-threshold") || 5,
67			lazyload_mode = $gallery.data("lazyload") || "sequential",
68			thumb_trans_speed = $gallery.data("thumb-trans-speed") || 250,
69			thumb_controls = $gallery.data("thumb-controls"),
70			//$items = $gallery.data('gallery-items'),
71			pauseonhover = false,
72			thumbnails_have_changed = false,
73			sliderDirection = "ltr";
74		var $datathumbs = false;
75		var original_items_count = items_count;
76		self.$galleryThumbnails = $gallery
77			.closest(".ksk-gallery")
78			.find("#pg-thumbnails-" + product_id);
79		self.$galleryExtra = $gallery
80			.closest(".ksk-gallery")
81			.siblings("#pg-extra-" + product_id);
82
83		const lazy_load_mode_map = {
84			'sequential': 'sequential',
85			'nearby': 'nearby',
86			'anticipated': 'sequential',
87			'ondemand': 'nearby',
88		};
89
90		lazyload_mode = lazy_load_mode_map[lazyload_mode] || 'sequential';
91
92		if (self.$galleryExtra.length) {
93			$datathumbs = self.$galleryExtra.data("product_variation_images");
94			if (
95				$datathumbs["is_ajax"] === false &&
96				$datathumbs["has_variation_images"] === false
97			) {
98				$datathumbs = false;
99			}
100		}
101		if ($('html[dir="rtl"]').length) {
102			sliderDirection = "rtl";
103		}
104		if (
105			$zoom &&
106			!KadenceProductGalleryisMobile.any() &&
107			$(window).width() > 790
108		) {
109			pauseonhover = true;
110		}
111		$gallery.addClass("splide-initial");
112		var current_layout = layout;
113		var current_thumb_width = splide_thumbs_width;
114		var current_thumbs_show = splide_thumbs_show;
115		if ($(window).width() < 769) {
116			current_layout = smLayout;
117			current_thumb_width = splide_thumbs_mobile_width;
118			current_thumbs_show = splide_thumbs_mobile_show;
119		} else if ($(window).width() < 1024) {
120			current_layout = mdLayout;
121			current_thumb_width = splide_thumbs_tablet_width;
122			current_thumbs_show = splide_thumbs_tablet_show;
123		}
124		if (kadence_pg.stacked_layouts.includes(current_layout)) {
125			splide_auto = false;
126		}
127		var splideMain = new Splide(self.$gallery[0], {
128			type: splide_animation ? "fade" : "slide",
129			autoplay: splide_auto === true ? true : false,
130			lazyLoad: lazyload_mode,
131			rewind: splide_loop,
132			flickPower: Math.round(600 / swipe_threshold),
133			pagination: slick_pagination ? true : false,
134			paginationDirection: 'ttb',
135			arrows: slick_arrows ? true : false,
136			perPage: 1,
137			pauseOnHover: pauseonhover === false ? false : true,
138			direction: sliderDirection,
139			interval: undefined !== splide_speed ? splide_speed : 7000,
140			speed:
141				undefined !== splide_animation_speed
142					? splide_animation_speed
143					: 400,
144			easing:
145				undefined !== splide_animation_speed &&
146					splide_animation_speed > 1000
147					? "linear"
148					: "cubic-bezier(0.25, 1, 0.5, 1)",
149		});
150		splideMain.on("mounted", function () {
151			$gallery.addClass("kt-product-gal-loaded");
152		});
153		if (
154			splide_auto_height === true &&
155			(current_layout === "above" || current_layout === "below" || current_layout === "slider")
156		) {
157			var updateSlideHeight = (newIndex) => {
158				var slide = splideMain.Components.Slides.getAt(
159					typeof newIndex == "number" ? newIndex : splideMain.index
160				).slide;
161				if (slide && slide.parentElement) {
162					slide.parentElement.style.height =
163						slide.firstChild.offsetHeight + "px";
164				}
165			};
166			splideMain.on("mounted move resize", updateSlideHeight);
167			var updateSlideHeightRefresh = (newIndex) => {
168				var slide = splideMain.Components.Slides.getAt(
169					typeof newIndex == "number" ? newIndex : splideMain.index
170				).slide;
171				if (slide && slide.parentElement && slide.firstChild) {
172					setTimeout(() => {
173						slide.parentElement.style.height =
174							slide?.firstChild?.offsetHeight + "px";
175					}, 100);
176				}
177			};
178			splideMain.on("refresh", updateSlideHeightRefresh);
179		}
180		self.kt_thumb_slideHeight = () => {
181			self.$gallery.css("height", "auto");
182			setTimeout(function () {
183				var imageheight = 0;
184				// The images have a PHP-output inline style="width: Npx" that forces
185				// them to their natural pixel width, so measuring the track height
186				// always returns the natural image height (e.g. 600) regardless of
187				// the container width. Instead, derive the height from the image's
188				// natural aspect ratio and the actual gallery container width.
189				var $img = self.$gallery.find('.splide__slide img').first();
190				if ( $img.length && $img[0].naturalWidth ) {
191					imageheight = Math.round( self.$gallery.width() * $img[0].naturalHeight / $img[0].naturalWidth );
192				}
193				if ( !imageheight ) {
194					// Fallback for before the image has loaded.
195					imageheight = self.$gallery.find(".splide__track").height();
196				}
197				self.$galleryThumbnails.css("height", imageheight);
198				self.$gallery.css("height", imageheight);
199			}, 30);
200		};
201		if (current_layout === "left" || current_layout === "right") {
202			self.kt_thumb_slideHeight();
203			splideMain.on("mounted", function () {
204				setTimeout(function () {
205					self.kt_thumb_slideHeight();
206				}, 100);
207				// naturalWidth is 0 until the image loads, so re-measure once
208				// the first slide image actually finishes loading.
209				var $firstImg = self.$gallery.find('.splide__slide img').first();
210				if ($firstImg.length) {
211					if ($firstImg[0].complete && $firstImg[0].naturalHeight) {
212						self.kt_thumb_slideHeight();
213					} else {
214						$firstImg.one('load', function () {
215							self.kt_thumb_slideHeight();
216						});
217					}
218				}
219			});
220		}
221		self.clear_slide_layout = (
222			the_layout,
223			the_width,
224			the_columns,
225			the_count
226		) => {
227			if (the_layout === "left") {
228				setTimeout(function () {
229					self.$galleryThumbnails.css("width", the_width + "%");
230					self.$galleryThumbnails
231						.find(".thumb-wrapper")
232						.css("maxWidth", "");
233					self.$gallery.css("margin-left", the_width + "%");
234					self.$gallery.css("margin-right", "");
235				}, 30);
236				setTimeout(function () {
237					//this is a backup in case the first timeout is still too early.
238					self.$gallery.css("margin-left", the_width + "%");
239					self.$gallery.css("margin-right", "");
240				}, 300);
241				self.kt_thumb_slideHeight();
242			} else if (the_layout === "right") {
243				setTimeout(function () {
244					self.$galleryThumbnails.css("width", the_width + "%");
245					self.$galleryThumbnails
246						.find(".thumb-wrapper")
247						.css("maxWidth", "");
248					self.$gallery.css("margin-right", the_width + "%");
249					self.$gallery.css("margin-left", "");
250				}, 30);
251				setTimeout(function () {
252					//this is a backup in case the first timeout is still too early.
253					self.$gallery.css("margin-right", the_width + "%");
254					self.$gallery.css("margin-left", "");
255				}, 300);
256				self.kt_thumb_slideHeight();
257			} else {
258				self.$gallery.css("margin-left", "");
259				self.$gallery.css("margin-right", "");
260				self.$gallery.css("height", "");
261				self.$galleryThumbnails.css("height", "");
262				self.$galleryThumbnails.css("width", "");
263				if (the_count < the_columns) {
264					self.$galleryThumbnails
265						.find(".thumb-wrapper")
266						.css(
267							"maxWidth",
268							Math.floor((100 / the_columns) * the_count) + "%"
269						);
270				} else {
271					self.$galleryThumbnails
272						.find(".thumb-wrapper")
273						.css("maxWidth", "none");
274				}
275			}
276		};
277		self.clear_slide_layout(
278			current_layout,
279			current_thumb_width,
280			current_thumbs_show,
281			items_count
282		);
283		if (self.$galleryThumbnails.length) {
284			var thumbnails = new Splide(self.$galleryThumbnails[0], {
285				direction:
286					layout === "left" || layout === "right"
287						? "ttb"
288						: sliderDirection,
289				focus:
290					splide_thumbs_center &&
291						((current_layout !== "left" &&
292							current_layout !== "right") ||
293							(items_count > splide_thumbs_show &&
294								(current_layout === "left" ||
295									current_layout === "right")))
296						? "center"
297						: undefined,
298				height: "100%",
299				perPage:
300					items_count < splide_thumbs_show &&
301						layout !== "left" &&
302						layout !== "right"
303						? items_count
304						: splide_thumbs_show,
305				gap: splide_thumbs_gap,
306				rewind: true,
307				speed: thumb_trans_speed,
308				pagination: false,
309				isNavigation: true,
310				drag: false,
311				arrows: thumb_controls,
312				breakpoints: {
313					767: {
314						direction:
315							smLayout === "left" || smLayout === "right"
316								? "ttb"
317								: sliderDirection,
318						perPage:
319							items_count < splide_thumbs_mobile_show &&
320								smLayout !== "left" &&
321								smLayout !== "right"
322								? items_count
323								: splide_thumbs_mobile_show,
324						gap: splide_thumbs_mobile_gap,
325					},
326					1024: {
327						direction:
328							mdLayout === "left" || mdLayout === "right"
329								? "ttb"
330								: sliderDirection,
331						perPage:
332							items_count < splide_thumbs_tablet_show &&
333								mdLayout !== "left" &&
334								mdLayout !== "right"
335								? items_count
336								: splide_thumbs_tablet_show,
337						gap: splide_thumbs_tablet_gap,
338					},
339				},
340			});
341
342			splideMain.sync(thumbnails);
343			splideMain.mount();
344			thumbnails.mount();
345		} else {
346			splideMain.mount();
347		}
348
349		self.galleryChangeLayout = () => {
350			// Mobile.
351			if ($(window).width() < 769) {
352				self.clear_slide_layout(
353					smLayout,
354					splide_thumbs_mobile_width,
355					splide_thumbs_mobile_show,
356					items_count
357				);
358			} else if ($(window).width() < 1024) {
359				self.clear_slide_layout(
360					mdLayout,
361					splide_thumbs_tablet_width,
362					splide_thumbs_tablet_show,
363					items_count
364				);
365			} else {
366				self.clear_slide_layout(
367					layout,
368					splide_thumbs_width,
369					splide_thumbs_show,
370					items_count
371				);
372			}
373		};
374		var galleryLayoutResizeTimer;
375		$(window).on("resize", function () {
376			clearTimeout(galleryLayoutResizeTimer);
377			galleryLayoutResizeTimer = setTimeout(
378				self.galleryChangeLayout(),
379				100
380			);
381		});
382		self.galleryUpdateThumbHover = () => {
383			var galleryHoverClickTimer;
384			self.$galleryThumbnails.find(".splide__slide").hover(function () {
385				$thumb = $(this);
386				clearTimeout(galleryHoverClickTimer);
387				galleryHoverClickTimer = setTimeout(function () {
388					$thumb.trigger("click");
389				}, 100);
390			});
391		};
392		if (splide_thumbs_on_hover && thumbnails) {
393			self.galleryUpdateThumbHover();
394		}
395
396		self.init_product_zoom = () => {
397			const $activeSlide = self.$gallery.find('.splide__slide.is-active');
398			const $img = $activeSlide.find('img').first();
399			const rawType = kadence_pg.zoom_type || 'window';
400			const type = rawType === 'window' ? 'standard' : rawType;
401			// Use .attr() not .data() — jQuery caches .data() on first read and won't
402			// reflect subsequent DOM attribute changes made by kt_wc_set_variation_attr.
403			const largeSrc = $img.attr('data-zoom-image') || $img.attr('src');
404
405			if ($activeSlide.data('imagezoom')) {
406				$activeSlide.data('imagezoom').destroy();
407			}
408			if (!largeSrc) { return; }
409
410			// Disable zoom for video slides.
411			if ($activeSlide.find('.kt-woo-video-link').length) { return; }
412
413			if (typeof $.fn.ImageZoom !== 'function') { return; }
414
415			$activeSlide.ImageZoom({
416				type: type,
417				bigImageSrc: largeSrc,
418				zoomSize: [kadence_pg.zoom_lens_width, kadence_pg.zoom_lens_height],
419				zoomViewerClass: type === 'follow'
420					? 'shape' + (kadence_pg.zoom_shape || 'circular')
421					: 'shapesquare',
422				position: kadence_pg.zoom_position || 'right',
423				preload: false,
424				showDescription: false,
425				hoverIntent:     type === 'follow' && typeof $.fn.hoverIntent === 'function',
426				onShow() {
427					self.$gallery.addClass( 'kt-zoom-hovering' );
428				},
429				onHide() {
430					self.$gallery.removeClass( 'kt-zoom-hovering' );
431				},
432			});
433		};
434		if (
435			$zoom &&
436			!KadenceProductGalleryisMobile.any() &&
437			$(window).width() > 790
438		) {
439			splideMain.on("move", function () {
440				const $activeSlide = self.$gallery.find('.splide__slide.is-active');
441				if ($activeSlide.data('imagezoom')) {
442					$activeSlide.data('imagezoom').destroy();
443				}
444			});
445			splideMain.on("moved", function () {
446				setTimeout(function () {
447					self.init_product_zoom();
448				}, 100);
449			});
450			var ktwoozoomresizeTimer;
451			$(window).on("resize", function () {
452				clearTimeout(ktwoozoomresizeTimer);
453				ktwoozoomresizeTimer = setTimeout(self.init_product_zoom, 200);
454			});
455			self.init_product_zoom();
456		}
457		self.init_product_lightbox = () => {
458			if (kadence_pg.lightbox) {
459				var plyrConfig = { hideControls: true };
460
461				// Controls visibility
462				if (!kadence_pg.video_controls) {
463					plyrConfig.controls = [];
464				} else if (kadence_pg.video_controls_list && kadence_pg.video_controls_list.length) {
465					plyrConfig.controls = kadence_pg.video_controls_list;
466				}
467
468				// Loop
469				if (kadence_pg.video_loop !== undefined) {
470					plyrConfig.loop = { active: kadence_pg.video_loop };
471				}
472
473				return GLightbox({
474					selector: "#pg-main-" + product_id + ' a[data-rel^="lightbox"]:not([target="_blank"])',
475					touchNavigation: true,
476					skin: kadence_pg.lightbox_style,
477					loop: true,
478					openEffect: "fade",
479					closeEffect: "fade",
480					autoplayVideos: kadence_pg.video_autoplay !== undefined ? kadence_pg.video_auto
480play : true,
481					afterSlideLoad: function (slideData) {
482						var videoEl = slideData.slide.querySelector('video.gvideo-local');
483						if (videoEl) {
484							if (kadence_pg.video_poster) {
485								var anchors = document.querySelectorAll('#pg-main-' + product_id + ' a[data-rel^="lightbox"]:not([target="_blank"])');
486								var anchor = anchors[slideData.index];
487								var posterUrl = anchor ? anchor.getAttribute('data-poster') : null;
488								if (posterUrl) {
489									if (slideData.player) {
490										slideData.player.poster = posterUrl;
491									} else {
492										videoEl.poster = posterUrl;
493									}
494								}
495							}
496							if (kadence_pg.video_lazyload) {
497								videoEl.preload = 'none';
498							}
499						}
500					},
501					plyr: {
502						css: kadence_pg.plyr_css,
503						js: kadence_pg.plyr_js,
504						config: plyrConfig,
505					},
506				});
507			}
508		};
509		var glightbox = self.init_product_lightbox();
510		if (kadence_pg.lightbox && !kadence_pg.lightbox_click_anywhere) {
511			$gallery.addClass('kt-no-click-lightbox');
512		}
513		self.reload_product_lightbox = () => {
514			if (kadence_pg.lightbox) {
515				if (glightbox) {
516					glightbox.reload();
517				}
518			}
519		};
520		$(".variations_form")
521			.find(".single_variation")
522			.on("show_variation", function (event, variation, purchasable) {
523				var $product_img_wrap = self.$gallery.find(
524					".woocommerce-main-image"
525				);
526				var $product_img = kadence_pg.lightbox
527					? $product_img_wrap.find("img")
528					: self.$gallery.find(".woo-main-slide img");
529				var $product_thumb_wrap = self.$galleryThumbnails.find(
530					".woocommerce-main-image-thumb"
531				);
532				var $product_thumb_img = $product_thumb_wrap.find("img");
533				// Change zoom image
534				if (
535					variation &&
536					variation.image.src &&
537					variation.image.src.length > 1
538				) {
539					// See if the gallery has an image with the same original src as the image we want to switch to.
540					var galleryHasImage =
541						self.$gallery.find(
542							'.splide__slide img[data-o_src="' +
543							variation.image.src +
544							'"]'
545						).length > 0;
546					// If the gallery has the image, reset the images. We'll scroll to the correct one.
547					if (galleryHasImage) {
548						self.kt_wc_variations_image_reset();
549					}
550					// See if gallery has a matching image we can slide to.
551					var gal_non_retina =
552						variation.image.gallery_thumbnail_src.replace(
553							variation.image.gallery_thumbnail_src_w +
554							"x" +
555							variation.image.gallery_thumbnail_src_h,
556							Math.floor(
557								variation.image.gallery_thumbnail_src_w / 2
558							) +
559							"x" +
560							Math.floor(
561								variation.image.gallery_thumbnail_src_h / 2
562							)
563						);
564					var slideToImage = self.$galleryThumbnails.find(
565						'.splide__slide img[src="' + gal_non_retina + '"]'
566					);
567					if (slideToImage.length == 0) {
568						slideToImage = self.$galleryThumbnails.find(
569							'.splide__slide img[src="' +
570							variation.image.gallery_thumbnail_src +
571							'"]'
572						);
573					}
574
575					if (slideToImage.length > 0 && !$datathumbs) {
576						//var galIndex = slideToImage.parent().data( 'slick-index' ) .trigger( 'click' );
577						slideToImage.parent().trigger("click");
578						if (
579							self.$gallery.data("zoom-active") &&
580							!KadenceProductGalleryisMobile.any()
581						) {
582							self.init_product_zoom();
583						}
584						return;
585					}
586
587					var slideCount = splideMain.length;
588					var currentIndex = splideMain.index;
589
590					$product_img.kt_wc_set_variation_attr(
591						"data-zoom-image",
592						variation.image.full_src
593					);
594					$product_img.kt_wc_set_variation_attr(
595						"src",
596						variation.image.src
597					);
598					if (variation.image.srcset) {
599						$product_img.kt_wc_set_variation_attr(
600							"srcset",
601							variation.image.srcset
602						);
603					} else {
604						$product_img.kt_wc_set_variation_attr("srcset", "");
605					}
606					if (variation.image.title) {
607						$product_img.kt_wc_set_variation_attr(
608							"title",
609							variation.image.title
610						);
611					} else {
612						$product_img.kt_wc_set_variation_attr("title", "");
613					}
614					if (variation.image.caption) {
615						$product_img.kt_wc_set_variation_attr(
616							"data-caption",
617							variation.image.caption
618						);
619					} else {
620						$product_img.kt_wc_set_variation_attr(
621							"data-caption",
622							""
623						);
624					}
625					if (visible_captions === true) {
626						if (variation.image.caption) {
627							$product_img_wrap
628								.find(".sp-gal-image-caption")
629								.html(variation.image.caption);
630							$product_img_wrap
631								.find(".sp-gal-image-caption")
632								.fadeIn();
633						} else {
634							$product_img_wrap
635								.find(".sp-gal-image-caption")
636								.fadeOut();
637						}
638					}
639					if ($product_img_wrap.hasClass("kt-woo-video-link")) {
640						$product_img_wrap.find(".kt-woo-play-btn").hide();
641						$product_thumb_wrap.find(".kt-woo-play-btn").hide();
642						$product_img_wrap.removeClass("kt-woo-video-link");
643						$product_img_wrap.addClass("kt-woo-orig-video-link");
644					}
645					$product_img.kt_wc_set_variation_attr(
646						"alt",
647						variation.image.alt
648					);
649					$product_img_wrap.kt_wc_set_variation_attr(
650						"href",
651						variation.image.full_src
652					);
653					$product_thumb_img.kt_wc_set_variation_attr(
654						"src",
655						variation.image.gallery_thumbnail_src
656					);
657					if (variation.image.gallery_thumbnail_srcset) {
658						$product_thumb_img.kt_wc_set_variation_attr(
659							"srcset",
660							variation.image.gallery_thumbnail_srcset
661						);
662					} else {
663						$product_thumb_img.kt_wc_set_variation_attr(
664							"srcset",
665							""
666						);
667					}
668					$product_thumb_img.kt_wc_set_variation_attr(
669						"alt",
670						variation.image.alt
671					);
672					if ($datathumbs) {
673						var aiSlidesForVariation =
674							Object.keys(self.attributeImages.data).length
675								? self.attributeImages.getSelectedSlides()
676								: null;
677						if ($datathumbs["is_ajax"]) {
678							self.kt_wc_variations_run_ajax_call(
679								variation.variation_id,
680								aiSlidesForVariation
681							);
682						} else {
683							self.kt_wc_variations_run_thumbnails(
684								variation.variation_id
685							);
686							if (aiSlidesForVariation) {
687								self.attributeImages.append(
688									aiSlidesForVariation
689								);
690							}
691						}
692					} else if (Object.keys(self.attributeImages.data).length) {
693						// No variation gallery — attribute images were already applied
694						// by the change handler, but if galleryHasImage triggered a
695						// reset above we need to re-append them now.
696						var attrSlidesAfterReset =
697							self.attributeImages.getSelectedSlides();
698						if (attrSlidesAfterReset) {
699							self.attributeImages.append(attrSlidesAfterReset);
700						}
701					}
702					splideMain.refresh();
703					if (
704						self.$gallery.data("zoom-active") &&
705						!KadenceProductGalleryisMobile.any()
706					) {
707						self.init_product_zoom();
708					}
709					self.reload_product_lightbox();
710				} else {
711					self.kt_wc_variations_image_reset();
712				}
713
714				if (1 < slideCount) {
715					splideMain.go(maintain_slide_index ? currentIndex : 0);
716				}
717			});
718		self.kt_wc_variations_original_thumbnails = () => {
719			if (thumbnails_have_changed) {
720				splideMain.remove(".splide__slide:not(.woo-main-slide)");
721				splideMain.add($datathumbs["original"]["images"]);
722				items_count = original_items_count;
723				if (thumbnails) {
724					thumbnails.remove(
725						".splide__slide:not(.woocommerce-main-image-thumb)"
726					);
727					self.$galleryThumbnails.css("height", "auto");
728					if (
729						items_count < current_thumbs_show &&
730						current_layout !== "left" &&
731						current_layout !== "right"
732					) {
733						thumbnails.options.perPage = items_count;
734					} else if (
735						thumbnails.options.perPage < current_thumbs_show
736					) {
737						thumbnails.options.perPage = current_thumbs_show;
738						if (splide_thumbs_center) {
739							thumbnails.options.focus =
740								(current_layout !== "left" &&
741									current_layout !== "right") ||
742									(items_count > current_thumbs_show &&
743										(current_layout === "left" ||
744											current_layout === "right"))
745									? "center"
746									: undefined;
747						}
748					} else if (
749						thumbnails.options.perPage >= current_thumbs_show
750					) {
751						if (splide_thumbs_center) {
752							thumbnails.options.focus =
753								(current_layout !== "left" &&
754									current_layout !== "right") ||
755									(items_count > current_thumbs_show &&
756										(current_layout === "left" ||
757											current_layout === "right"))
758									? "center"
759									: undefined;
760						}
761					}
762					thumbnails.add($datathumbs["original"]["thumbnails"]);
763					if (splide_thumbs_on_hover) {
764						self.galleryUpdateThumbHover();
765					}
766				}
767				self.clear_slide_layout(
768					current_layout,
769					current_thumb_width,
770					current_thumbs_show,
771					original_items_count
772				);
773				self.reload_product_lightbox();
774				thumbnails_have_changed = false;
775			}
776		};
777		self.kt_wc_variations_run_thumbnails = (variation_id) => {
778			if (!$datathumbs[variation_id] || !$datathumbs[variation_id].images) {
779				self.kt_wc_variations_original_thumbnails();
780			} else {
781				self.kt_wc_variations_switch_thumbnails(
782					$datathumbs[variation_id]
783				);
784			}
785		};
786		self.kt_wc_variations_switch_thumbnails = (thumbnails_data) => {
787			if (
788				!thumbnails_data ||
789				!thumbnails_data.images ||
790				!thumbnails_data.thumbnails
791			) {
792				self.kt_wc_variations_original_thumbnails();
793				return;
794			}
795			thumbnails_have_changed = true;
796			var switchIndex = maintain_slide_index ? splideMain.index : 0;
797			splideMain.remove(".splide__slide:not(.woo-main-slide)");
798			splideMain.add(thumbnails_data["images"]);
799			items_count = thumbnails_data["thumbnails"].length + 1;
800			if (thumbnails) {
801				thumbnails.remove(
802					".splide__slide:not(.woocommerce-main-image-thumb)"
803				);
804				self.$galleryThumbnails.css("height", "auto");
805				if (
806					items_count < current_thumbs_show &&
807					current_layout !== "left" &&
808					current_layout !== "right"
809				) {
810					thumbnails.options.perPage = items_count;
811				} else if (thumbnails.options.perPage < current_thumbs_show) {
812					thumbnails.options.perPage = current_thumbs_show;
813					if (splide_thumbs_center) {
814						thumbnails.options.focus =
815							(current_layout !== "left" &&
816								current_layout !== "right") ||
817								(items_count > current_thumbs_show &&
818									(current_layout === "left" ||
819										current_layout === "right"))
820								? "center"
821								: undefined;
822					}
823				} else if (thumbnails.options.perPage >= current_thumbs_show) {
824					if (splide_thumbs_center) {
825						thumbnails.options.focus =
826							(current_layout !== "left" &&
827								current_layout !== "right") ||
828								(items_count > current_thumbs_show &&
829									(current_layout === "left" ||
830										current_layout === "right"))
831								? "center"
832								: undefined;
833					}
834				}
835				thumbnails.add(thumbnails_data["thumbnails"]);
836				if (splide_thumbs_on_hover) {
837					self.galleryUpdateThumbHover();
838				}
839			}
840			if (maintain_slide_index && switchIndex > 0) {
841				splideMain.go(switchIndex);
842			}
843			self.clear_slide_layout(
844				current_layout,
845				current_thumb_width,
846				current_thumbs_show,
847				items_count
848			);
849			self.reload_product_lightbox();
850		};
851		self.kt_wc_variations_run_ajax_call = (variation_id, aiSlides) => {
852			var $data = {
853				action: "kadence_variation_images_load_frontend_ajax",
854				ajaxkwsvNonce: kadence_pg.ajax_nonce,
855				variation_id: variation_id,
856				post_id: product_id,
857			};
858			$.post(kadence_pg.ajax_url, $data, function (response) {
859				if (response.length) {
860					response = JSON.parse(response);
861					// replace with new image set
862					self.kt_wc_variations_switch_thumbnails(response);
863				} else {
864					// replace with original image set
865					self.kt_wc_variations_original_thumbnails();
866				}
867				// Append attribute images on top of whatever was just applied.
868				if (aiSlides) {
869					self.attributeImages.append(aiSlides);
870				}
871
872				if (!maintain_slide_index && 1 < splideMain.length) {
873					splideMain.go(0);
874				}
875			});
876		};
877		self.kt_wc_variations_image_reset = () => {
878			var $product_img_wrap = self.$gallery.find(
879				".woocommerce-main-image"
880			);
881			var $product_img = kadence_pg.lightbox
882				? $product_img_wrap.find("img")
883				: self.$gallery.find(".woo-main-slide img");
884			var $product_thumb_wrap = self.$galleryThumbnails.find(
885				".woocommerce-main-image-thumb"
886			);
887			var $product_thumb_img = $product_thumb_wrap.find("img");
888			$product_img.kt_wc_reset_variation_attr("src");
889			$product_img.kt_wc_reset_variation_attr("srcset");
890			$product_img.kt_wc_reset_variation_attr("data-caption");
891			$product_img.kt_wc_reset_variation_attr("alt");
892			if (visible_captions === true) {
893				if (undefined !== $product_img.attr("data-o_data-caption")) {
894					$product_img_wrap
895						.find(".sp-gal-image-caption")
896						.html($product_img.attr("data-o_data-caption"));
897					$product_img_wrap.find(".sp-gal-image-caption").fadeIn();
898				} else {
899					$product_img_wrap.find(".sp-gal-image-caption").fadeOut();
900				}
901			}
902			if ($product_img_wrap.hasClass("kt-woo-orig-video-link")) {
903				$product_img_wrap.addClass("kt-woo-video-link");
904				$product_img_wrap.find(".kt-woo-play-btn").show();
905				$product_thumb_wrap.find(".kt-woo-play-btn").show();
906				$product_img_wrap.removeClass("kt-woo-orig-video-link");
907			}
908			$product_img.kt_wc_reset_variation_attr("title");
909			$product_img.kt_wc_reset_variation_attr("data-zoom-image");
910			$product_thumb_img.kt_wc_reset_variation_attr("src");
911			$product_thumb_img.kt_wc_reset_variation_attr("srcset");
912			$product_thumb_img.kt_wc_reset_variation_attr("alt");
913			$product_img_wrap.kt_wc_reset_variation_attr("href");
914			self.kt_wc_variations_original_thumbnails();
915			if (
916				self.$gallery.data("zoom-active") &&
917				!KadenceProductGalleryisMobile.any()
918			) {
919				var slideCount = splideMain.length;
920				if (1 < slideCount) {
921					splideMain.go(0);
922				}
923				self.init_product_zoom();
924			}
925			splideMain.refresh();
926			self.reload_product_lightbox();
927		};
928		$.fn.kt_wc_set_variation_attr = function (attr, value) {
929			if (undefined === this.attr("data-o_" + attr)) {
930				this.attr(
931					"data-o_" + attr,
932					!this.attr(attr) ? "" : this.attr(attr)
933				);
934			}
935			this.attr(attr, value);
936		};
937		$.fn.kt_wc_reset_variation_attr = function (attr) {
938			if (undefined !== this.attr("data-o_" + attr)) {
939				this.attr(attr, this.attr("data-o_" + attr));
940			}
941		};
942		$gallery.find(".kt-gallery-fullscreen-btn").on("click", function () {
943			var activeLink = $gallery
944				.find(".splide__slide.is-active a[data-rel^='lightbox']")
945				.get(0);
946			if (activeLink) {
947				activeLink.click();
948			}
949		});
950
951		$(".variations_form").on("click", ".reset_variations", function () {
952			self.kt_wc_variations_image_reset();
953		});
954
955		// Attribute Images — encapsulated object for managing attribute-based
956		// gallery images. Pre-rendered slide data is output by class-attribute-images.php
957		// as window.kadence_attribute_images_data and consumed here.
958		self.attributeImages = {
959			data: {},
960
961			init: function () {
962				this.data =
963					"undefined" !== typeof window.kadence_attribute_images_data
964						? window.kadence_attribute_images_data
965						: {};
966				this.bindEvents();
967			},
968
969			/**
970			 * Build the combined attribute-image slide data for the currently
971			 * selected attribute values. Returns null when nothing matches.
972			 *
973			 * @return {{ images: string[], thumbnails: string[] }|null}
974			 */
975			getSelectedSlides: function () {
976				if (!Object.keys(this.data).length) {
977					return null;
978				}
979
980				var selectedAttributes = {};
981				$(".variations_form")
982					.filter(":visible")
983					.find("select[name^='attribute_']")
984					.each(function () {
985						var val = $(this).val();
986						if (val) {
987							selectedAttributes[$(this).attr("id")] = val;
988						}
989					});
990
991				var combinedImages = [];
992				var combinedThumbnails = [];
993				var data = this.data;
994
995				for (var attr in selectedAttributes) {
996					if (
997						Object.prototype.hasOwnProperty.call(selectedAttributes, attr)
998					) {
999						var termSlug = selectedAttributes[attr];
1000						if (data[attr]) {
1001							if (data[attr][termSlug]) {
1002								combinedImages = combinedImages.concat(
1003									data[attr][termSlug].images
1004								);
1005								combinedThumbnails = combinedThumbnails.concat(
1006									data[attr][termSlug].thumbnails
1007								);
1008							}
1009							if (data[attr]["any"]) {
1010								combinedImages = combinedImages.concat(
1011									data[attr]["any"].images
1012								);
1013								combinedThumbnails = combinedThumbnails.concat(
1014									data[attr]["any"].thumbnails
1015								);
1016							}
1017						}
1018					}
1019				}
1020
1021				if (data["all"] && data["all"]["all"]) {
1022					combinedImages = combinedImages.concat(
1023						data["all"]["all"].images
1024					);
1025					combinedThumbnails = combinedThumbnails.concat(
1026						data["all"]["all"].thumbnails
1027					);
1028				}
1029
1030				if (!combinedImages.length) {
1031					return null;
1032				}
1033
1034				// Optionally append the parent gallery when maintain_gallery = 1.
1035				var maintainGallery = parseInt(
1036					(kadence_pg && kadence_pg.maintain_gallery) || "0"
1037				);
1038				if (
1039					maintainGallery === 1 &&
1040					$datathumbs &&
1041					$datathumbs["original"]
1042				) {
1043					combinedImages = combinedImages.concat(
1044						$datathumbs["original"].images
1045					);
1046					combinedThumbnails = combinedThumbnails.concat(
1047						$datathumbs["original"].thumbnails
1048					);
1049				}
1050
1051				return { images: combinedImages, thumbnails: combinedThumbnails };
1052			},
1053
1054			/**
1055			 * Append attribute-image slides to whatever is currently in the gallery
1056			 * without replacing existing slides.  Used after variation gallery images
1057			 * have already been applied by kt_wc_variations_switch_thumbnails.
1058			 *
1059			 * @param {{ images: string[], thumbnails: string[] }} attrSlides
1060			 */
1061			append: function (attrSlides) {
1062				if (!attrSlides || !attrSlides.images || !attrSlides.images.length) {
1063					return;
1064				}
1065				thumbnails_have_changed = true;
1066				splideMain.add(attrSlides.images);
1067				items_count = splideMain.length;
1068				if (thumbnails) {
1069					self.$galleryThumbnails.css("height", "auto");
1070					thumbnails.add(attrSlides.thumbnails);
1071					if (
1072						items_count < current_thumbs_show &&
1073						current_layout !== "left" &&
1074						current_layout !== "right"
1075					) {
1076						thumbnails.options.perPage = items_count;
1077					} else if (thumbnails.options.perPage < current_thumbs_show) {
1078						thumbnails.options.perPage = current_thumbs_show;
1079					}
1080					if (splide_thumbs_on_hover) {
1081						self.galleryUpdateThumbHover();
1082					}
1083				}
1084				self.clear_slide_layout(
1085					current_layout,
1086					current_thumb_width,
1087					current_thumbs_show,
1088					items_count
1089				);
1090				self.reload_product_lightbox();
1091			},
1092
1093			// Bind the attribute change handler (fires before show_variation).
1094			bindEvents: function () {
1095				if (!Object.keys(this.data).length) {
1096					return;
1097				}
1098				$(".variations_form").on(
1099					"change",
1100					"select[name^='attribute_']",
1101					function () {
1102						var attrSlides = self.attributeImages.getSelectedSlides();
1103						if (attrSlides) {
1104							self.kt_wc_variations_switch_thumbnails(attrSlides);
1105						} else {
1106							self.kt_wc_variations_original_thumbnails();
1107						}
1108					}
1109				);
1110			},
1111		};
1112
1113		self.attributeImages.init();
1114	};
1115	/**
1116	 * Function to call kt_wc_product_gallery on jquery selector.
1117	 */
1118	$.fn.kt_wc_product_gallery = function () {
1119		var $gallery = this;
1120		if (!$gallery.hasClass("splide-initial")) {
1121			if (typeof Splide === "function") {
1122				new KadenceProductGallery($gallery);
1123			} else {
1124				// eslint-disable-next-line vars-on-top
1125				var initLoadDelay = setInterval(function () {
1126					if (typeof Splide === "function") {
1127						new KadenceProductGallery($gallery);
1128						clearInterval(initLoadDelay);
1129					}
1130				}, 200);
1131			}
1132		}
1133		return this;
1134	};
1135
1136	/*
1137	 * Initialize all galleries on page.
1138	 */
1139	window.initKaenceProductGalleries = () => {
1140		$(".kadence-ga-splide-init").each(function () {
1141			$(this).kt_wc_product_gallery();
1142		});
1143	};
1144
1145	window.initKaenceProductGalleries();
1146
1147	document.addEventListener("kb-query-loaded", function () {
1148		window.initKaenceProductGalleries();
1149	});
1150	document.addEventListener("kt-quickview-load", function () {
1151		window.initKaenceProductGalleries();
1152	});
1153
1154	// Todo: Make this more generic so it can be used for other buttons as well.
1155	// Icon tooltips for gallery action buttons.
1156	(function () {
1157		var $tooltip = $('<div class="kt-gallery-icon-tooltip"></div>').appendTo('body');
1158
1159		$(document)
1160			.on('mouseenter', '.kt-icons-tooltips .kt-gallery-fullscreen-btn, .kt-icons-tooltips .kt-gallery-video-btn', function () {
1161				var $btn = $(this);
1162				var text = $btn.data('tooltip');
1163				if (!text) { return; }
1164
1165				$tooltip.text(text);
1166
1167				var offset = $btn.offset();
1168				var tipWidth = $tooltip.outerWidth();
1169				var tipHeight = $tooltip.outerHeight();
1170				var btnWidth = $btn.outerWidth();
1171
1172				$tooltip.css({
1173					left: offset.left + (btnWidth / 2) - (tipWidth / 2),
1174					top: offset.top - tipHeight - 5  // 10 = 5px arrow height + 5px gap
1175				}).addClass('kt-gallery-icon-tooltip--visible');
1176			})
1177			.on('mouseleave', '.kt-icons-tooltips .kt-gallery-fullscreen-btn, .kt-icons-tooltips .kt-gallery-video-btn', function () {
1178				$tooltip.removeClass('kt-gallery-icon-tooltip--visible');
1179			});
1180	}());
1181});

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.