PageSourceSearch

https://inhouseproduction.co/store/wp-content/themes/woostify/assets/js/photoswipe-init.min.js?ver=2.5.2

js inhouseproduction.co collected 2026-09-25 03:34:57 UTC 11,883 bytes, 457 lines download raw bytes

1/**
2 * Photo Swipe on Product Images
3 *
4 * @package woostify
5 */
6
7'use strict';
8
9function initPhotoSwipe(gallerySelector) {
10	var added = false;
11
12	// Helper function to extract YouTube video ID
13	var getYoutubeId = function (url) {
14		var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|shorts\/)([^#\&\?]*).*/;
15		var match = url.match(regExp);
16		if (match && match[2].length == 11) {
17			return match[2];
18		} else {
19			return null;
20		}
21	};
22
23	// parse slide data (url, title, size ...) from DOM elements
24	// (children of gallerySelector).
25	var parseThumbnailElements = function (el) {
26		var thumbElements = el.childNodes,
27			numNodes = thumbElements.length,
28			items = [],
29			figureEl,
30			linkEl,
31			size,
32			item;
33
34		for (var i = 0; i < numNodes; i++) {
35
36			figureEl = thumbElements[i]; // <figure> element.
37
38			// include only element nodes.
39			if (1 !== figureEl.nodeType) {
40				continue;
41			}
42
43			// Check if this is a video item
44			var isVideo = figureEl.classList.contains('has-video');
45			var videoSource = figureEl.getAttribute('data-video-source');
46			var videoUrl = figureEl.getAttribute('data-video-url');
47			var videoAutoplay = figureEl.getAttribute('data-video-autoplay');
48			var videoMute = figureEl.getAttribute('data-video-mute');
49
50			linkEl = figureEl.children[0]; // <a> element.
51			if (!linkEl.getAttribute('href') && !isVideo) {
52				continue;
53			}
54
55			if (isVideo && videoUrl) {
56				// Video item
57				item = {
58					html: '', // Will be populated dynamically
59					w: 1280,
60					h: 720,
61					isVideo: true,
62					videoSource: videoSource || 'youtube',
63					videoUrl: videoUrl,
64					videoAutoplay: videoAutoplay,
65					videoMute: videoMute
66				};
67
68				if (linkEl.children.length > 0) {
69					item.msrc = linkEl.children[0].getAttribute('src');
70				}
71			} else {
72				// Image item
73				size = linkEl.getAttribute('data-size').split('x');
74
75				item = {
76					src: linkEl.getAttribute('href'),
77					w: parseInt(size[0], 10),
78					h: parseInt(size[1], 10)
79				};
80
81				if (linkEl.children.length > 0) {
82					item.msrc = linkEl.children[0].getAttribute('src');
83				}
84			}
85
86			item.el = figureEl; // save link to element for getThumbBoundsFn.
87			items.push(item);
88		}
89
90		return items;
91	};
92
93	// find nearest parent element.
94	var closest = function closest(el, fn) {
95		return el && (fn(el) ? el : closest(el.parentNode, fn));
96	};
97
98	var onToggleButtonClick = function (e) {
99		e = e || window.event;
100		e.preventDefault ? e.preventDefault() : e.returnValue = false;
101
102		var eTarget = e.target || e.srcElement;
103
104		var productImages = eTarget.closest('.product-images');
105
106		var clickedListItem = productImages.querySelectorAll('.image-item')[0];
107
108		// find root element of slide.
109		var slider = productImages.querySelector('.flickity-slider');
110		if (slider) {
111			clickedListItem = productImages.querySelector('.image-item.is-selected');
112		}
113
114		if (!clickedListItem) {
115			return;
116		}
117
118		// find index of clicked item by looping through all child nodes
119		// alternatively, you may define index via data- attribute.
120		var clickedGallery = clickedListItem.parentNode,
121			childNodes = clickedListItem.parentNode.childNodes,
122			numChildNodes = childNodes.length,
123			nodeIndex = 0,
124			index;
125
126		for (var i = 0; i < numChildNodes; i++) {
127			if (childNodes[i].nodeType !== 1) {
128				continue;
129			}
130
131			if (childNodes[i] === clickedListItem) {
132				index = nodeIndex;
133				break;
134			}
135			nodeIndex++;
136		}
137
138		if (index >= 0) {
139			// open PhotoSwipe if valid index found.
140			openPhotoSwipe(index, clickedGallery);
141		}
142		return false;
143	}
144
145	// triggers when user clicks on thumbnail.
146	var onThumbnailsClick = function (e) {
147		e = e || window.event;
148		e.preventDefault ? e.preventDefault() : e.returnValue = false;
149
150		var eTarget = e.target || e.srcElement;
151
152		if ('A' === eTarget.tagName.toUpperCase()) {
153			return;
154		}
155
156		// find root element of slide.
157		var clickedListItem = closest(
158			eTarget,
159			function (el) {
160				return (el.tagName && 'FIGURE' === el.tagName.toUpperCase());
161			}
162		);
163
164		if (!clickedListItem) {
165			return;
166		}
167
168		// find index of clicked item by looping through all child nodes
169		// alternatively, you may define index via data- attribute.
170		var clickedGallery = clickedListItem.parentNode,
171			childNodes = clickedListItem.parentNode.childNodes,
172			numChildNodes = childNodes.length,
173			nodeIndex = 0,
174			index;
175
176		for (var i = 0; i < numChildNodes; i++) {
177			if (childNodes[i].nodeType !== 1) {
178				continue;
179			}
180
181			if (childNodes[i] === clickedListItem) {
182				index = nodeIndex;
183				break;
184			}
185			nodeIndex++;
186		}
187
188		if (index >= 0) {
189			// open PhotoSwipe if valid index found.
190			openPhotoSwipe(index, clickedGallery);
191		}
192		return false;
193	};
194
195	var openPhotoSwipe = function (index, galleryElement, disableAnimation, fromURL) {
196		var productGallery = galleryElement.closest('.product-gallery');
197
198		var pswpElement,
199			gallery,
200			options,
201			items;
202
203		if (productGallery.querySelector('.pswp')) {
204			pswpElement = productGallery.querySelector('.pswp');
205		} else {
206			pswpElement = productGallery.nextElementSibling;
207		}
208
209		items = parseThumbnailElements(galleryElement);
210
211		// define options (if needed).
212		options = {
213
214			// define gallery index (for URL).
215			galleryUID: galleryElement.getAttribute('data-pswp-uid'),
216
217			getThumbBoundsFn: function (index) {
218				// See Options -> getThumbBoundsFn section of documentation for more info.
219				var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail.
220					pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
221					rect = thumbnail.getBoundingClientRect();
222
223				return {
224					x: rect.left,
225					y: rect.top + pageYScroll,
226					w: rect.width
227				};
228			}
229
230		};
231
232		// PhotoSwipe opened from URL.
233		if (fromURL) {
234			if (options.galleryPIDs) {
235				// parse real index when custom PIDs are used
236				// http://photoswipe.com/documentation/faq.html#custom-pid-in-url.
237				for (var j = 0, ji = items.length; j < ji; j++) {
238					if (items[j].pid == index) {
239						options.index = j;
240						break;
241					}
242				}
243			} else {
244				// in URL indexes start from 1.
245				options.index = parseInt(index, 10) - 1;
246			}
247		} else {
248			options.index = parseInt(index, 10);
249		}
250
251		// exit if index not found.
252		if (isNaN(options.index)) {
253			return;
254		}
255
256		if (disableAnimation) {
257			options.showAnimationDuration = 0;
258		}
259
260		// Pass data to PhotoSwipe and initialize it.
261		gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
262		gallery.init();
263
264		// Handle video rendering
265		gallery.listen('gettingData', function (index, item) {
266			if (item.isVideo && !item.html) {
267				var videoHtml = '';
268
269				if (item.videoSource === 'mp4') {
270					// MP4 Video
271					videoHtml = '<div class="pswp__video-container">';
272					videoHtml += '<video controls autoplay';
273
274					if (item.videoMute == 1 || item.videoAutoplay == 1) {
275						videoHtml += ' muted';
276					}
277
278					videoHtml += ' playsinline style="width:100%;height:100%;object-fit:contain;">';
279					videoHtml += '<source src="' + item.videoUrl + '" type="video/mp4">';
280					videoHtml += 'Your browser does not support the video tag.';
281					videoHtml += '</video>';
282					videoHtml += '</div>';
283				} else {
284					// YouTube Video
285					var videoId = getYoutubeId(item.videoUrl);
286					if (videoId) {
287						var embedUrl = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&rel=0&enablejsapi=1';
288
289						if (item.videoMute == 1 || item.videoAutoplay == 1) {
290							embedUrl += '&mute=1';
291						}
292
293						videoHtml = '<div class="pswp__video-container">';
294						videoHtml += '<iframe src="' + embedUrl + '" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen style="width:100%;height:100%;"></iframe>';
295						videoHtml += '</div>';
296					}
297				}
298
299				item.html = videoHtml;
300			}
301		});
302
303		var selector = '.pswp__thumbnails';
304
305		gallery.listen(
306			'gettingData',
307			function () {
308				if (added) {
309					return;
310				}
311				added = true;
312
313				var oldThumbnailEls = document.querySelectorAll(selector);
314				if (oldThumbnailEls.length) {
315					oldThumbnailEls.forEach(
316						function (odlThumb) {
317							odlThumb.remove();
318						}
319					)
320				}
321				setTimeout(
322					function () {
323						addPreviews(gallery);
324					},
325					200
326				);
327			}
328		)
329
330		gallery.listen(
331			'close',
332			function () {
333				var scrollWrap = gallery.scrollWrap;
334				var pswpThumbEl = scrollWrap.closest('.pswp').querySelector('.pswp__thumbnails');
335
336				// Stop all videos when closing lightbox
337				var videos = scrollWrap.querySelectorAll('video');
338				for (var i = 0; i < videos.length; i++) {
339					videos[i].pause();
340				}
341
342				var iframes = scrollWrap.querySelectorAll('iframe');
343				for (var j = 0; j < iframes.length; j++) {
344					iframes[j].src = '';
345				}
346
347				if (!pswpThumbEl) {
348					return;
349				}
350
351				pswpThumbEl.remove();
352				added = false;
353			}
354		)
355		gallery.listen(
356			'afterChange',
357			function () {
358				var scrollWrap = gallery.scrollWrap;
359				var pswpThumbEl = scrollWrap.closest('.pswp').querySelector('.pswp__thumbnails');
360
361				if (!pswpThumbEl) {
362					return;
363				}
364
365				Object.keys(gallery.items).forEach(
366					function (k) {
367						var currThumbItem = pswpThumbEl.children[k];
368
369						currThumbItem.classList.remove('active');
370
371						if (gallery.getCurrentIndex() == k) {
372							currThumbItem.classList.add('active');
373						}
374					}
375				)
376			}
377		)
378	};
379
380	function addPreviews(gallery) {
381		var scrollWrap = gallery.scrollWrap;
382		var productImagesWrapperEl = document.querySelector('.product-gallery');
383		var thumbnailEl = document.createElement('div');
384		thumbnailEl.classList.add('pswp__thumbnails');
385
386		if (!productImagesWrapperEl) {
387			return;
388		}
389
390		var productThumbWrapperEl = productImagesWrapperEl.querySelector('.product-thumbnail-images-container');
391
392		if (!productThumbWrapperEl) {
393			Object.keys(gallery.items).forEach(
394				function (k) {
395					var currItem = gallery.items[k];
396					var newThumbEl = document.createElement('div');
397					var newImgEl = document.createElement('img');
398
399					newImgEl.setAttribute('src', currItem.msrc);
400					newThumbEl.classList.add('thumbnail-item');
401					newThumbEl.appendChild(newImgEl)
402					thumbnailEl.appendChild(newThumbEl);
403				}
404			)
405		} else {
406			var thumbSlider = productThumbWrapperEl.querySelector('.flickity-slider');
407			if (thumbSlider) {
408				thumbnailEl.innerHTML = thumbSlider.innerHTML;
409			} else {
410				thumbnailEl.innerHTML = productThumbWrapperEl.innerHTML;
411			}
412		}
413
414		Object.keys(gallery.items).forEach(
415			function (k) {
416				var currThumbItem = thumbnailEl.children[k];
417				currThumbItem.removeAttribute('style');
418				currThumbItem.classList.remove('is-selected', 'is-nav-selected');
419
420				if (gallery.getCurrentIndex() == k) {
421					currThumbItem.classList.add('active');
422				}
423
424				// Add play icon for video items
425				if (gallery.items[k].isVideo) {
426					currThumbItem.classList.add('has-video-thumb');
427					var playIcon = document.createElement('div');
428					playIcon.className = 'pswp__thumb-play-icon';
429					playIcon.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M8 5v14l11-7z" fill="currentColor"/></svg>';
430					currThumbItem.appendChild(playIcon);
431				}
432
433				currThumbItem.addEventListener(
434					'click',
435					function () {
436						gallery.goTo(gallery.items.indexOf(gallery.items[k]))
437					}
438				)
439			}
440		)
441
442		scrollWrap.parentNode.insertBefore(thumbnailEl, scrollWrap.nextSibling);
443	}
444
445	// loop through all gallery elements and bind events.
446	var galleryElements = document.querySelectorAll(gallerySelector);
447	for (var i = 0, l = galleryElements.length; i < l; i++) {
448		var buttonEl = galleryElements[i].closest('.product-images').querySelector('.photoswipe-toggle-button');
449
450		galleryElements[i].setAttribute('data-pswp-uid', i + 1);
451
452		buttonEl.onclick = onToggleButtonClick;
453		galleryElements[i].onclick = onThumbnailsClick;
454	}
455}
456
457initPhotoSwipe('.product-images-container');

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.